ISFileManager.cpp
Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright (c) 2014-2021 Inertial Sense, Inc. - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include "ISFileManager.h"
14 #include <regex>
15 
16 
17 #if PLATFORM_IS_EVB_2
18 #include <ff.h>
19 #else
20 #include <sys/stat.h>
21 #include <cstdio>
22 #include <time.h>
23 #endif
24 
25 #if PLATFORM_IS_LINUX || PLATFORM_IS_APPLE
26 #include <sys/statvfs.h>
27 #endif
28 
29 namespace ISFileManager {
30 
31  bool PathIsDir(const std::string& path)
32  {
33 #if PLATFORM_IS_EVB_2
34  FILINFO info;
35  FRESULT result = f_stat(path.c_str(), &info);
36  return (result == FR_OK) && (info.fattrib & AM_DIR);
37 #else
38  struct stat sb;
39  return (stat(path.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode));
40 #endif
41  }
42 
43  bool GetAllFilesInDirectory(const std::string& directory, bool recursive, const std::string& regexPattern, std::vector<std::string>& files)
44  {
45  size_t startSize = files.size();
46  std::regex* rePtr = NULL;
47  std::regex re;
48  if (regexPattern.length() != 0)
49  {
50  re = std::regex(regexPattern, std::regex::icase);
51  rePtr = &re;
52  }
53 
54 #if PLATFORM_IS_EVB_2
55 
56  {
57  FRESULT result;
58  FILINFO info;
59  DIR dir;
60  char *file_name;
61 #if _USE_LFN
62  static char longFileName[_MAX_LFN + 1];
63  info.lfname = longFileName;
64  info.lfsize = sizeof(longFileName);
65 #endif
66 
67 
68  result = f_opendir(&dir, directory.c_str());
69  if (result == FR_OK) {
70  while (true) {
71  result = f_readdir(&dir, &info);
72  if (result != FR_OK || info.fname[0] == 0)
73  {
74  break;
75  }
76 #if _USE_LFN
77  file_name = *info.lfname ? info.lfname : info.fname;
78 #else
79  file_name = info.fname;
80 #endif
81  std::string full_file_name = directory + "/" + file_name;
82 
83 
84  if (file_name[0] == '.' || (rePtr != NULL && !regex_search(full_file_name, re)))
85  {
86  continue;
87  }
88  else if (info.fattrib & AM_DIR) {
89  if (recursive)
90  {
91  GetAllFilesInDirectory(full_file_name, true, files);
92  }
93  continue;
94  }
95  files.push_back(full_file_name);
96  }
97  }
98 
99  }
100 
101 #elif PLATFORM_IS_WINDOWS
102 
103  HANDLE dir;
104  WIN32_FIND_DATAA file_data;
105  if ((dir = FindFirstFileA((directory + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE)
106  {
107  return false;
108  }
109  do
110  {
111  std::string file_name = file_data.cFileName;
112  std::string full_file_name = directory + "/" + file_name;
113  if (file_name[0] == '.' || (rePtr != NULL && !regex_search(full_file_name, re)))
114  {
115  continue;
116  }
117  else if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
118  {
119  if (recursive)
120  {
121  GetAllFilesInDirectory(full_file_name, true, files);
122  }
123  continue;
124  }
125  files.push_back(full_file_name);
126  } while (FindNextFileA(dir, &file_data));
127  FindClose(dir);
128 
129 #else // Linux
130 
131  class dirent* ent;
132  class stat st;
133  DIR* dir = opendir(directory.c_str());
134 
135  if (dir == NULL) {
136  return false;
137  }
138 
139  while ((ent = readdir(dir)) != NULL) {
140  const std::string file_name = ent->d_name;
141  const std::string full_file_name = directory + "/" + file_name;
142 
143  // if file is current path or does not exist (-1) then continue
144  if (file_name[0] == '.' || stat(full_file_name.c_str(), &st) == -1 ||
145  (rePtr != NULL && !regex_search(full_file_name, re))) {
146  continue;
147  }
148  else if ((st.st_mode & S_IFDIR) != 0) {
149  if (recursive) {
150  GetAllFilesInDirectory(full_file_name, true, files);
151  }
152  continue;
153  }
154 
155  files.push_back(full_file_name);
156  }
157  closedir(dir);
158 
159 #endif
160 
161  return (files.size() != startSize);
162  }
163 
164  bool GetAllFilesInDirectory(const std::string& directory, bool recursive, std::vector<std::string>& files)
165  {
166  return GetAllFilesInDirectory(directory, recursive, "", files);
167  }
168 
169  bool DeleteFile(const std::string& fullFilePath)
170  {
171 #if PLATFORM_IS_EVB_2
172  return (f_unlink(fullFilePath.c_str()) == FR_OK);
173 #else
174  return (std::remove(fullFilePath.c_str()) == 0);
175 #endif
176 
177  }
178 
179  void DeleteDirectory(const std::string& directory, bool recursive)
180  {
181 
182 #if PLATFORM_IS_EVB_2
183  // Always recursive
184  f_unlink(directory.c_str());
185 #elif PLATFORM_IS_WINDOWS
186 
187  HANDLE dir;
188  WIN32_FIND_DATAA file_data;
189  if ((dir = FindFirstFileA((directory + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE)
190  {
191  return;
192  }
193  do
194  {
195  const std::string file_name = file_data.cFileName;
196  const std::string full_file_name = directory + "/" + file_name;
197  const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
198  if (file_name[0] == '.')
199  {
200  continue;
201  }
202  else if (is_directory)
203  {
204  if (recursive)
205  {
206  DeleteDirectory(full_file_name, true);
207  }
208  continue;
209  }
210  std::remove(full_file_name.c_str());
211  } while (FindNextFileA(dir, &file_data));
212  FindClose(dir);
213 
214 #else
215 
216  class dirent* ent;
217  class stat st;
218 
219  DIR* dir;
220  if ((dir = opendir(directory.c_str())) == NULL) {
221  return;
222  }
223 
224  while ((ent = readdir(dir)) != NULL) {
225  const std::string file_name = ent->d_name;
226  const std::string full_file_name = directory + "/" + file_name;
227 
228  // if file is current path or does not exist (-1) then continue
229  if (file_name[0] == '.' || stat(full_file_name.c_str(), &st) == -1) {
230  continue;
231  } else if ((st.st_mode & S_IFDIR) != 0) {
232  if (recursive) {
233  DeleteDirectory(full_file_name, true);
234  }
235  continue;
236  }
237  std::remove(full_file_name.c_str());
238  }
239  closedir(dir);
240 
241 #endif
242 
243  _RMDIR(directory.c_str());
244  }
245 
246  uint64_t GetDirectorySpaceUsed(const std::string& directory, bool recursive)
247  {
248  std::vector<file_info_t> files;
249  return GetDirectorySpaceUsed(directory, "", files, true, recursive);
250  }
251 
252 
253  uint64_t GetDirectorySpaceUsed(const std::string& directory, std::vector<file_info_t>& files, bool sortByDate, bool recursive)
254  {
255  return GetDirectorySpaceUsed(directory, "", files, sortByDate, recursive);
256  }
257 
258  uint64_t GetDirectorySpaceUsed(const std::string& directory, std::string regexPattern, std::vector<file_info_t>& files,
259  bool sortByDate, bool recursive)
260  {
261 #if PLATFORM_IS_EVB_2
262  static_assert((sizeof(time_t) >= 2 * sizeof(WORD)), "time_t must be at least 2* DWORD, since we store the FatFs date/time (DWORD) in a time_t here.");
263 #endif
264 
265  std::vector<std::string> fileNames;
266  ISFileManager::GetAllFilesInDirectory(directory, recursive, regexPattern, fileNames);
267  uint64_t spaceUsed = 0;
268  for (unsigned int i = 0; i < fileNames.size(); i++)
269  {
270  file_info_t info;
271  info.name = fileNames[i];
272 #if PLATFORM_IS_EVB_2
273  FILINFO filInfo;
274  f_stat(info.name.c_str(), &filInfo);
275  info.size = filInfo.fsize;
276  info.lastModificationDate = static_cast<time_t>(filInfo.ftime);
277  info.lastModificationDate |= static_cast<time_t>(filInfo.fdate) << (sizeof(filInfo.ftime) * 8);
278 #else
279  struct stat st;
280  stat(info.name.c_str(), &st);
281  info.size = st.st_size;
282  info.lastModificationDate = st.st_mtime;
283 #endif
284  files.push_back(info);
285  spaceUsed += info.size;
286  }
287 
288  if (sortByDate) {
289  struct
290  {
291  bool operator()(const file_info_t& a, const file_info_t& b)
292  {
293  int compare = (a.lastModificationDate == b.lastModificationDate ? 0 : (a.lastModificationDate <
294  b.lastModificationDate ? -1
295  : 1));
296  if (compare == 0) {
297  compare = a.name.compare(b.name);
298  }
299  return compare < 0;
300  }
301  } customSortDate;
302  sort(files.begin(), files.end(), customSortDate);
303  } else {
304  struct
305  {
306  bool operator()(const file_info_t& a, const file_info_t& b)
307  {
308  return a.name < b.name;
309  }
310  } customSortName;
311  sort(files.begin(), files.end(), customSortName);
312  }
313 
314  return spaceUsed;
315  }
316 
317  uint64_t GetDirectorySpaceAvailable(const std::string& directory)
318  {
319 #if PLATFORM_IS_EVB_2
320  FATFS *fs;
321  DWORD free_clusters;
322  DWORD sector_size;
323 
324  /* Get volume information and free clusters of drive 1 */
325  FRESULT result = f_getfree("0:", &free_clusters, &fs);
326  if (result != FR_OK)
327  {
328  return 0;
329  }
330 #if _MAX_SS == 512
331  sector_size = 512;
332 #else
333  sector_size = fs->ssize;
334 #endif
335 
336  return free_clusters * fs->csize * sector_size;
337 
338 #elif PLATFORM_IS_WINDOWS
339 
340  ULARGE_INTEGER space;
341  memset(&space, 0, sizeof(space));
342  char fullPath[MAX_PATH];
343  GetFullPathNameA(directory.c_str(), MAX_PATH, fullPath, NULL);
344  bool created = (_MKDIR(fullPath) == 0);
345  GetDiskFreeSpaceExA(fullPath, &space, NULL, NULL);
346  if (created)
347  {
348  _RMDIR(fullPath);
349  }
350  return (uint64_t)space.QuadPart;
351 
352 #else
353 
354  struct statvfs stat;
355  memset(&stat, 0, sizeof(stat));
356  char fullPath[PATH_MAX];
357  if (realpath(directory.c_str(), fullPath) == NULL)
358  {
359  return 0;
360  }
361  bool created = (_MKDIR(fullPath) == 0);
362  statvfs(fullPath, &stat);
363  if (created)
364  {
365  _RMDIR(fullPath);
366  }
367  return (uint64_t)stat.f_bsize * (uint64_t)stat.f_bavail;
368 
369 #endif
370 
371  }
372 
373  std::string GetFileName(const std::string& path)
374  {
375  size_t lastSepIndex = path.find_last_of("\\/");
376  if (lastSepIndex != std::string::npos)
377  {
378  return path.substr(lastSepIndex + 1);
379  }
380  return path;
381  }
382 
383  bool TouchFile(const std::string& path)
384  {
385 #if PLATFORM_IS_EVB_2
386  DWORD datetime = get_fattime();
387  FILINFO info;
388  info.fdate = static_cast<WORD>(datetime >> sizeof(WORD));
389  info.ftime = static_cast<WORD>(datetime);
390  f_utime(path.c_str(), &info);
391  return true;
392 #else
393  _UTIMEBUF buf{time(NULL), time(NULL)};
394  return (_UTIME(path.c_str(), &buf) == 0);
395 #endif
396  }
397 
398 } // namespace ISFileManager
unsigned short WORD
Definition: integer.h:27
WORD fdate
Definition: ff.h:164
Definition: ff.h:162
Definition: ff.h:78
bool PathIsDir(const std::string &path)
#define _UTIMEBUF
Definition: ISConstants.h:217
WORD ftime
Definition: ff.h:165
#define NULL
Definition: nm_bsp.h:52
uint32_t get_fattime(void)
Current time returned is packed into a DWORD value.
Definition: fattime_rtc.c:57
TCHAR * lfname
Definition: ff.h:169
BYTE csize
Definition: ff.h:81
TCHAR fname[13]
Definition: ff.h:167
Definition: ff.h:143
unsigned long DWORD
Definition: integer.h:33
FRESULT f_utime(const TCHAR *path, const FILINFO *fno)
Definition: ff.c:3381
uint64_t GetDirectorySpaceAvailable(const std::string &directory)
UINT lfsize
Definition: ff.h:170
#define _UTIME
Definition: ISConstants.h:216
bool GetAllFilesInDirectory(const std::string &directory, bool recursive, const std::string &regexPattern, std::vector< std::string > &files)
FRESULT
Definition: ff.h:178
bool DeleteFile(const std::string &fullFilePath)
#define _MAX_LFN
Definition: ffconf.h:96
FRESULT f_unlink(const TCHAR *path)
Definition: ff.c:3198
FRESULT f_getfree(const TCHAR *path, DWORD *nclst, FATFS **fatfs)
Definition: ff.c:3085
#define _RMDIR(dir)
Definition: ISConstants.h:214
std::string GetFileName(const std::string &path)
FRESULT f_readdir(DIR *dj, FILINFO *fno)
Definition: ff.c:3010
BYTE fattrib
Definition: ff.h:166
DWORD fsize
Definition: ff.h:163
#define _MKDIR(dir)
Definition: ISConstants.h:213
uint64_t GetDirectorySpaceUsed(const std::string &directory, bool recursive)
FRESULT f_stat(const TCHAR *path, FILINFO *fno)
Definition: ff.c:3052
void DeleteDirectory(const std::string &directory, bool recursive)
Definition: ff.h:179
#define AM_DIR
Definition: ff.h:310
FRESULT f_opendir(DIR *dj, const TCHAR *path)
Definition: ff.c:2970
bool TouchFile(const std::string &path)


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:57