Skip to content

Latest commit

 

History

History
458 lines (354 loc) · 10.9 KB

platform_posix.c

File metadata and controls

458 lines (354 loc) · 10.9 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
} /* __PHYSFS_platformGetUserDir */
int __PHYSFS_platformExists(const char *fname)
{
struct stat statbuf;
Mar 18, 2007
Mar 18, 2007
122
BAIL_IF_MACRO(lstat(fname, &statbuf) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
123
return 1;
May 24, 2002
May 24, 2002
124
125
126
127
128
129
} /* __PHYSFS_platformExists */
int __PHYSFS_platformIsSymLink(const char *fname)
{
struct stat statbuf;
Aug 21, 2002
Aug 21, 2002
130
BAIL_IF_MACRO(lstat(fname, &statbuf) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
131
return ( (S_ISLNK(statbuf.st_mode)) ? 1 : 0 );
May 24, 2002
May 24, 2002
132
133
134
135
136
137
} /* __PHYSFS_platformIsSymlink */
int __PHYSFS_platformIsDirectory(const char *fname)
{
struct stat statbuf;
Aug 21, 2002
Aug 21, 2002
138
BAIL_IF_MACRO(stat(fname, &statbuf) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
139
return ( (S_ISDIR(statbuf.st_mode)) ? 1 : 0 );
May 24, 2002
May 24, 2002
140
141
142
143
144
145
146
147
148
149
} /* __PHYSFS_platformIsDirectory */
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
150
char *retval = (char *) allocator.Malloc(len);
May 24, 2002
May 24, 2002
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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
166
return retval;
May 24, 2002
May 24, 2002
167
168
169
170
} /* __PHYSFS_platformCvtToDependent */
Sep 29, 2004
Sep 29, 2004
171
172
void __PHYSFS_platformEnumerateFiles(const char *dirname,
int omitSymLinks,
Sep 18, 2005
Sep 18, 2005
173
174
PHYSFS_EnumFilesCallback callback,
const char *origdir,
Sep 29, 2004
Sep 29, 2004
175
void *callbackdata)
May 24, 2002
May 24, 2002
176
177
178
179
180
181
182
{
DIR *dir;
struct dirent *ent;
int bufsize = 0;
char *buf = NULL;
int dlen = 0;
Sep 29, 2004
Sep 29, 2004
183
if (omitSymLinks) /* !!! FIXME: this malloc sucks. */
May 24, 2002
May 24, 2002
184
185
186
{
dlen = strlen(dirname);
bufsize = dlen + 256;
Mar 14, 2005
Mar 14, 2005
187
buf = (char *) allocator.Malloc(bufsize);
Sep 29, 2004
Sep 29, 2004
188
189
if (buf == NULL)
return;
May 24, 2002
May 24, 2002
190
191
192
193
194
195
196
197
198
199
200
201
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
202
allocator.Free(buf);
Sep 29, 2004
Sep 29, 2004
203
return;
May 24, 2002
May 24, 2002
204
205
} /* if */
Jul 23, 2002
Jul 23, 2002
206
while ((ent = readdir(dir)) != NULL)
May 24, 2002
May 24, 2002
207
208
209
210
211
212
213
214
215
216
217
218
219
{
if (strcmp(ent->d_name, ".") == 0)
continue;
if (strcmp(ent->d_name, "..") == 0)
continue;
if (omitSymLinks)
{
char *p;
int len = strlen(ent->d_name) + dlen + 1;
if (len > bufsize)
{
Mar 14, 2005
Mar 14, 2005
220
p = (char *) allocator.Realloc(buf, len);
May 24, 2002
May 24, 2002
221
222
223
224
225
226
227
228
229
230
231
if (p == NULL)
continue;
buf = p;
bufsize = len;
} /* if */
strcpy(buf + dlen, ent->d_name);
if (__PHYSFS_platformIsSymLink(buf))
continue;
} /* if */
Sep 18, 2005
Sep 18, 2005
232
callback(callbackdata, origdir, ent->d_name);
May 24, 2002
May 24, 2002
233
234
} /* while */
Mar 24, 2007
Mar 24, 2007
235
allocator.Free(buf);
May 24, 2002
May 24, 2002
236
237
238
239
240
241
242
243
244
245
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
246
return 1;
May 24, 2002
May 24, 2002
247
248
249
} /* __PHYSFS_platformMkDir */
Jun 2, 2002
Jun 2, 2002
250
static void *doOpen(const char *filename, int mode)
May 24, 2002
May 24, 2002
251
{
Apr 3, 2008
Apr 3, 2008
252
const int appending = (mode & O_APPEND);
Jun 2, 2002
Jun 2, 2002
253
254
int fd;
int *retval;
May 24, 2002
May 24, 2002
255
256
errno = 0;
Apr 3, 2008
Apr 3, 2008
257
258
259
/* O_APPEND doesn't actually behave as we'd like. */
mode &= ~O_APPEND;
Jun 2, 2002
Jun 2, 2002
260
fd = open(filename, mode, S_IRUSR | S_IWUSR);
Jun 23, 2002
Jun 23, 2002
261
BAIL_IF_MACRO(fd < 0, strerror(errno), NULL);
May 24, 2002
May 24, 2002
262
Apr 3, 2008
Apr 3, 2008
263
264
265
266
267
268
269
270
271
if (appending)
{
if (lseek(fd, 0, SEEK_END) < 0)
{
close(fd);
BAIL_MACRO(strerror(errno), NULL);
} /* if */
} /* if */
Mar 14, 2005
Mar 14, 2005
272
retval = (int *) allocator.Malloc(sizeof (int));
Jun 2, 2002
Jun 2, 2002
273
274
275
276
277
278
279
if (retval == NULL)
{
close(fd);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
} /* if */
*retval = fd;
Jan 28, 2010
Jan 28, 2010
280
return ((void *) retval);
May 24, 2002
May 24, 2002
281
282
283
284
285
} /* doOpen */
void *__PHYSFS_platformOpenRead(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
286
return doOpen(filename, O_RDONLY);
May 24, 2002
May 24, 2002
287
288
289
290
291
} /* __PHYSFS_platformOpenRead */
void *__PHYSFS_platformOpenWrite(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
292
return doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC);
May 24, 2002
May 24, 2002
293
294
295
296
297
} /* __PHYSFS_platformOpenWrite */
void *__PHYSFS_platformOpenAppend(const char *filename)
{
Jan 28, 2010
Jan 28, 2010
298
return doOpen(filename, O_WRONLY | O_CREAT | O_APPEND);
May 24, 2002
May 24, 2002
299
300
301
302
} /* __PHYSFS_platformOpenAppend */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
Aug 21, 2010
Aug 21, 2010
303
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
304
{
Jun 2, 2002
Jun 2, 2002
305
int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
306
ssize_t rc = 0;
May 24, 2002
May 24, 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 = 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
315
316
317
318
} /* __PHYSFS_platformRead */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
Aug 21, 2010
Aug 21, 2010
319
PHYSFS_uint64 len)
May 24, 2002
May 24, 2002
320
{
Jun 2, 2002
Jun 2, 2002
321
int fd = *((int *) opaque);
Aug 21, 2010
Aug 21, 2010
322
ssize_t rc = 0;
Jun 2, 2002
Jun 2, 2002
323
Aug 21, 2010
Aug 21, 2010
324
BAIL_IF_MACRO(!__PHYSFS_ui64FitsAddressSpace(len),ERR_INVALID_ARGUMENT,-1);
Jun 2, 2002
Jun 2, 2002
325
Aug 21, 2010
Aug 21, 2010
326
327
328
329
330
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
331
332
333
334
335
} /* __PHYSFS_platformWrite */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
{
Jun 2, 2002
Jun 2, 2002
336
int fd = *((int *) opaque);
May 24, 2002
May 24, 2002
337
Jun 6, 2002
Jun 6, 2002
338
339
340
341
342
343
344
345
346
#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
347
Jan 28, 2010
Jan 28, 2010
348
return 1;
May 24, 2002
May 24, 2002
349
350
351
352
353
} /* __PHYSFS_platformSeek */
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
{
Jun 2, 2002
Jun 2, 2002
354
int fd = *((int *) opaque);
Jun 6, 2002
Jun 6, 2002
355
356
357
358
359
360
361
362
363
364
365
366
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
367
return retval;
May 24, 2002
May 24, 2002
368
369
370
371
372
} /* __PHYSFS_platformTell */
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
{
Jun 2, 2002
Jun 2, 2002
373
int fd = *((int *) opaque);
May 24, 2002
May 24, 2002
374
struct stat statbuf;
Jun 2, 2002
Jun 2, 2002
375
BAIL_IF_MACRO(fstat(fd, &statbuf) == -1, strerror(errno), -1);
Jan 28, 2010
Jan 28, 2010
376
return ((PHYSFS_sint64) statbuf.st_size);
May 24, 2002
May 24, 2002
377
378
379
380
381
} /* __PHYSFS_platformFileLength */
int __PHYSFS_platformEOF(void *opaque)
{
Jun 2, 2002
Jun 2, 2002
382
383
PHYSFS_sint64 pos = __PHYSFS_platformTell(opaque);
PHYSFS_sint64 len = __PHYSFS_platformFileLength(opaque);
Jan 28, 2010
Jan 28, 2010
384
return (pos >= len);
May 24, 2002
May 24, 2002
385
386
387
388
389
} /* __PHYSFS_platformEOF */
int __PHYSFS_platformFlush(void *opaque)
{
Jun 2, 2002
Jun 2, 2002
390
391
int fd = *((int *) opaque);
BAIL_IF_MACRO(fsync(fd) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
392
return 1;
May 24, 2002
May 24, 2002
393
394
395
396
397
} /* __PHYSFS_platformFlush */
int __PHYSFS_platformClose(void *opaque)
{
Jun 2, 2002
Jun 2, 2002
398
399
int fd = *((int *) opaque);
BAIL_IF_MACRO(close(fd) == -1, strerror(errno), 0);
Mar 14, 2005
Mar 14, 2005
400
allocator.Free(opaque);
Jan 28, 2010
Jan 28, 2010
401
return 1;
May 24, 2002
May 24, 2002
402
403
404
405
406
407
} /* __PHYSFS_platformClose */
int __PHYSFS_platformDelete(const char *path)
{
BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
Jan 28, 2010
Jan 28, 2010
408
return 1;
May 24, 2002
May 24, 2002
409
410
} /* __PHYSFS_platformDelete */
May 25, 2002
May 25, 2002
411
Feb 15, 2010
Feb 15, 2010
412
413
414
415
416
417
418
419
420
421
422
423
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
424
425
BAIL_MACRO(strerror(errno), 0);
Feb 15, 2010
Feb 15, 2010
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
} /* 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
452
return 1;
Feb 15, 2010
Feb 15, 2010
453
454
} /* __PHYSFS_platformStat */
Mar 11, 2007
Mar 11, 2007
455
#endif /* PHYSFS_PLATFORM_POSIX */
Jun 29, 2002
Jun 29, 2002
456
May 24, 2002
May 24, 2002
457
/* end of posix.c ... */