Skip to content

Latest commit

 

History

History
441 lines (342 loc) · 10.5 KB

platform_posix.c

File metadata and controls

441 lines (342 loc) · 10.5 KB
 
May 24, 2002
May 24, 2002
1
2
3
/*
* Posix-esque support routines for PhysicsFS.
*
Mar 11, 2007
Mar 11, 2007
4
* Please see the file LICENSE.txt in the source's root directory.
May 24, 2002
May 24, 2002
5
6
7
8
*
* This file written by Ryan C. Gordon.
*/
Mar 11, 2007
Mar 11, 2007
9
10
11
12
#define __PHYSICSFS_INTERNAL__
#include "physfs_platforms.h"
#ifdef PHYSFS_PLATFORM_POSIX
Jun 29, 2002
Jun 29, 2002
13
May 24, 2002
May 24, 2002
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
Jun 2, 2002
Jun 2, 2002
18
#include <ctype.h>
May 24, 2002
May 24, 2002
19
20
#include <sys/types.h>
#include <sys/stat.h>
Jun 2, 2002
Jun 2, 2002
21
#include <pwd.h>
May 24, 2002
May 24, 2002
22
23
#include <dirent.h>
#include <errno.h>
Jun 2, 2002
Jun 2, 2002
24
#include <fcntl.h>
May 24, 2002
May 24, 2002
25
Jun 6, 2002
Jun 6, 2002
26
27
28
29
#ifdef PHYSFS_HAVE_LLSEEK
#include <linux/unistd.h>
#endif
May 24, 2002
May 24, 2002
30
31
32
#include "physfs_internal.h"
Mar 21, 2007
Mar 21, 2007
33
34
35
const char *__PHYSFS_platformDirSeparator = "/";
May 24, 2002
May 24, 2002
36
37
38
39
40
41
42
char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname)
{
const char *envr = getenv(varname);
char *retval = NULL;
if (envr != NULL)
{
Mar 14, 2005
Mar 14, 2005
43
retval = (char *) allocator.Malloc(strlen(envr) + 1);
May 24, 2002
May 24, 2002
44
45
46
47
if (retval != NULL)
strcpy(retval, envr);
} /* if */
Jan 28, 2010
Jan 28, 2010
48
return retval;
May 24, 2002
May 24, 2002
49
50
51
52
53
54
55
56
57
58
59
60
} /* __PHYSFS_platformCopyEnvironmentVariable */
static char *getUserNameByUID(void)
{
uid_t uid = getuid();
struct passwd *pw;
char *retval = NULL;
pw = getpwuid(uid);
if ((pw != NULL) && (pw->pw_name != NULL))
{
Mar 14, 2005
Mar 14, 2005
61
retval = (char *) allocator.Malloc(strlen(pw->pw_name) + 1);
May 24, 2002
May 24, 2002
62
63
64
65
if (retval != NULL)
strcpy(retval, pw->pw_name);
} /* if */
Jan 28, 2010
Jan 28, 2010
66
return retval;
May 24, 2002
May 24, 2002
67
68
69
70
71
72
73
74
75
76
77
78
} /* getUserNameByUID */
static char *getUserDirByUID(void)
{
uid_t uid = getuid();
struct passwd *pw;
char *retval = NULL;
pw = getpwuid(uid);
if ((pw != NULL) && (pw->pw_dir != NULL))
{
Mar 14, 2005
Mar 14, 2005
79
retval = (char *) allocator.Malloc(strlen(pw->pw_dir) + 1);
May 24, 2002
May 24, 2002
80
81
82
83
if (retval != NULL)
strcpy(retval, pw->pw_dir);
} /* if */
Jan 28, 2010
Jan 28, 2010
84
return retval;
May 24, 2002
May 24, 2002
85
86
87
88
89
90
91
92
} /* getUserDirByUID */
char *__PHYSFS_platformGetUserName(void)
{
char *retval = getUserNameByUID();
if (retval == NULL)
retval = __PHYSFS_platformCopyEnvironmentVariable("USER");
Jan 28, 2010
Jan 28, 2010
93
return retval;
May 24, 2002
May 24, 2002
94
95
96
97
98
99
} /* __PHYSFS_platformGetUserName */
char *__PHYSFS_platformGetUserDir(void)
{
char *retval = __PHYSFS_platformCopyEnvironmentVariable("HOME");
Mar 21, 2010
Mar 21, 2010
100
101
102
103
104
105
106
107
108
109
110
111
/* if the environment variable was set, make sure it's really a dir. */
if (retval != NULL)
{
struct stat statbuf;
if ((stat(retval, &statbuf) == -1) || (S_ISDIR(statbuf.st_mode) == 0))
{
allocator.Free(retval);
retval = NULL;
} /* if */
} /* if */
May 24, 2002
May 24, 2002
112
113
if (retval == NULL)
retval = getUserDirByUID();
Mar 21, 2010
Mar 21, 2010
114
Jan 28, 2010
Jan 28, 2010
115
return retval;
May 24, 2002
May 24, 2002
116
117
118
119
120
121
122
123
124
125
} /* __PHYSFS_platformGetUserDir */
char *__PHYSFS_platformCvtToDependent(const char *prepend,
const char *dirName,
const char *append)
{
int len = ((prepend) ? strlen(prepend) : 0) +
((append) ? strlen(append) : 0) +
strlen(dirName) + 1;
Mar 14, 2005
Mar 14, 2005
126
char *retval = (char *) allocator.Malloc(len);
May 24, 2002
May 24, 2002
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
/* platform-independent notation is Unix-style already. :) */
if (prepend)
strcpy(retval, prepend);
else
retval[0] = '\0';
strcat(retval, dirName);
if (append)
strcat(retval, append);
Jan 28, 2010
Jan 28, 2010
142
return retval;
May 24, 2002
May 24, 2002
143
144
145
146
} /* __PHYSFS_platformCvtToDependent */
Sep 29, 2004
Sep 29, 2004
147
148
void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
Sep 18, 2005
Sep 18, 2005
149
150
PHYSFS_EnumFilesCallback callback,
const char *origdir,
Sep 29, 2004
Sep 29, 2004
151
void *callbackdata)
May 24, 2002
May 24, 2002
152
153
154
155
156
157
158
{
DIR *dir;
struct dirent *ent;
int bufsize = 0;
char *buf = NULL;
int dlen = 0;
Sep 29, 2004
Sep 29, 2004
159
if (omitSymLinks) /* !!! FIXME: this malloc sucks. */
May 24, 2002
May 24, 2002
160
161
162
{
dlen = strlen(dirname);
bufsize = dlen + 256;
Mar 14, 2005
Mar 14, 2005
163
buf = (char *) allocator.Malloc(bufsize);
Sep 29, 2004
Sep 29, 2004
164
165
if (buf == NULL)
return;
May 24, 2002
May 24, 2002
166
167
168
169
170
171
172
173
174
175
176
177
strcpy(buf, dirname);
if (buf[dlen - 1] != '/')
{
buf[dlen++] = '/';
buf[dlen] = '\0';
} /* if */
} /* if */
errno = 0;
dir = opendir(dirname);
if (dir == NULL)
{
Mar 24, 2007
Mar 24, 2007
178
allocator.Free(buf);
Sep 29, 2004
Sep 29, 2004
179
return;
May 24, 2002
May 24, 2002
180
181
} /* if */
Jul 23, 2002
Jul 23, 2002
182
while ((ent = readdir(dir)) != NULL)
May 24, 2002
May 24, 2002
183
184
185
186
187
188
189
190
191
{
if (strcmp(ent->d_name, ".") == 0)
continue;
if (strcmp(ent->d_name, "..") == 0)
continue;
if (omitSymLinks)
{
Sep 5, 2010
Sep 5, 2010
192
193
PHYSFS_Stat statbuf;
int exists = 0;
May 24, 2002
May 24, 2002
194
195
196
197
char *p;
int len = strlen(ent->d_name) + dlen + 1;
if (len > bufsize)
{
Mar 14, 2005
Mar 14, 2005
198
p = (char *) allocator.Realloc(buf, len);
May 24, 2002
May 24, 2002
199
200
201
202
203
204
205
if (p == NULL)
continue;
buf = p;
bufsize = len;
} /* if */
strcpy(buf + dlen, ent->d_name);
Sep 5, 2010
Sep 5, 2010
206
207
208
209
210
211
212
213
if (__PHYSFS_platformStat(buf, &exists, &statbuf))
{
if (!exists)
continue;
else if (statbuf.filetype == PHYSFS_FILETYPE_SYMLINK)
continue;
} /* if */
May 24, 2002
May 24, 2002
214
215
} /* if */
Sep 18, 2005
Sep 18, 2005
216
callback(callbackdata, origdir, ent->d_name);
May 24, 2002
May 24, 2002
217
218
} /* while */
Mar 24, 2007
Mar 24, 2007
219
allocator.Free(buf);
May 24, 2002
May 24, 2002
220
221
222
223
224
225
226
227
228
229
closedir(dir);
} /* __PHYSFS_platformEnumerateFiles */
int __PHYSFS_platformMkDir(const char *path)
{
int rc;
errno = 0;
rc = mkdir(path, S_IRWXU);
BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
230
return 1;
May 24, 2002
May 24, 2002
231
232
233
} /* __PHYSFS_platformMkDir */
Jun 2, 2002
Jun 2, 2002
234
static void *doOpen(const char *filename, int mode)
May 24, 2002
May 24, 2002
235
{
Apr 3, 2008
Apr 3, 2008
236
const int appending = (mode & O_APPEND);
Jun 2, 2002
Jun 2, 2002
237
238
int fd;
int *retval;
May 24, 2002
May 24, 2002
239
240
errno = 0;
Apr 3, 2008
Apr 3, 2008
241
242
243
/* O_APPEND doesn't actually behave as we'd like. */
mode &= ~O_APPEND;
Jun 2, 2002
Jun 2, 2002
244
fd = open(filename, mode, S_IRUSR | S_IWUSR);
Jun 23, 2002
Jun 23, 2002
245
BAIL_IF_MACRO(fd < 0, strerror(errno), NULL);
May 24, 2002
May 24, 2002
246
Apr 3, 2008
Apr 3, 2008
247
248
249
250
251
252
253
254
255
if (appending)
{
if (lseek(fd, 0, SEEK_END) < 0)
{
close(fd);
BAIL_MACRO(strerror(errno), NULL);
} /* if */
} /* if */
Mar 14, 2005
Mar 14, 2005
256
retval = (int *) allocator.Malloc(sizeof (int));
Jun 2, 2002
Jun 2, 2002
257
258
259
260
261
262
263
if (retval == NULL)
{
close(fd);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
*retval = fd;
Jan 28, 2010
Jan 28, 2010
264
return ((void *) retval);
May 24, 2002
May 24, 2002
265
266
267
268
269
} /* doOpen */
void *__PHYSFS_platformOpenRead(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
270
return doOpen(filename, O_RDONLY);
May 24, 2002
May 24, 2002
271
272
273
274
275
} /* __PHYSFS_platformOpenRead */
void *__PHYSFS_platformOpenWrite(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
276
return doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC);
May 24, 2002
May 24, 2002
277
278
279
280
281
} /* __PHYSFS_platformOpenWrite */
void *__PHYSFS_platformOpenAppend(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
282
return doOpen(filename, O_WRONLY | O_CREAT | O_APPEND);
May 24, 2002
May 24, 2002
283
284
285
286
} /* __PHYSFS_platformOpenAppend */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
Aug 21, 2010
Aug 21, 2010
287
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
288
{
Aug 29, 2010
Aug 29, 2010
289
const int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
290
ssize_t rc = 0;
May 24, 2002
May 24, 2002
291
Aug 21, 2010
Aug 21, 2010
292
BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
Jun 2, 2002
Jun 2, 2002
293
Aug 21, 2010
Aug 21, 2010
294
295
296
297
298
rc = read(fd, buffer, (size_t) len);
BAIL_IF_MACRO(rc == -1, strerror(errno), (PHYSFS_sint64) rc);
assert(rc >= 0);
assert(rc <= len);
return (PHYSFS_sint64) rc;
May 24, 2002
May 24, 2002
299
300
301
302
} /* __PHYSFS_platformRead */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
Aug 21, 2010
Aug 21, 2010
303
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
304
{
Aug 29, 2010
Aug 29, 2010
305
const int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
306
ssize_t rc = 0;
Jun 2, 2002
Jun 2, 2002
307
Aug 21, 2010
Aug 21, 2010
308
BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
Jun 2, 2002
Jun 2, 2002
309
Aug 21, 2010
Aug 21, 2010
310
311
312
313
314
rc = write(fd, (void *) buffer, (size_t) len);
BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
assert(rc >= 0);
assert(rc <= len);
return (PHYSFS_sint64) rc;
May 24, 2002
May 24, 2002
315
316
317
318
319
} /* __PHYSFS_platformWrite */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
{
Aug 29, 2010
Aug 29, 2010
320
const int fd = *((int *) opaque);
May 24, 2002
May 24, 2002
321
Jun 6, 2002
Jun 6, 2002
322
323
324
325
326
327
328
329
330
#ifdef PHYSFS_HAVE_LLSEEK
unsigned long offset_high = ((pos >> 32) & 0xFFFFFFFF);
unsigned long offset_low = (pos & 0xFFFFFFFF);
loff_t retoffset;
int rc = llseek(fd, offset_high, offset_low, &retoffset, SEEK_SET);
BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
#else
BAIL_IF_MACRO(lseek(fd, (int) pos, SEEK_SET) == -1, strerror(errno), 0);
#endif
May 24, 2002
May 24, 2002
331
Jan 28, 2010
Jan 28, 2010
332
return 1;
May 24, 2002
May 24, 2002
333
334
335
336
337
} /* __PHYSFS_platformSeek */
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
338
const int fd = *((int *) opaque);
Jun 6, 2002
Jun 6, 2002
339
340
341
342
343
344
345
346
347
348
349
350
PHYSFS_sint64 retval;
#ifdef PHYSFS_HAVE_LLSEEK
loff_t retoffset;
int rc = llseek(fd, 0, &retoffset, SEEK_CUR);
BAIL_IF_MACRO(rc == -1, strerror(errno), -1);
retval = (PHYSFS_sint64) retoffset;
#else
retval = (PHYSFS_sint64) lseek(fd, 0, SEEK_CUR);
BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
#endif
Jan 28, 2010
Jan 28, 2010
351
return retval;
May 24, 2002
May 24, 2002
352
353
354
355
356
} /* __PHYSFS_platformTell */
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
357
const int fd = *((int *) opaque);
May 24, 2002
May 24, 2002
358
struct stat statbuf;
Jun 2, 2002
Jun 2, 2002
359
BAIL_IF_MACRO(fstat(fd, &statbuf) == -1, strerror(errno), -1);
Jan 28, 2010
Jan 28, 2010
360
return ((PHYSFS_sint64) statbuf.st_size);
May 24, 2002
May 24, 2002
361
362
363
364
365
} /* __PHYSFS_platformFileLength */
int __PHYSFS_platformEOF(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
366
367
const PHYSFS_sint64 pos = __PHYSFS_platformTell(opaque);
const PHYSFS_sint64 len = __PHYSFS_platformFileLength(opaque);
Jan 28, 2010
Jan 28, 2010
368
return (pos >= len);
May 24, 2002
May 24, 2002
369
370
371
372
373
} /* __PHYSFS_platformEOF */
int __PHYSFS_platformFlush(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
374
const int fd = *((int *) opaque);
Jun 2, 2002
Jun 2, 2002
375
BAIL_IF_MACRO(fsync(fd) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
376
return 1;
May 24, 2002
May 24, 2002
377
378
379
} /* __PHYSFS_platformFlush */
Aug 30, 2010
Aug 30, 2010
380
void __PHYSFS_platformClose(void *opaque)
May 24, 2002
May 24, 2002
381
{
Aug 30, 2010
Aug 30, 2010
382
383
const int fd = *((int *) opaque);
(void) close(fd); /* we don't check this. You should have used flush! */
Mar 14, 2005
Mar 14, 2005
384
allocator.Free(opaque);
May 24, 2002
May 24, 2002
385
386
387
388
389
390
} /* __PHYSFS_platformClose */
int __PHYSFS_platformDelete(const char *path)
{
BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
391
return 1;
May 24, 2002
May 24, 2002
392
393
} /* __PHYSFS_platformDelete */
May 25, 2002
May 25, 2002
394
Feb 15, 2010
Feb 15, 2010
395
396
397
398
399
400
401
402
403
404
405
406
int __PHYSFS_platformStat(const char *filename, int *exists, PHYSFS_Stat *st)
{
struct stat statbuf;
/* !!! FIXME: lstat()? */
if (stat(filename, &statbuf))
{
if (errno == ENOENT)
{
*exists = 0;
return 0;
} /* if */
Aug 21, 2010
Aug 21, 2010
407
408
BAIL_MACRO(strerror(errno), 0);
Feb 15, 2010
Feb 15, 2010
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
} /* if */
if (S_ISREG(statbuf.st_mode))
{
st->filetype = PHYSFS_FILETYPE_REGULAR;
st->filesize = statbuf.st_size;
} /* if */
else if(S_ISDIR(statbuf.st_mode))
{
st->filetype = PHYSFS_FILETYPE_DIRECTORY;
st->filesize = 0;
} /* else if */
else
{
st->filetype = PHYSFS_FILETYPE_OTHER;
st->filesize = statbuf.st_size;
} /* else */
st->modtime = statbuf.st_mtime;
st->createtime = statbuf.st_ctime;
st->accesstime = statbuf.st_atime;
/* !!! FIXME: maybe we should just report full permissions? */
st->readonly = access(filename, W_OK);
Aug 21, 2010
Aug 21, 2010
435
return 1;
Feb 15, 2010
Feb 15, 2010
436
437
} /* __PHYSFS_platformStat */
Mar 11, 2007
Mar 11, 2007
438
#endif /* PHYSFS_PLATFORM_POSIX */
Jun 29, 2002
Jun 29, 2002
439
May 24, 2002
May 24, 2002
440
/* end of posix.c ... */