Skip to content

Latest commit

 

History

History
465 lines (364 loc) · 11.3 KB

platform_posix.c

File metadata and controls

465 lines (364 loc) · 11.3 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
#include <unistd.h>
Jun 2, 2002
Jun 2, 2002
15
#include <ctype.h>
May 24, 2002
May 24, 2002
16
17
#include <sys/types.h>
#include <sys/stat.h>
Jun 2, 2002
Jun 2, 2002
18
#include <pwd.h>
May 24, 2002
May 24, 2002
19
20
#include <dirent.h>
#include <errno.h>
Jun 2, 2002
Jun 2, 2002
21
#include <fcntl.h>
May 24, 2002
May 24, 2002
22
Jul 25, 2011
Jul 25, 2011
23
24
25
26
#if ((!defined PHYSFS_NO_THREAD_SUPPORT) && (!defined PHYSFS_PLATFORM_BEOS))
#include <pthread.h>
#endif
May 24, 2002
May 24, 2002
27
28
29
30
31
32
33
34
35
#include "physfs_internal.h"
char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname)
{
const char *envr = getenv(varname);
char *retval = NULL;
if (envr != NULL)
{
Mar 14, 2005
Mar 14, 2005
36
retval = (char *) allocator.Malloc(strlen(envr) + 1);
May 24, 2002
May 24, 2002
37
38
39
40
if (retval != NULL)
strcpy(retval, envr);
} /* if */
Jan 28, 2010
Jan 28, 2010
41
return retval;
May 24, 2002
May 24, 2002
42
43
44
45
46
47
48
49
50
51
52
53
} /* __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
54
retval = (char *) allocator.Malloc(strlen(pw->pw_name) + 1);
May 24, 2002
May 24, 2002
55
56
57
58
if (retval != NULL)
strcpy(retval, pw->pw_name);
} /* if */
Jan 28, 2010
Jan 28, 2010
59
return retval;
May 24, 2002
May 24, 2002
60
61
62
63
64
65
66
67
68
69
70
71
} /* 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
72
retval = (char *) allocator.Malloc(strlen(pw->pw_dir) + 1);
May 24, 2002
May 24, 2002
73
74
75
76
if (retval != NULL)
strcpy(retval, pw->pw_dir);
} /* if */
Jan 28, 2010
Jan 28, 2010
77
return retval;
May 24, 2002
May 24, 2002
78
79
80
81
82
83
84
85
} /* getUserDirByUID */
char *__PHYSFS_platformGetUserName(void)
{
char *retval = getUserNameByUID();
if (retval == NULL)
retval = __PHYSFS_platformCopyEnvironmentVariable("USER");
Jan 28, 2010
Jan 28, 2010
86
return retval;
May 24, 2002
May 24, 2002
87
88
89
90
91
92
} /* __PHYSFS_platformGetUserName */
char *__PHYSFS_platformGetUserDir(void)
{
char *retval = __PHYSFS_platformCopyEnvironmentVariable("HOME");
Mar 21, 2010
Mar 21, 2010
93
94
95
96
97
98
99
100
101
102
103
104
/* 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
105
106
if (retval == NULL)
retval = getUserDirByUID();
Mar 21, 2010
Mar 21, 2010
107
Jan 28, 2010
Jan 28, 2010
108
return retval;
May 24, 2002
May 24, 2002
109
110
111
} /* __PHYSFS_platformGetUserDir */
Sep 29, 2004
Sep 29, 2004
112
113
void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
Sep 18, 2005
Sep 18, 2005
114
115
PHYSFS_EnumFilesCallback callback,
const char *origdir,
Sep 29, 2004
Sep 29, 2004
116
void *callbackdata)
May 24, 2002
May 24, 2002
117
118
119
120
121
122
123
{
DIR *dir;
struct dirent *ent;
int bufsize = 0;
char *buf = NULL;
int dlen = 0;
Sep 29, 2004
Sep 29, 2004
124
if (omitSymLinks) /* !!! FIXME: this malloc sucks. */
May 24, 2002
May 24, 2002
125
126
127
{
dlen = strlen(dirname);
bufsize = dlen + 256;
Mar 14, 2005
Mar 14, 2005
128
buf = (char *) allocator.Malloc(bufsize);
Sep 29, 2004
Sep 29, 2004
129
130
if (buf == NULL)
return;
May 24, 2002
May 24, 2002
131
132
133
134
135
136
137
138
139
140
141
142
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
143
allocator.Free(buf);
Sep 29, 2004
Sep 29, 2004
144
return;
May 24, 2002
May 24, 2002
145
146
} /* if */
Jul 23, 2002
Jul 23, 2002
147
while ((ent = readdir(dir)) != NULL)
May 24, 2002
May 24, 2002
148
149
150
151
152
153
154
155
156
{
if (strcmp(ent->d_name, ".") == 0)
continue;
if (strcmp(ent->d_name, "..") == 0)
continue;
if (omitSymLinks)
{
Sep 5, 2010
Sep 5, 2010
157
158
PHYSFS_Stat statbuf;
int exists = 0;
May 24, 2002
May 24, 2002
159
160
161
162
char *p;
int len = strlen(ent->d_name) + dlen + 1;
if (len > bufsize)
{
Mar 14, 2005
Mar 14, 2005
163
p = (char *) allocator.Realloc(buf, len);
May 24, 2002
May 24, 2002
164
165
166
167
168
169
170
if (p == NULL)
continue;
buf = p;
bufsize = len;
} /* if */
strcpy(buf + dlen, ent->d_name);
Sep 5, 2010
Sep 5, 2010
171
Mar 9, 2012
Mar 9, 2012
172
173
174
175
176
177
if (!__PHYSFS_platformStat(buf, &exists, &statbuf))
continue;
else if (!exists)
continue; /* probably can't happen, but just in case. */
else if (statbuf.filetype == PHYSFS_FILETYPE_SYMLINK)
continue;
May 24, 2002
May 24, 2002
178
179
} /* if */
Sep 18, 2005
Sep 18, 2005
180
callback(callbackdata, origdir, ent->d_name);
May 24, 2002
May 24, 2002
181
182
} /* while */
Mar 24, 2007
Mar 24, 2007
183
allocator.Free(buf);
May 24, 2002
May 24, 2002
184
185
186
187
188
189
190
191
192
193
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
194
return 1;
May 24, 2002
May 24, 2002
195
196
197
} /* __PHYSFS_platformMkDir */
Jun 2, 2002
Jun 2, 2002
198
static void *doOpen(const char *filename, int mode)
May 24, 2002
May 24, 2002
199
{
Apr 3, 2008
Apr 3, 2008
200
const int appending = (mode & O_APPEND);
Jun 2, 2002
Jun 2, 2002
201
202
int fd;
int *retval;
May 24, 2002
May 24, 2002
203
204
errno = 0;
Apr 3, 2008
Apr 3, 2008
205
206
207
/* O_APPEND doesn't actually behave as we'd like. */
mode &= ~O_APPEND;
Jun 2, 2002
Jun 2, 2002
208
fd = open(filename, mode, S_IRUSR | S_IWUSR);
Jun 23, 2002
Jun 23, 2002
209
BAIL_IF_MACRO(fd < 0, strerror(errno), NULL);
May 24, 2002
May 24, 2002
210
Apr 3, 2008
Apr 3, 2008
211
212
213
214
215
216
217
218
219
if (appending)
{
if (lseek(fd, 0, SEEK_END) < 0)
{
close(fd);
BAIL_MACRO(strerror(errno), NULL);
} /* if */
} /* if */
Mar 14, 2005
Mar 14, 2005
220
retval = (int *) allocator.Malloc(sizeof (int));
Jun 2, 2002
Jun 2, 2002
221
222
223
224
225
226
227
if (retval == NULL)
{
close(fd);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
*retval = fd;
Jan 28, 2010
Jan 28, 2010
228
return ((void *) retval);
May 24, 2002
May 24, 2002
229
230
231
232
233
} /* doOpen */
void *__PHYSFS_platformOpenRead(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
234
return doOpen(filename, O_RDONLY);
May 24, 2002
May 24, 2002
235
236
237
238
239
} /* __PHYSFS_platformOpenRead */
void *__PHYSFS_platformOpenWrite(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
240
return doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC);
May 24, 2002
May 24, 2002
241
242
243
244
245
} /* __PHYSFS_platformOpenWrite */
void *__PHYSFS_platformOpenAppend(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
246
return doOpen(filename, O_WRONLY | O_CREAT | O_APPEND);
May 24, 2002
May 24, 2002
247
248
249
250
} /* __PHYSFS_platformOpenAppend */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
Aug 21, 2010
Aug 21, 2010
251
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
252
{
Aug 29, 2010
Aug 29, 2010
253
const int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
254
ssize_t rc = 0;
May 24, 2002
May 24, 2002
255
Aug 21, 2010
Aug 21, 2010
256
BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
Jun 2, 2002
Jun 2, 2002
257
Aug 21, 2010
Aug 21, 2010
258
259
260
261
262
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
263
264
265
266
} /* __PHYSFS_platformRead */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
Aug 21, 2010
Aug 21, 2010
267
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
268
{
Aug 29, 2010
Aug 29, 2010
269
const int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
270
ssize_t rc = 0;
Jun 2, 2002
Jun 2, 2002
271
Aug 21, 2010
Aug 21, 2010
272
BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
Jun 2, 2002
Jun 2, 2002
273
Aug 21, 2010
Aug 21, 2010
274
275
276
277
278
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
279
280
281
282
283
} /* __PHYSFS_platformWrite */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
{
Aug 29, 2010
Aug 29, 2010
284
const int fd = *((int *) opaque);
Mar 18, 2012
Mar 18, 2012
285
BAIL_IF_MACRO(lseek(fd, (off_t) pos, SEEK_SET) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
286
return 1;
May 24, 2002
May 24, 2002
287
288
289
290
291
} /* __PHYSFS_platformSeek */
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
292
const int fd = *((int *) opaque);
Jun 6, 2002
Jun 6, 2002
293
PHYSFS_sint64 retval;
Mar 18, 2012
Mar 18, 2012
294
295
retval = (PHYSFS_sint64) lseek(fd, 0, SEEK_CUR);
BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
Jan 28, 2010
Jan 28, 2010
296
return retval;
May 24, 2002
May 24, 2002
297
298
299
300
301
} /* __PHYSFS_platformTell */
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
302
const int fd = *((int *) opaque);
May 24, 2002
May 24, 2002
303
struct stat statbuf;
Jun 2, 2002
Jun 2, 2002
304
BAIL_IF_MACRO(fstat(fd, &statbuf) == -1, strerror(errno), -1);
Jan 28, 2010
Jan 28, 2010
305
return ((PHYSFS_sint64) statbuf.st_size);
May 24, 2002
May 24, 2002
306
307
308
309
310
} /* __PHYSFS_platformFileLength */
int __PHYSFS_platformFlush(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
311
const int fd = *((int *) opaque);
Jun 2, 2002
Jun 2, 2002
312
BAIL_IF_MACRO(fsync(fd) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
313
return 1;
May 24, 2002
May 24, 2002
314
315
316
} /* __PHYSFS_platformFlush */
Aug 30, 2010
Aug 30, 2010
317
void __PHYSFS_platformClose(void *opaque)
May 24, 2002
May 24, 2002
318
{
Aug 30, 2010
Aug 30, 2010
319
320
const int fd = *((int *) opaque);
(void) close(fd); /* we don't check this. You should have used flush! */
Mar 14, 2005
Mar 14, 2005
321
allocator.Free(opaque);
May 24, 2002
May 24, 2002
322
323
324
325
326
327
} /* __PHYSFS_platformClose */
int __PHYSFS_platformDelete(const char *path)
{
BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
328
return 1;
May 24, 2002
May 24, 2002
329
330
} /* __PHYSFS_platformDelete */
May 25, 2002
May 25, 2002
331
Feb 15, 2010
Feb 15, 2010
332
333
334
335
int __PHYSFS_platformStat(const char *filename, int *exists, PHYSFS_Stat *st)
{
struct stat statbuf;
Mar 9, 2012
Mar 9, 2012
336
if (lstat(filename, &statbuf) == -1)
Feb 15, 2010
Feb 15, 2010
337
{
Mar 9, 2012
Mar 9, 2012
338
*exists = (errno == ENOENT);
Aug 21, 2010
Aug 21, 2010
339
BAIL_MACRO(strerror(errno), 0);
Feb 15, 2010
Feb 15, 2010
340
341
} /* if */
Jun 22, 2011
Jun 22, 2011
342
343
*exists = 1;
Feb 15, 2010
Feb 15, 2010
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
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
368
return 1;
Feb 15, 2010
Feb 15, 2010
369
370
} /* __PHYSFS_platformStat */
Jul 25, 2011
Jul 25, 2011
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
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
435
436
437
438
439
440
441
442
443
444
445
446
#ifndef PHYSFS_PLATFORM_BEOS /* BeOS has its own code in platform_beos.cpp */
#if (defined PHYSFS_NO_THREAD_SUPPORT)
void *__PHYSFS_platformGetThreadID(void) { return ((void *) 0x0001); }
void *__PHYSFS_platformCreateMutex(void) { return ((void *) 0x0001); }
void __PHYSFS_platformDestroyMutex(void *mutex) {}
int __PHYSFS_platformGrabMutex(void *mutex) { return 1; }
void __PHYSFS_platformReleaseMutex(void *mutex) {}
#else
typedef struct
{
pthread_mutex_t mutex;
pthread_t owner;
PHYSFS_uint32 count;
} PthreadMutex;
void *__PHYSFS_platformGetThreadID(void)
{
return ( (void *) ((size_t) pthread_self()) );
} /* __PHYSFS_platformGetThreadID */
void *__PHYSFS_platformCreateMutex(void)
{
int rc;
PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex));
BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
rc = pthread_mutex_init(&m->mutex, NULL);
if (rc != 0)
{
allocator.Free(m);
BAIL_MACRO(strerror(rc), NULL);
} /* if */
m->count = 0;
m->owner = (pthread_t) 0xDEADBEEF;
return ((void *) m);
} /* __PHYSFS_platformCreateMutex */
void __PHYSFS_platformDestroyMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
/* Destroying a locked mutex is a bug, but we'll try to be helpful. */
if ((m->owner == pthread_self()) && (m->count > 0))
pthread_mutex_unlock(&m->mutex);
pthread_mutex_destroy(&m->mutex);
allocator.Free(m);
} /* __PHYSFS_platformDestroyMutex */
int __PHYSFS_platformGrabMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
pthread_t tid = pthread_self();
if (m->owner != tid)
{
if (pthread_mutex_lock(&m->mutex) != 0)
return 0;
m->owner = tid;
} /* if */
m->count++;
return 1;
} /* __PHYSFS_platformGrabMutex */
void __PHYSFS_platformReleaseMutex(void *mutex)
{
PthreadMutex *m = (PthreadMutex *) mutex;
Mar 20, 2012
Mar 20, 2012
447
448
assert(m->owner == pthread_self()); /* catch programming errors. */
assert(m->count > 0); /* catch programming errors. */
Jul 25, 2011
Jul 25, 2011
449
450
451
452
453
454
455
456
457
458
459
460
461
if (m->owner == pthread_self())
{
if (--m->count == 0)
{
m->owner = (pthread_t) 0xDEADBEEF;
pthread_mutex_unlock(&m->mutex);
} /* if */
} /* if */
} /* __PHYSFS_platformReleaseMutex */
#endif /* !PHYSFS_NO_THREAD_SUPPORT */
#endif /* !PHYSFS_PLATFORM_BEOS */
Mar 11, 2007
Mar 11, 2007
462
#endif /* PHYSFS_PLATFORM_POSIX */
Jun 29, 2002
Jun 29, 2002
463
May 24, 2002
May 24, 2002
464
/* end of posix.c ... */