Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
file_system.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * higher-level interface on top of sysdep/filesystem.h
25  */
26 
27 #include "precompiled.h"
28 #include "lib/file/file_system.h"
29 
30 #include <vector>
31 #include <algorithm>
32 #include <string>
33 
34 #include "lib/sysdep/filesystem.h"
35 
36 
37 bool DirectoryExists(const OsPath& path)
38 {
39  WDIR* dir = wopendir(path);
40  if(dir)
41  {
42  wclosedir(dir);
43  return true;
44  }
45  return false;
46 }
47 
48 
49 bool FileExists(const OsPath& pathname)
50 {
51  struct stat s;
52  const bool exists = wstat(pathname, &s) == 0;
53  return exists;
54 }
55 
56 
57 u64 FileSize(const OsPath& pathname)
58 {
59  struct stat s;
60  ENSURE(wstat(pathname, &s) == 0);
61  return s.st_size;
62 }
63 
64 
65 Status GetFileInfo(const OsPath& pathname, CFileInfo* pPtrInfo)
66 {
67  errno = 0;
68  struct stat s;
69  memset(&s, 0, sizeof(s));
70  if(wstat(pathname, &s) != 0)
72 
73  *pPtrInfo = CFileInfo(pathname.Filename(), s.st_size, s.st_mtime);
74  return INFO::OK;
75 }
76 
77 
78 struct DirDeleter
79 {
80  void operator()(WDIR* osDir) const
81  {
82  const int ret = wclosedir(osDir);
83  ENSURE(ret == 0);
84  }
85 };
86 
87 Status GetDirectoryEntries(const OsPath& path, CFileInfos* files, DirectoryNames* subdirectoryNames)
88 {
89  // open directory
90  errno = 0;
91  WDIR* pDir = wopendir(path);
92  if(!pDir)
93  return StatusFromErrno(); // NOWARN
94  shared_ptr<WDIR> osDir(pDir, DirDeleter());
95 
96  for(;;)
97  {
98  errno = 0;
99  struct wdirent* osEnt = wreaddir(osDir.get());
100  if(!osEnt)
101  {
102  // no error, just no more entries to return
103  if(!errno)
104  return INFO::OK;
106  }
107 
108  for(size_t i = 0; osEnt->d_name[i] != '\0'; i++)
110  const OsPath name(osEnt->d_name);
111 
112  // get file information (mode, size, mtime)
113  struct stat s;
114 #if OS_WIN
115  // .. return wdirent directly (much faster than calling stat).
116  RETURN_STATUS_IF_ERR(wreaddir_stat_np(osDir.get(), &s));
117 #else
118  // .. call regular stat().
119  errno = 0;
120  const OsPath pathname = path / name;
121  if(wstat(pathname, &s) != 0)
123 #endif
124 
125  if(files && S_ISREG(s.st_mode))
126  files->push_back(CFileInfo(name, s.st_size, s.st_mtime));
127  else if(subdirectoryNames && S_ISDIR(s.st_mode) && name != L"." && name != L"..")
128  subdirectoryNames->push_back(name);
129  }
130 }
131 
132 
133 Status CreateDirectories(const OsPath& path, mode_t mode)
134 {
135  if(path.empty())
136  return INFO::OK;
137 
138  struct stat s;
139  if(wstat(path, &s) == 0)
140  {
141  if(!S_ISDIR(s.st_mode)) // encountered a file
143  return INFO::OK;
144  }
145 
146  // If we were passed a path ending with '/', strip the '/' now so that
147  // we can consistently use Parent to find parent directory names
148  if(path.IsDirectory())
149  return CreateDirectories(path.Parent(), mode);
150 
152 
153  errno = 0;
154  if(wmkdir(path, mode) != 0)
155  {
156  debug_printf(L"CreateDirectories: failed to mkdir %ls (mode %d)", path.string().c_str(), mode);
158  }
159 
160  return INFO::OK;
161 }
162 
163 
165 {
166  // note: we have to recursively empty the directory before it can
167  // be deleted (required by Windows and POSIX rmdir()).
168 
169  CFileInfos files; DirectoryNames subdirectoryNames;
170  RETURN_STATUS_IF_ERR(GetDirectoryEntries(path, &files, &subdirectoryNames));
171 
172  // delete files
173  for(size_t i = 0; i < files.size(); i++)
174  {
175  const OsPath pathname = path / files[i].Name();
176  errno = 0;
177  if(wunlink(pathname) != 0)
179  }
180 
181  // recurse over subdirectoryNames
182  for(size_t i = 0; i < subdirectoryNames.size(); i++)
183  RETURN_STATUS_IF_ERR(DeleteDirectory(path / subdirectoryNames[i]));
184 
185  errno = 0;
186  if(wrmdir(path) != 0)
188 
189  return INFO::OK;
190 }
Path Filename() const
Definition: path.h:158
const Status OK
Definition: status.h:386
bool IsDirectory() const
Definition: path.h:143
#define S_ISREG(m)
Definition: wfilesystem.h:53
LIB_API int wrmdir(const OsPath &path)
WDIR * wopendir(const OsPath &path)
Definition: ufilesystem.cpp:76
Path Parent() const
Definition: path.h:150
Status GetDirectoryEntries(const OsPath &path, CFileInfos *files, DirectoryNames *subdirectoryNames)
Definition: file_system.cpp:87
bool FileExists(const OsPath &pathname)
Definition: file_system.cpp:49
wchar_t * d_name
Definition: filesystem.h:44
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
LIB_API int wunlink(const OsPath &pathname)
Definition: path.h:75
const String & string() const
Definition: path.h:123
u64 FileSize(const OsPath &pathname)
Definition: file_system.cpp:57
int wreaddir_stat_np(WDIR *, struct stat *)
wdirent * wreaddir(WDIR *)
Definition: ufilesystem.cpp:89
i64 Status
Error handling system.
Definition: status.h:171
Status StatusFromErrno()
Definition: status.cpp:105
static Status Validate(String::value_type c)
Definition: path.cpp:99
#define u64
Definition: types.h:42
bool empty() const
Definition: path.h:118
#define S_ISDIR(m)
Definition: wfilesystem.h:52
LIB_API int wmkdir(const OsPath &path, mode_t mode)
int wclosedir(WDIR *)
Definition: ufilesystem.cpp:98
std::vector< OsPath > DirectoryNames
Definition: file_system.h:77
#define WARN_RETURN(status)
Definition: status.h:255
const Status FAIL
Definition: status.h:406
Status DeleteDirectory(const OsPath &path)
Status CreateDirectories(const OsPath &path, mode_t mode)
bool DirectoryExists(const OsPath &path)
Definition: file_system.cpp:37
std::vector< CFileInfo > CFileInfos
Definition: file_system.h:76
void operator()(WDIR *osDir) const
Definition: file_system.cpp:80
LIB_API int wstat(const OsPath &pathname, struct stat *buf)
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
Definition: debug.cpp:142
Status GetFileInfo(const OsPath &pathname, CFileInfo *pPtrInfo)
Definition: file_system.cpp:65
#define RETURN_STATUS_IF_ERR(expression)
Definition: status.h:276