Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fileutils.cc
Go to the documentation of this file.
1 
18 #include "ion/port/fileutils.h"
19 
20 #if defined(ION_PLATFORM_IOS)
21 #include <Foundation/Foundation.h>
22 #endif
23 #if defined(ION_PLATFORM_WINDOWS)
24 #include <windows.h>
25 #else
26 #include <dirent.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <cstdlib>
30 #endif
31 
32 #include <cassert>
33 
34 #include "base/integral_types.h"
35 #include "ion/port/string.h"
36 
37 namespace ion {
38 namespace port {
39 
40 std::string GetCanonicalFilePath(const std::string& path) {
41 #if defined(ION_PLATFORM_WINDOWS)
42  std::string canonical_path = path;
45  const size_t length = canonical_path.length();
46  for (size_t i = 0; i < length; ++i)
47  if (canonical_path[i] == '\\')
48  canonical_path[i] = '/';
49  return canonical_path;
50 
51 #else
52  return path;
54 #endif
55 }
56 
58 #if defined(ION_PLATFORM_WINDOWS)
59  WCHAR pwd[MAX_PATH] = L"";
60  const int result = ::GetCurrentDirectoryW(MAX_PATH, pwd);
61  assert(0 < result && result < ARRAYSIZE(pwd));
62  (void) result; // for opt builds that elide the assert
63  return GetCanonicalFilePath(WideToUtf8(pwd));
64 #else
65  static const int kExpectedPathLength = 2048;
66  std::vector<char> path(kExpectedPathLength);
67  while (!getcwd(&path[0], static_cast<int>(path.size()))) {
68  path.resize(path.size() * 2);
69  }
70  return &path[0];
71 #endif
72 }
73 
74 bool GetFileModificationTime(const std::string& path,
75  std::chrono::system_clock::time_point* time) {
76 #if defined(ION_PLATFORM_WINDOWS)
77  static const int64 kEpochOffset = 116444736000000000ULL;
83 
84  bool retval = false;
85  const std::wstring wide = Utf8ToWide(path);
86  HANDLE handle = ::CreateFileW(wide.c_str(), GENERIC_READ,
87  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
88  OPEN_EXISTING, 0, NULL);
89  FILETIME create_time, access_time, write_time;
91  if (handle != INVALID_HANDLE_VALUE) {
92  if (GetFileTime(handle, &create_time, &access_time, &write_time)) {
93  const std::chrono::duration<int64, std::ratio<1, 10000000>> file_duration(
94  (static_cast<int64>(write_time.dwHighDateTime) << 32) +
95  write_time.dwLowDateTime - kEpochOffset);
96  *time = std::chrono::system_clock::time_point(file_duration);
97  retval = true;
98  }
99  CloseHandle(handle);
100  }
101  return retval;
102 
103 #else
104  struct stat info;
105 # if defined(ION_PLATFORM_IOS) || defined(ION_PLATFORM_MAC)
106 # define ION_STAT_SECONDS static_cast<uint64>(info.st_mtimespec.tv_sec)
107 # define ION_STAT_NSECONDS static_cast<uint64>(info.st_mtimespec.tv_nsec)
108 # elif defined(ION_PLATFORM_ANDROID) || defined(ION_PLATFORM_GENERIC_ARM)
109 # define ION_STAT_SECONDS static_cast<uint64>(info.st_mtime)
110 # define ION_STAT_NSECONDS static_cast<uint64>(info.st_mtime_nsec)
111 # elif defined(ION_PLATFORM_ASMJS) || defined(ION_PLATFORM_QNX) || \
112  defined(ION_PLATFORM_NACL)
113 # define ION_STAT_SECONDS static_cast<uint64>(info.st_mtime)
114 # define ION_STAT_NSECONDS 0
115 # elif defined(ION_PLATFORM_LINUX)
116 # define ION_STAT_SECONDS static_cast<uint64>(info.st_mtim.tv_sec)
117 # define ION_STAT_NSECONDS static_cast<uint64>(info.st_mtim.tv_nsec)
118 # else
119 # error No valid platform defined!
120 # endif
121 
122  if (!stat(path.c_str(), &info)) {
123  *time = std::chrono::system_clock::time_point(
124  std::chrono::duration_cast<std::chrono::system_clock::duration>(
125  std::chrono::seconds(ION_STAT_SECONDS) +
126  std::chrono::nanoseconds(ION_STAT_NSECONDS)));
127  return true;
128  }
129  return false;
130 
131 # undef ION_STAT_SECONDS
132 # undef ION_STAT_NSECONDS
133 #endif
134 }
135 
136 std::string GetTemporaryDirectory() {
137 #if defined(ION_PLATFORM_ANDROID)
138  return std::string("/data/local/tmp");
140 #elif defined(ION_PLATFORM_IOS)
141  return std::string([NSTemporaryDirectory() fileSystemRepresentation]);
142 #elif defined(ION_PLATFORM_WINDOWS)
143  WCHAR temp_path[MAX_PATH] = L"";
144  int size = ::GetTempPathW(MAX_PATH, temp_path);
145  assert(0 < size && size < ARRAYSIZE(temp_path));
146  if (size > 0 && temp_path[size - 1] == L'\\') {
147  temp_path[size - 1] = L'\0';
148  }
149  return GetCanonicalFilePath(WideToUtf8(temp_path));
150 #else
151  return std::string("/tmp");
153 #endif
154 }
155 
156 std::string GetTemporaryFilename() {
157  std::string return_path;
158 #if defined(ION_PLATFORM_WINDOWS)
159  WCHAR temp_path[MAX_PATH] = L"";
160  int size = ::GetTempPathW(MAX_PATH, temp_path);
161  assert(0 < size && size < ARRAYSIZE(temp_path));
162  (void) size;
163  WCHAR wide_path[MAX_PATH] = L"";
164  const UINT unique = ::GetTempFileNameW(temp_path, L"ion", 0, wide_path);
165  assert(unique != 0);
166  (void) unique;
167  return_path = GetCanonicalFilePath(WideToUtf8(wide_path));
168 #elif !defined(ION_PLATFORM_NACL)
169  std::string path = GetTemporaryDirectory() + "/ionXXXXXX";
171  const int fd = mkstemp(&path[0]);
172  if (fd != -1) {
173  close(fd);
174  return_path = path;
175  }
176 #endif
177  return return_path;
178 }
179 
180 FILE* OpenFile(const std::string& path, const std::string& mode) {
181  const std::string canonical_path = GetCanonicalFilePath(path);
182 #if defined(ION_PLATFORM_WINDOWS)
183  const std::wstring wide_path = Utf8ToWide(canonical_path);
184  const std::wstring wide_mode = Utf8ToWide(mode);
185  return _wfopen(wide_path.c_str(), wide_mode.c_str());
186 #else
187  return fopen(path.c_str(), mode.c_str());
188 #endif
189 }
190 
191 bool ReadDataFromFile(const std::string& path, std::string* out) {
192  if (FILE* file = ion::port::OpenFile(path, "rb")) {
194  fseek(file, 0, SEEK_END);
195  const size_t length = ftell(file);
196  rewind(file);
197 
199  out->resize(length);
200  fseek(file, 0, SEEK_SET);
201  fread(&out->at(0), sizeof(char), length, file);
202  fclose(file);
203  return true;
204  }
205 
206  return false;
207 }
208 
209 bool RemoveFile(const std::string& path) {
210 #if defined(ION_PLATFORM_NACL)
211  return false;
212 #elif defined(ION_PLATFORM_WINDOWS)
213  return ::DeleteFileW(Utf8ToWide(path).c_str()) != 0;
214 #else
215  return unlink(path.c_str()) == 0;
216 #endif
217 }
218 
219 std::vector<std::string> ListDirectory(const std::string& path) {
220  std::vector<std::string> files;
221 #if defined(ION_PLATFORM_WINDOWS)
222  std::wstring wild = ion::port::Utf8ToWide(path) + L"/*";
223  WIN32_FIND_DATAW find_data;
224  HANDLE find_handle = ::FindFirstFileW(wild.c_str(), &find_data);
225  if (find_handle != INVALID_HANDLE_VALUE) {
226  do {
227  if (!lstrcmpW(find_data.cFileName, L".") ||
228  !lstrcmpW(find_data.cFileName, L"..")) {
229  continue;
230  }
231  files.push_back(ion::port::WideToUtf8(find_data.cFileName));
232  } while (::FindNextFileW(find_handle, &find_data));
233  ::FindClose(find_handle);
234  }
235 #elif !defined(ION_PLATFORM_NACL)
236  if (DIR* dir = opendir(path.c_str())) {
239  struct dirent dent_buf;
240  struct dirent* dent;
241  while (readdir_r(dir, &dent_buf, &dent) == 0 && dent) {
242  const std::string file = dent->d_name;
243  if (file != "." && file != "..")
244  files.push_back(file);
245  }
246  closedir(dir);
247  }
248 #endif
249  return files;
250 }
251 
252 } // namespace port
253 } // namespace ion
std::string GetTemporaryFilename()
Returns a platform-dependent string that names a valid filename which may be opened for reading or wr...
Definition: fileutils.cc:156
std::vector< std::string > ListDirectory(const std::string &path)
Returns the contents of path, non-recursively.
Definition: fileutils.cc:219
unzFile handle
std::string GetCurrentWorkingDirectory()
Returns a platform-dependent string that is the current working directory.
Definition: fileutils.cc:57
bool RemoveFile(const std::string &path)
Attempts to remove the file at path and returns whether the file was successfully removed...
Definition: fileutils.cc:209
bool ReadDataFromFile(const std::string &path, std::string *out)
Opens the file at path and read the contents of the file into a string.
Definition: fileutils.cc:191
uint32 length
bool GetFileModificationTime(const std::string &path, std::chrono::system_clock::time_point *time)
Reads the last modification time of the passed file path into time and returns true, iff the file exists.
Definition: fileutils.cc:74
std::string GetCanonicalFilePath(const std::string &path)
Returns a canonical version of a file path string.
Definition: fileutils.cc:40
FILE * OpenFile(const std::string &path, const std::string &mode)
Opens the file at path and returns a FILE pointer suitable for passing to fread, fwrite, fclose, etc.
Definition: fileutils.cc:180
std::string GetTemporaryDirectory()
Returns a platform-dependent string that names the temporary directory.
Definition: fileutils.cc:136