Medial Code Documentation
Loading...
Searching...
No Matches
local_filesys.cc
1// Copyright by Contributors
2
3#include <dmlc/base.h>
4#include <dmlc/logging.h>
5#include <errno.h>
6extern "C" {
7#include <sys/stat.h>
8}
9#ifndef _WIN32
10extern "C" {
11#include <sys/types.h>
12#include <dirent.h>
13}
14#define stat_struct stat
15#else // _WIN32
16#include <Windows.h>
17#define stat _stat64
18#define stat_struct __stat64
19#endif // _WIN32
20
21#include "./local_filesys.h"
22
23
24namespace dmlc {
25namespace io {
27class FileStream : public SeekStream {
28 public:
29 explicit FileStream(FILE *fp, bool use_stdio)
30 : fp_(fp), use_stdio_(use_stdio) {}
31 virtual ~FileStream(void) {
32 this->Close();
33 }
34 virtual size_t Read(void *ptr, size_t size) {
35 return std::fread(ptr, 1, size, fp_);
36 }
37 virtual void Write(const void *ptr, size_t size) {
38 CHECK(std::fwrite(ptr, 1, size, fp_) == size)
39 << "FileStream.Write incomplete";
40 }
41 virtual void Seek(size_t pos) {
42#ifndef _MSC_VER
43 CHECK(!std::fseek(fp_, static_cast<long>(pos), SEEK_SET)); // NOLINT(*)
44#else // _MSC_VER
45 CHECK(!_fseeki64(fp_, pos, SEEK_SET));
46#endif // _MSC_VER
47 }
48 virtual size_t Tell(void) {
49#ifndef _MSC_VER
50 return std::ftell(fp_);
51#else // _MSC_VER
52 return _ftelli64(fp_);
53#endif // _MSC_VER
54 }
55 virtual bool AtEnd(void) const {
56 return std::feof(fp_) != 0;
57 }
58 inline void Close(void) {
59 if (fp_ != NULL && !use_stdio_) {
60 std::fclose(fp_); fp_ = NULL;
61 }
62 }
63
64 private:
65 std::FILE *fp_;
66 bool use_stdio_;
67};
68
69FileInfo LocalFileSystem::GetPathInfo(const URI &path) {
70 struct stat_struct sb;
71 FileInfo ret;
72 ret.path = path;
73 if (stat(path.name.c_str(), &sb) == -1) {
74 int errsv = errno;
75#ifndef _WIN32
76 // If lstat succeeds where stat failed, assume a problematic
77 // symlink and treat this as if it were a 0-length file.
78 if (lstat(path.name.c_str(), &sb) == 0) {
79 ret.size = 0;
80 ret.type = kFile;
81 LOG(INFO) << "LocalFileSystem.GetPathInfo: detected symlink "
82 << path.name << " error: " << strerror(errsv);
83 return ret;
84 }
85#endif // _WIN32
86 LOG(FATAL) << "LocalFileSystem.GetPathInfo: "
87 << path.name << " error: " << strerror(errsv);
88 }
89 ret.size = sb.st_size;
90
91 if ((sb.st_mode & S_IFMT) == S_IFDIR) {
92 ret.type = kDirectory;
93 } else {
94 ret.type = kFile;
95 }
96 return ret;
97}
98
99void LocalFileSystem::ListDirectory(const URI &path, std::vector<FileInfo> *out_list) {
100#ifndef _WIN32
101 DIR *dir = opendir(path.name.c_str());
102 if (dir == NULL) {
103 int errsv = errno;
104 LOG(FATAL) << "LocalFileSystem.ListDirectory " << path.str()
105 <<" error: " << strerror(errsv);
106 }
107 out_list->clear();
108 struct dirent *ent;
109 /* print all the files and directories within directory */
110 while ((ent = readdir(dir)) != NULL) {
111 if (!strcmp(ent->d_name, ".")) continue;
112 if (!strcmp(ent->d_name, "..")) continue;
113 URI pp = path;
114 if (pp.name[pp.name.length() - 1] != '/') {
115 pp.name += '/';
116 }
117 pp.name += ent->d_name;
118 out_list->push_back(GetPathInfo(pp));
119 }
120 closedir(dir);
121#else // _WIN32
122 WIN32_FIND_DATA fd;
123 std::string pattern = path.name + "/*";
124 HANDLE handle = FindFirstFile(pattern.c_str(), &fd);
125 if (handle == INVALID_HANDLE_VALUE) {
126 int errsv = GetLastError();
127 LOG(FATAL) << "LocalFileSystem.ListDirectory " << path.str()
128 << " error: " << strerror(errsv);
129 }
130 do {
131 if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) {
132 URI pp = path;
133 char clast = pp.name[pp.name.length() - 1];
134 if (pp.name == ".") {
135 pp.name = fd.cFileName;
136 } else if (clast != '/' && clast != '\\') {
137 pp.name += '/';
138 pp.name += fd.cFileName;
139 }
140 out_list->push_back(GetPathInfo(pp));
141 }
142 } while (FindNextFile(handle, &fd));
143 FindClose(handle);
144#endif // _WIN32
145}
146
148 const char* const mode,
149 bool allow_null) {
150 bool use_stdio = false;
151 FILE *fp = NULL;
152#ifdef _WIN32
153 const int fname_length = MultiByteToWideChar(CP_UTF8, 0, path.name.c_str(), -1, nullptr, 0);
154 CHECK(fname_length > 0) << " LocalFileSystem::Open \"" << path.str()
155 << "\": " << "Invalid character sequence.";
156 std::wstring fname(fname_length, 0);
157 MultiByteToWideChar(CP_UTF8, 0, path.name.c_str(), -1, &fname[0], fname_length);
158
159 const int mode_length = MultiByteToWideChar(CP_UTF8, 0, mode, -1, nullptr, 0);
160 std::wstring wmode(mode_length, 0);
161 MultiByteToWideChar(CP_UTF8, 0, mode, -1, &wmode[0], mode_length);
162
163 using namespace std;
164#ifndef DMLC_DISABLE_STDIN
165 if (!wcscmp(fname.c_str(), L"stdin")) {
166 use_stdio = true; fp = stdin;
167 }
168 if (!wcscmp(fname.c_str(), L"stdout")) {
169 use_stdio = true; fp = stdout;
170 }
171#endif // DMLC_DISABLE_STDIN
172 if (!wcsncmp(fname.c_str(), L"file://", 7)) { fname = fname.substr(7); }
173 if (!use_stdio) {
174 std::wstring flag(wmode.c_str());
175 if (flag == L"w") flag = L"wb";
176 if (flag == L"r") flag = L"rb";
177#if DMLC_USE_FOPEN64
178 fp = _wfopen(fname.c_str(), flag.c_str());
179#else // DMLC_USE_FOPEN64
180 fp = fopen(fname, flag.c_str());
181#endif // DMLC_USE_FOPEN64
182 }
183#else // _WIN32
184 const char *fname = path.name.c_str();
185 using namespace std;
186#ifndef DMLC_DISABLE_STDIN
187 if (!strcmp(fname, "stdin")) {
188 use_stdio = true; fp = stdin;
189 }
190 if (!strcmp(fname, "stdout")) {
191 use_stdio = true; fp = stdout;
192 }
193#endif // DMLC_DISABLE_STDIN
194 if (!strncmp(fname, "file://", 7)) fname += 7;
195 if (!use_stdio) {
196 std::string flag = mode;
197 if (flag == "w") flag = "wb";
198 if (flag == "r") flag = "rb";
199#if DMLC_USE_FOPEN64
200 fp = fopen64(fname, flag.c_str());
201#else // DMLC_USE_FOPEN64
202 fp = fopen(fname, flag.c_str());
203#endif // DMLC_USE_FOPEN64
204 }
205#endif // _WIN32
206 if (fp != NULL) {
207 return new FileStream(fp, use_stdio);
208 } else {
209 CHECK(allow_null) << " LocalFileSystem::Open \"" << path.str() << "\": " << strerror(errno);
210 return NULL;
211 }
212}
213SeekStream *LocalFileSystem::OpenForRead(const URI &path, bool allow_null) {
214 return Open(path, "r", allow_null);
215}
216} // namespace io
217} // namespace dmlc
interface of i/o stream that support seek
Definition io.h:109
implementation of file i/o stream
Definition local_filesys.cc:27
virtual size_t Tell(void)
tell the position of the stream
Definition local_filesys.cc:48
virtual void Seek(size_t pos)
seek to certain position of the file
Definition local_filesys.cc:41
virtual void Write(const void *ptr, size_t size)
writes data to a stream
Definition local_filesys.cc:37
virtual size_t Read(void *ptr, size_t size)
reads data from a stream
Definition local_filesys.cc:34
virtual void ListDirectory(const URI &path, std::vector< FileInfo > *out_list)
list files in a directory
Definition local_filesys.cc:99
virtual FileInfo GetPathInfo(const URI &path)
get information about a path
Definition local_filesys.cc:69
virtual SeekStream * OpenForRead(const URI &path, bool allow_null)
open a seekable stream for read
Definition local_filesys.cc:213
virtual SeekStream * Open(const URI &path, const char *const flag, bool allow_null)
open a stream, will report error and exit if bad thing happens NOTE: the IStream can continue to work...
Definition local_filesys.cc:147
defines configuration macros
defines logging macros of dmlc allows use of GLOG, fall back to internal implementation when disabled
local access module
namespace for dmlc
Definition array_view.h:12
Definition StdDeque.h:58