comparison deps/Platinum/ThirdParty/Neptune/Source/System/Posix/NptPosixFile.cpp @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
1 /*****************************************************************
2 |
3 | Neptune - File :: Posix Implementation
4 |
5 | (c) 2001-2008 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
7 |
8 ****************************************************************/
9
10 /*----------------------------------------------------------------------
11 | includes
12 +---------------------------------------------------------------------*/
13 #define _LARGEFILE_SOURCE
14 #define _LARGEFILE_SOURCE64
15 #define _FILE_OFFSET_BITS 64
16
17 #include <sys/stat.h>
18
19 #include <errno.h>
20
21 #if defined(_WIN32)
22 #include <direct.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #else
26 #include <unistd.h>
27 #include <dirent.h>
28 #endif
29
30 #include "NptLogging.h"
31 #include "NptFile.h"
32 #include "NptUtils.h"
33
34 /*----------------------------------------------------------------------
35 | logging
36 +---------------------------------------------------------------------*/
37 //NPT_SET_LOCAL_LOGGER("neptune.posix.file")
38
39 /*----------------------------------------------------------------------
40 | Win32 adaptation
41 +---------------------------------------------------------------------*/
42 #if defined(_WIN32) || defined(_XBOX)
43 extern int NPT_stat_utf8(const char* path, NPT_stat_struct* info);
44 extern char* NPT_getcwd_utf8(char* path, unsigned int path_size);
45 #define getcwd NPT_getcwd_utf8
46 #define S_ISDIR(_m) (((_m)&_S_IFMT) == _S_IFDIR)
47 #define S_ISREG(_m) (((_m)&_S_IFMT) == _S_IFREG)
48 #define S_IWUSR _S_IWRITE
49 #endif
50
51 /*----------------------------------------------------------------------
52 | MapErrno
53 +---------------------------------------------------------------------*/
54 static NPT_Result
55 MapErrno(int err) {
56 switch (err) {
57 case EACCES: return NPT_ERROR_PERMISSION_DENIED;
58 case EPERM: return NPT_ERROR_PERMISSION_DENIED;
59 case ENOENT: return NPT_ERROR_NO_SUCH_FILE;
60 case ENAMETOOLONG: return NPT_ERROR_INVALID_PARAMETERS;
61 case EBUSY: return NPT_ERROR_FILE_BUSY;
62 case EROFS: return NPT_ERROR_FILE_NOT_WRITABLE;
63 case ENOTDIR: return NPT_ERROR_FILE_NOT_DIRECTORY;
64 case EEXIST: return NPT_ERROR_FILE_ALREADY_EXISTS;
65 case ENOSPC: return NPT_ERROR_FILE_NOT_ENOUGH_SPACE;
66 case ENOTEMPTY: return NPT_ERROR_DIRECTORY_NOT_EMPTY;
67 default: return NPT_ERROR_ERRNO(err);
68 }
69 }
70
71 #if !defined(_WIN32)
72 /*----------------------------------------------------------------------
73 | NPT_FilePath::Separator
74 +---------------------------------------------------------------------*/
75 const NPT_String NPT_FilePath::Separator("/");
76
77 /*----------------------------------------------------------------------
78 | NPT_File::GetRoots
79 +---------------------------------------------------------------------*/
80 NPT_Result
81 NPT_File::GetRoots(NPT_List<NPT_String>& roots)
82 {
83 roots.Clear();
84 roots.Add("/");
85 return NPT_SUCCESS;
86 }
87
88 /*----------------------------------------------------------------------
89 | NPT_File::CreateDirectory
90 +---------------------------------------------------------------------*/
91 NPT_Result
92 NPT_File::CreateDirectory(const char* path)
93 {
94 int result;
95
96 result = mkdir(path, 0755);
97 if (result != 0) {
98 return MapErrno(errno);
99 }
100
101 return NPT_SUCCESS;
102 }
103
104 /*----------------------------------------------------------------------
105 | NPT_File::DeleteFile
106 +---------------------------------------------------------------------*/
107 NPT_Result
108 NPT_File::DeleteFile(const char* path)
109 {
110 int result = unlink(path);
111 if (result != 0) return MapErrno(errno);
112
113 return NPT_SUCCESS;
114 }
115
116 /*----------------------------------------------------------------------
117 | NPT_File::DeleteDirectory
118 +---------------------------------------------------------------------*/
119 NPT_Result
120 NPT_File::DeleteDirectory(const char* path)
121 {
122 int result = rmdir(path);
123 if (result != 0) return MapErrno(errno);
124
125 return NPT_SUCCESS;
126 }
127
128 /*----------------------------------------------------------------------
129 | NPT_File::Rename
130 +---------------------------------------------------------------------*/
131 NPT_Result
132 NPT_File::Rename(const char* from_path, const char* to_path)
133 {
134 int result = rename(from_path, to_path);
135 if (result != 0) return MapErrno(errno);
136
137 return NPT_SUCCESS;
138 }
139
140 /*----------------------------------------------------------------------
141 | NPT_File::ListDirectory
142 +---------------------------------------------------------------------*/
143 NPT_Result
144 NPT_File::ListDirectory(const char* path,
145 NPT_List<NPT_String>& entries,
146 NPT_Ordinal start /* = 0 */,
147 NPT_Cardinal max /* = 0 */)
148 {
149 // default return value
150 entries.Clear();
151
152 // check the arguments
153 if (path == NULL) return NPT_ERROR_INVALID_PARAMETERS;
154
155 // list the entries
156 DIR *directory = opendir(path);
157 if (directory == NULL) return NPT_ERROR_OUT_OF_MEMORY;
158
159 NPT_Cardinal count = 0;
160 for (;;) {
161 struct dirent* entry_pointer = NULL;
162 #if defined(NPT_CONFIG_HAVE_READDIR_R)
163 struct dirent entry;
164 int result = readdir_r(directory, &entry, &entry_pointer);
165 if (result != 0 || entry_pointer == NULL) break;
166 #else
167 entry_pointer = readdir(directory);
168 if (entry_pointer == NULL) break;
169 #endif
170 // ignore odd names
171 if (entry_pointer->d_name[0] == '\0') continue;
172
173 // ignore . and ..
174 if (entry_pointer->d_name[0] == '.' &&
175 entry_pointer->d_name[1] == '\0') {
176 continue;
177 }
178 if (entry_pointer->d_name[0] == '.' &&
179 entry_pointer->d_name[1] == '.' &&
180 entry_pointer->d_name[2] == '\0') {
181 continue;
182 }
183
184 // continue if not yet first item requested
185 if (start > 0) {
186 --start;
187 continue;
188 }
189 entries.Add(NPT_String(entry_pointer->d_name));
190
191 // stop when reaching maximum requested
192 if (max && ++count == max) break;
193 }
194
195 closedir(directory);
196
197 return NPT_SUCCESS;
198 }
199 #endif
200
201 /*----------------------------------------------------------------------
202 | NPT_File::GetWorkingDirectory
203 +---------------------------------------------------------------------*/
204 NPT_Result
205 NPT_File::GetWorkingDirectory(NPT_String& path)
206 {
207 char buffer[1024+1];
208 char* dir = getcwd(buffer, 1024+1);
209 if (dir == NULL) return MapErrno(errno);
210 path = dir;
211
212 return NPT_SUCCESS;
213 }
214
215 /*----------------------------------------------------------------------
216 | NPT_File::GetInfo
217 +---------------------------------------------------------------------*/
218 NPT_Result
219 NPT_File::GetInfo(const char* path, NPT_FileInfo* info)
220 {
221 // default value
222 if (info) NPT_SetMemory(info, 0, sizeof(*info));
223
224 // On Windows, stat will fail if a dir ends with a separator
225 NPT_String _path = path;
226 _path.TrimRight("\\/");
227 if (NPT_StringLength(path) == 2 && path[1] == ':') {
228 _path += NPT_FilePath::Separator;
229 }
230
231 // get the file info
232 NPT_stat_struct stat_buffer;
233 int result = NPT_stat(_path, &stat_buffer);
234 if (result != 0) return MapErrno(errno);
235
236 // setup the returned fields
237 if (info) {
238 info->m_Size = stat_buffer.st_size;
239 if (S_ISREG(stat_buffer.st_mode)) {
240 info->m_Type = NPT_FileInfo::FILE_TYPE_REGULAR;
241 } else if (S_ISDIR(stat_buffer.st_mode)) {
242 info->m_Type = NPT_FileInfo::FILE_TYPE_DIRECTORY;
243 } else {
244 info->m_Type = NPT_FileInfo::FILE_TYPE_OTHER;
245 }
246 info->m_AttributesMask &= NPT_FILE_ATTRIBUTE_READ_ONLY;
247 if ((stat_buffer.st_mode & S_IWUSR) == 0) {
248 info->m_Attributes &= NPT_FILE_ATTRIBUTE_READ_ONLY;
249 }
250 }
251
252 return NPT_SUCCESS;
253 }