Skip to content

Latest commit

 

History

History
419 lines (332 loc) · 10.5 KB

platform_posix.c

File metadata and controls

419 lines (332 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 20, 2012
Mar 20, 2012
9
10
/* !!! FIXME: check for EINTR? */
Mar 11, 2007
Mar 11, 2007
11
12
13
14
#define __PHYSICSFS_INTERNAL__
#include "physfs_platforms.h"
#ifdef PHYSFS_PLATFORM_POSIX
Jun 29, 2002
Jun 29, 2002
15
May 24, 2002
May 24, 2002
16
#include <unistd.h>
Jun 2, 2002
Jun 2, 2002
17
#include <ctype.h>
May 24, 2002
May 24, 2002
18
19
#include <sys/types.h>
#include <sys/stat.h>
Jun 2, 2002
Jun 2, 2002
20
#include <pwd.h>
May 24, 2002
May 24, 2002
21
22
#include <dirent.h>
#include <errno.h>
Jun 2, 2002
Jun 2, 2002
23
#include <fcntl.h>
Jul 25, 2011
Jul 25, 2011
24
25
#include <pthread.h>
May 24, 2002
May 24, 2002
26
27
#include "physfs_internal.h"
Mar 20, 2012
Mar 20, 2012
28
29
30
31
32
33
34
35
36
37
38
39
40
static PHYSFS_ErrorCode errcodeFromErrnoError(const int err)
{
switch (err)
{
case 0: return PHYSFS_ERR_OK;
case EACCES: return PHYSFS_ERR_PERMISSION;
case EPERM: return PHYSFS_ERR_PERMISSION;
case EDQUOT: return PHYSFS_ERR_NO_SPACE;
case EIO: return PHYSFS_ERR_IO;
case ELOOP: return PHYSFS_ERR_SYMLINK_LOOP;
case EMLINK: return PHYSFS_ERR_NO_SPACE;
case ENAMETOOLONG: return PHYSFS_ERR_BAD_FILENAME;
Nov 28, 2012
Nov 28, 2012
41
case ENOENT: return PHYSFS_ERR_NOT_FOUND;
Mar 20, 2012
Mar 20, 2012
42
case ENOSPC: return PHYSFS_ERR_NO_SPACE;
Nov 28, 2012
Nov 28, 2012
43
case ENOTDIR: return PHYSFS_ERR_NOT_FOUND;
Mar 20, 2012
Mar 20, 2012
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
case EISDIR: return PHYSFS_ERR_NOT_A_FILE;
case EROFS: return PHYSFS_ERR_READ_ONLY;
case ETXTBSY: return PHYSFS_ERR_BUSY;
case EBUSY: return PHYSFS_ERR_BUSY;
case ENOMEM: return PHYSFS_ERR_OUT_OF_MEMORY;
case ENOTEMPTY: return PHYSFS_ERR_DIR_NOT_EMPTY;
default: return PHYSFS_ERR_OS_ERROR;
} /* switch */
} /* errcodeFromErrnoError */
static inline PHYSFS_ErrorCode errcodeFromErrno(void)
{
return errcodeFromErrnoError(errno);
} /* errcodeFromErrno */
May 24, 2002
May 24, 2002
61
62
63
64
65
66
67
static char *getUserDirByUID(void)
{
uid_t uid = getuid();
struct passwd *pw;
char *retval = NULL;
pw = getpwuid(uid);
Mar 24, 2012
Mar 24, 2012
68
if ((pw != NULL) && (pw->pw_dir != NULL) && (*pw->pw_dir != '\0'))
May 24, 2002
May 24, 2002
69
{
Mar 24, 2012
Mar 24, 2012
70
71
72
const size_t dlen = strlen(pw->pw_dir);
const size_t add_dirsep = (pw->pw_dir[dlen-1] != '/') ? 1 : 0;
retval = (char *) allocator.Malloc(dlen + 1 + add_dirsep);
May 24, 2002
May 24, 2002
73
if (retval != NULL)
Mar 24, 2012
Mar 24, 2012
74
{
May 24, 2002
May 24, 2002
75
strcpy(retval, pw->pw_dir);
Mar 24, 2012
Mar 24, 2012
76
77
78
79
80
81
if (add_dirsep)
{
retval[dlen] = '/';
retval[dlen+1] = '\0';
} /* if */
} /* if */
May 24, 2002
May 24, 2002
82
83
} /* if */
Jan 28, 2010
Jan 28, 2010
84
return retval;
May 24, 2002
May 24, 2002
85
86
87
} /* getUserDirByUID */
Mar 22, 2012
Mar 22, 2012
88
char *__PHYSFS_platformCalcUserDir(void)
May 24, 2002
May 24, 2002
89
{
Mar 24, 2012
Mar 24, 2012
90
91
char *retval = NULL;
char *envr = getenv("HOME");
Mar 21, 2010
Mar 21, 2010
92
93
/* if the environment variable was set, make sure it's really a dir. */
Mar 24, 2012
Mar 24, 2012
94
if (envr != NULL)
Mar 21, 2010
Mar 21, 2010
95
96
{
struct stat statbuf;
Mar 24, 2012
Mar 24, 2012
97
if ((stat(envr, &statbuf) != -1) && (S_ISDIR(statbuf.st_mode)))
Mar 21, 2010
Mar 21, 2010
98
{
Mar 24, 2012
Mar 24, 2012
99
100
101
102
103
104
105
106
107
108
109
110
const size_t envrlen = strlen(envr);
const size_t add_dirsep = (envr[envrlen-1] != '/') ? 1 : 0;
retval = allocator.Malloc(envrlen + 1 + add_dirsep);
if (retval)
{
strcpy(retval, envr);
if (add_dirsep)
{
retval[envrlen] = '/';
retval[envrlen+1] = '\0';
} /* if */
} /* if */
Mar 21, 2010
Mar 21, 2010
111
112
113
} /* if */
} /* if */
May 24, 2002
May 24, 2002
114
115
if (retval == NULL)
retval = getUserDirByUID();
Mar 21, 2010
Mar 21, 2010
116
Jan 28, 2010
Jan 28, 2010
117
return retval;
Mar 22, 2012
Mar 22, 2012
118
} /* __PHYSFS_platformCalcUserDir */
May 24, 2002
May 24, 2002
119
120
Sep 29, 2004
Sep 29, 2004
121
void __PHYSFS_platformEnumerateFiles(const char *dirname,
Sep 18, 2005
Sep 18, 2005
122
123
PHYSFS_EnumFilesCallback callback,
const char *origdir,
Sep 29, 2004
Sep 29, 2004
124
void *callbackdata)
May 24, 2002
May 24, 2002
125
126
127
128
129
130
131
132
133
{
DIR *dir;
struct dirent *ent;
char *buf = NULL;
errno = 0;
dir = opendir(dirname);
if (dir == NULL)
{
Mar 24, 2007
Mar 24, 2007
134
allocator.Free(buf);
Sep 29, 2004
Sep 29, 2004
135
return;
May 24, 2002
May 24, 2002
136
137
} /* if */
Jul 23, 2002
Jul 23, 2002
138
while ((ent = readdir(dir)) != NULL)
May 24, 2002
May 24, 2002
139
140
141
{
if (strcmp(ent->d_name, ".") == 0)
continue;
Nov 29, 2012
Nov 29, 2012
142
else if (strcmp(ent->d_name, "..") == 0)
May 24, 2002
May 24, 2002
143
144
continue;
Sep 18, 2005
Sep 18, 2005
145
callback(callbackdata, origdir, ent->d_name);
May 24, 2002
May 24, 2002
146
147
} /* while */
Mar 24, 2007
Mar 24, 2007
148
allocator.Free(buf);
May 24, 2002
May 24, 2002
149
150
151
152
153
154
closedir(dir);
} /* __PHYSFS_platformEnumerateFiles */
int __PHYSFS_platformMkDir(const char *path)
{
Mar 20, 2012
Mar 20, 2012
155
const int rc = mkdir(path, S_IRWXU);
Jul 6, 2017
Jul 6, 2017
156
BAIL_IF(rc == -1, errcodeFromErrno(), 0);
Jan 28, 2010
Jan 28, 2010
157
return 1;
May 24, 2002
May 24, 2002
158
159
160
} /* __PHYSFS_platformMkDir */
Jun 2, 2002
Jun 2, 2002
161
static void *doOpen(const char *filename, int mode)
May 24, 2002
May 24, 2002
162
{
Apr 3, 2008
Apr 3, 2008
163
const int appending = (mode & O_APPEND);
Jun 2, 2002
Jun 2, 2002
164
165
int fd;
int *retval;
May 24, 2002
May 24, 2002
166
167
errno = 0;
Apr 3, 2008
Apr 3, 2008
168
169
170
/* O_APPEND doesn't actually behave as we'd like. */
mode &= ~O_APPEND;
Jun 2, 2002
Jun 2, 2002
171
fd = open(filename, mode, S_IRUSR | S_IWUSR);
Jul 6, 2017
Jul 6, 2017
172
BAIL_IF(fd < 0, errcodeFromErrno(), NULL);
May 24, 2002
May 24, 2002
173
Apr 3, 2008
Apr 3, 2008
174
175
176
177
if (appending)
{
if (lseek(fd, 0, SEEK_END) < 0)
{
Mar 20, 2012
Mar 20, 2012
178
const int err = errno;
Apr 3, 2008
Apr 3, 2008
179
close(fd);
Jul 6, 2017
Jul 6, 2017
180
BAIL(errcodeFromErrnoError(err), NULL);
Apr 3, 2008
Apr 3, 2008
181
182
183
} /* if */
} /* if */
Mar 14, 2005
Mar 14, 2005
184
retval = (int *) allocator.Malloc(sizeof (int));
Mar 20, 2012
Mar 20, 2012
185
if (!retval)
Jun 2, 2002
Jun 2, 2002
186
187
{
close(fd);
Jul 6, 2017
Jul 6, 2017
188
BAIL(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
Jun 2, 2002
Jun 2, 2002
189
190
191
} /* if */
*retval = fd;
Jan 28, 2010
Jan 28, 2010
192
return ((void *) retval);
May 24, 2002
May 24, 2002
193
194
195
196
197
} /* doOpen */
void *__PHYSFS_platformOpenRead(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
198
return doOpen(filename, O_RDONLY);
May 24, 2002
May 24, 2002
199
200
201
202
203
} /* __PHYSFS_platformOpenRead */
void *__PHYSFS_platformOpenWrite(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
204
return doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC);
May 24, 2002
May 24, 2002
205
206
207
208
209
} /* __PHYSFS_platformOpenWrite */
void *__PHYSFS_platformOpenAppend(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
210
return doOpen(filename, O_WRONLY | O_CREAT | O_APPEND);
May 24, 2002
May 24, 2002
211
212
213
214
} /* __PHYSFS_platformOpenAppend */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
Aug 21, 2010
Aug 21, 2010
215
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
216
{
Aug 29, 2010
Aug 29, 2010
217
const int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
218
ssize_t rc = 0;
May 24, 2002
May 24, 2002
219
Mar 20, 2012
Mar 20, 2012
220
if (!__PHYSFS_ui64FitsAddressSpace(len))
Jul 6, 2017
Jul 6, 2017
221
BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
Jun 2, 2002
Jun 2, 2002
222
Aug 21, 2010
Aug 21, 2010
223
rc = read(fd, buffer, (size_t) len);
Jul 6, 2017
Jul 6, 2017
224
BAIL_IF(rc == -1, errcodeFromErrno(), -1);
Aug 21, 2010
Aug 21, 2010
225
226
227
assert(rc >= 0);
assert(rc <= len);
return (PHYSFS_sint64) rc;
May 24, 2002
May 24, 2002
228
229
230
231
} /* __PHYSFS_platformRead */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
Aug 21, 2010
Aug 21, 2010
232
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
233
{
Aug 29, 2010
Aug 29, 2010
234
const int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
235
ssize_t rc = 0;
Jun 2, 2002
Jun 2, 2002
236
Mar 20, 2012
Mar 20, 2012
237
if (!__PHYSFS_ui64FitsAddressSpace(len))
Jul 6, 2017
Jul 6, 2017
238
BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
Jun 2, 2002
Jun 2, 2002
239
Aug 21, 2010
Aug 21, 2010
240
rc = write(fd, (void *) buffer, (size_t) len);
Jul 6, 2017
Jul 6, 2017
241
BAIL_IF(rc == -1, errcodeFromErrno(), rc);
Aug 21, 2010
Aug 21, 2010
242
243
244
assert(rc >= 0);
assert(rc <= len);
return (PHYSFS_sint64) rc;
May 24, 2002
May 24, 2002
245
246
247
248
249
} /* __PHYSFS_platformWrite */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
{
Aug 29, 2010
Aug 29, 2010
250
const int fd = *((int *) opaque);
Mar 20, 2012
Mar 20, 2012
251
const int rc = lseek(fd, (off_t) pos, SEEK_SET);
Jul 6, 2017
Jul 6, 2017
252
BAIL_IF(rc == -1, errcodeFromErrno(), 0);
Jan 28, 2010
Jan 28, 2010
253
return 1;
May 24, 2002
May 24, 2002
254
255
256
257
258
} /* __PHYSFS_platformSeek */
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
259
const int fd = *((int *) opaque);
Jun 6, 2002
Jun 6, 2002
260
PHYSFS_sint64 retval;
Mar 18, 2012
Mar 18, 2012
261
retval = (PHYSFS_sint64) lseek(fd, 0, SEEK_CUR);
Jul 6, 2017
Jul 6, 2017
262
BAIL_IF(retval == -1, errcodeFromErrno(), -1);
Jan 28, 2010
Jan 28, 2010
263
return retval;
May 24, 2002
May 24, 2002
264
265
266
267
268
} /* __PHYSFS_platformTell */
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
269
const int fd = *((int *) opaque);
May 24, 2002
May 24, 2002
270
struct stat statbuf;
Jul 6, 2017
Jul 6, 2017
271
BAIL_IF(fstat(fd, &statbuf) == -1, errcodeFromErrno(), -1);
Jan 28, 2010
Jan 28, 2010
272
return ((PHYSFS_sint64) statbuf.st_size);
May 24, 2002
May 24, 2002
273
274
275
276
277
} /* __PHYSFS_platformFileLength */
int __PHYSFS_platformFlush(void *opaque)
{
Aug 29, 2010
Aug 29, 2010
278
const int fd = *((int *) opaque);
Aug 22, 2013
Aug 22, 2013
279
if ((fcntl(fd, F_GETFL) & O_ACCMODE) != O_RDONLY)
Jul 6, 2017
Jul 6, 2017
280
BAIL_IF(fsync(fd) == -1, errcodeFromErrno(), 0);
Jan 28, 2010
Jan 28, 2010
281
return 1;
May 24, 2002
May 24, 2002
282
283
284
} /* __PHYSFS_platformFlush */
Aug 30, 2010
Aug 30, 2010
285
void __PHYSFS_platformClose(void *opaque)
May 24, 2002
May 24, 2002
286
{
Aug 30, 2010
Aug 30, 2010
287
288
const int fd = *((int *) opaque);
(void) close(fd); /* we don't check this. You should have used flush! */
Mar 14, 2005
Mar 14, 2005
289
allocator.Free(opaque);
May 24, 2002
May 24, 2002
290
291
292
293
294
} /* __PHYSFS_platformClose */
int __PHYSFS_platformDelete(const char *path)
{
Jul 6, 2017
Jul 6, 2017
295
BAIL_IF(remove(path) == -1, errcodeFromErrno(), 0);
Jan 28, 2010
Jan 28, 2010
296
return 1;
May 24, 2002
May 24, 2002
297
298
} /* __PHYSFS_platformDelete */
May 25, 2002
May 25, 2002
299
Nov 30, 2012
Nov 30, 2012
300
int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *st)
Feb 15, 2010
Feb 15, 2010
301
302
303
{
struct stat statbuf;
Jul 6, 2017
Jul 6, 2017
304
BAIL_IF(lstat(filename, &statbuf) == -1, errcodeFromErrno(), 0);
Jun 22, 2011
Jun 22, 2011
305
Feb 15, 2010
Feb 15, 2010
306
307
308
309
310
311
312
313
314
315
316
317
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 */
Nov 29, 2012
Nov 29, 2012
318
319
320
321
322
323
else if(S_ISLNK(statbuf.st_mode))
{
st->filetype = PHYSFS_FILETYPE_SYMLINK;
st->filesize = 0;
} /* else if */
Feb 15, 2010
Feb 15, 2010
324
325
326
327
328
329
330
331
332
333
334
335
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
336
return 1;
Feb 15, 2010
Feb 15, 2010
337
338
} /* __PHYSFS_platformStat */
Jul 25, 2011
Jul 25, 2011
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
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));
Jul 6, 2017
Jul 6, 2017
358
BAIL_IF(!m, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
Jul 25, 2011
Jul 25, 2011
359
360
361
362
rc = pthread_mutex_init(&m->mutex, NULL);
if (rc != 0)
{
allocator.Free(m);
Jul 6, 2017
Jul 6, 2017
363
BAIL(PHYSFS_ERR_OS_ERROR, NULL);
Jul 25, 2011
Jul 25, 2011
364
365
366
367
368
369
370
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
} /* 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
404
405
assert(m->owner == pthread_self()); /* catch programming errors. */
assert(m->count > 0); /* catch programming errors. */
Jul 25, 2011
Jul 25, 2011
406
407
408
409
410
411
412
413
414
415
if (m->owner == pthread_self())
{
if (--m->count == 0)
{
m->owner = (pthread_t) 0xDEADBEEF;
pthread_mutex_unlock(&m->mutex);
} /* if */
} /* if */
} /* __PHYSFS_platformReleaseMutex */
Mar 11, 2007
Mar 11, 2007
416
#endif /* PHYSFS_PLATFORM_POSIX */
Jun 29, 2002
Jun 29, 2002
417
Jul 22, 2017
Jul 22, 2017
418
/* end of platform_posix.c ... */