1 krisbash 1.1 #include "dir.h"
2 #include <base/paths.h>
3 #include <pal/strings.h>
4 #include <ctype.h>
5
6 #if defined(PAL_HAVE_POSIX)
7 # include <sys/types.h>
8 # include <sys/stat.h>
9 # include <dirent.h>
10 # include <unistd.h>
11 #endif
12
13 #if defined(_MSC_VER)
14 # include <windows.h>
15 # include <sys/stat.h>
16 # include <io.h>
17 #endif
18
19 /*
20 **==============================================================================
21 **
22 krisbash 1.1 ** Dir type (POSIX)
23 **
24 **==============================================================================
25 */
26
27 #if defined(PAL_HAVE_POSIX)
28
29 struct _Dir
30 {
31 DIR* dir;
32 DirEnt ent;
33 };
34
35 Dir* Dir_Open(const char* path)
36 {
37 Dir* self = (Dir*)PAL_Calloc(1, sizeof(Dir));
38
39 if (!self)
40 return NULL;
41
42 self->dir = opendir(path);
43 krisbash 1.1 if (!self->dir)
44 {
45 PAL_Free(self);
46 return NULL;
47 }
48
49 return self;
50 }
51
52 DirEnt* Dir_Read(Dir* self)
53 {
54 struct dirent* p = readdir(self->dir);
55 if (!p)
56 return NULL;
57
58 Strlcpy(self->ent.name, p->d_name, sizeof(self->ent.name));
59
60 return &self->ent;
61 }
62
63 int Dir_Close(Dir* self)
64 krisbash 1.1 {
65 if (!self)
66 return -1;
67
68 if (closedir(self->dir) != 0)
69 {
70 PAL_Free(self);
71 return -1;
72 }
73
74 PAL_Free(self);
75 return 0;
76 }
77
78 #endif /* defined(PAL_HAVE_POSIX) */
79
80 /*
81 **==============================================================================
82 **
83 ** Dir type (Windows)
84 **
85 krisbash 1.1 **==============================================================================
86 */
87
88 #if defined(_MSC_VER)
89
90 struct _Dir
91 {
92 intptr_t handle;
93 struct _finddata_t fileinfo;
94 DirEnt ent;
95 int firstTime;
96 };
97
98 Dir* Dir_Open(const char* path)
99 {
100 Dir* dir;
101 char filespec[PAL_MAX_PATH_SIZE];
102
103 /* Allocate and zero-fill struct */
104 dir = (Dir*)PAL_Calloc(1, sizeof(Dir));
105 if (!dir)
106 krisbash 1.1 return NULL;
107
108 /* Build files spec */
109 {
110 if (Strlcpy(filespec, path, sizeof(filespec)) >= PAL_MAX_PATH_SIZE)
111 return NULL;
112
113 if (Strlcat(filespec, "/*", sizeof(filespec)) >= PAL_MAX_PATH_SIZE)
114 return NULL;
115 }
116
117 /* Find first file matching the file spec */
118 dir->handle = _findfirst(filespec, &dir->fileinfo);
119 if (dir->handle == -1)
120 {
121 PAL_Free(dir);
122 return NULL;
123 }
124
125 /* Note that readdir() has not been called yet */
126 dir->firstTime = 1;
127 krisbash 1.1
128 return dir;
129 }
130
131 DirEnt* Dir_Read(Dir* dir)
132 {
133 if (!dir->firstTime)
134 {
135 if (_findnext(dir->handle, &dir->fileinfo) != 0)
136 return NULL;
137 }
138
139 Strlcpy(dir->ent.name, dir->fileinfo.name, PAL_MAX_PATH_SIZE);
140 dir->firstTime = 0;
141 return &dir->ent;
142 }
143
144 int Dir_Close(Dir* dir)
145 {
146 _findclose(dir->handle);
147 PAL_Free(dir);
148 krisbash 1.1 return 0;
149 }
150
151 #endif /* defined(_MSC_VER) */
152
153 /*
154 **==============================================================================
155 **
156 ** Isdir()
157 **
158 **==============================================================================
159 */
160
161 PAL_Boolean Isdir(const char* path)
162 {
163 #if defined(_MSC_VER)
164 {
165 struct _stat st;
166
167 if (_stat(path, &st) != 0)
168 return 0;
169 krisbash 1.1
170 return (_S_IFDIR & st.st_mode) ? PAL_TRUE : PAL_FALSE;
171 }
172 #else
173 {
174 struct stat st;
175
176 if (stat(path, &st) != 0)
177 return 0;
178
179 return S_ISDIR(st.st_mode);
180 }
181 #endif
182 }
183
184 const char* Basename(const char* path)
185 {
186 const char* p = strrchr(path, '/');
187
188 if (p)
189 return p + 1;
190 krisbash 1.1
191 return path;
192 }
193
194 int Mkdirhier(const char* path_, int mode)
195 {
196 char path[PAL_MAX_PATH_SIZE];
197 char buf[PAL_MAX_PATH_SIZE];
198 char* p;
199 char* context = NULL;
200
201 /* Make a complete copy of the path (that we can destroy) */
202 if (Strlcpy(path, path_, sizeof(path)) >= sizeof(path))
203 return -1;
204
205 buf[0] = '\0';
206
207 for (p = Strtok(path, "/", &context); p; p = Strtok(NULL, "/", &context))
208 {
209 #if defined(CONFIG_OS_WINDOWS)
210 /* Skip drive letters (on Windows) */
211 krisbash 1.1 if (p == path && isalpha((unsigned char)p[0]) && p[1] == ':' && p[2] == '\0')
212 {
213 Strlcat(buf, p, sizeof(buf));
214 continue;
215 }
216 #endif
217
218 /* Concatenate next component */
219 Strlcat(buf, "/", sizeof(buf));
220 Strlcat(buf, p, sizeof(buf));
221
222 /* Create directory if it does not already exist */
223 if (!Isdir(buf))
224 {
225 if (Mkdir(buf, mode) != 0)
226 return -1;
227 }
228 }
229
230 return 0;
231 }
|