2 * Posix-esque support routines for PhysicsFS.
4 * Please see the file LICENSE.txt in the source's root directory.
6 * This file written by Ryan C. Gordon.
9 #define __PHYSICSFS_INTERNAL__
10 #include "physfs_platforms.h"
12 #ifdef PHYSFS_PLATFORM_POSIX
19 #include <sys/types.h>
26 #ifdef PHYSFS_HAVE_LLSEEK
27 #include <linux/unistd.h>
30 #include "physfs_internal.h"
33 const char *__PHYSFS_platformDirSeparator = "/";
36 char *__PHYSFS_platformCopyEnvironmentVariable(const char *varname)
38 const char *envr = getenv(varname);
43 retval = (char *) allocator.Malloc(strlen(envr) + 1);
49 } /* __PHYSFS_platformCopyEnvironmentVariable */
52 static char *getUserNameByUID(void)
59 if ((pw != NULL) && (pw->pw_name != NULL))
61 retval = (char *) allocator.Malloc(strlen(pw->pw_name) + 1);
63 strcpy(retval, pw->pw_name);
67 } /* getUserNameByUID */
70 static char *getUserDirByUID(void)
77 if ((pw != NULL) && (pw->pw_dir != NULL))
79 retval = (char *) allocator.Malloc(strlen(pw->pw_dir) + 1);
81 strcpy(retval, pw->pw_dir);
85 } /* getUserDirByUID */
88 char *__PHYSFS_platformGetUserName(void)
90 char *retval = getUserNameByUID();
92 retval = __PHYSFS_platformCopyEnvironmentVariable("USER");
94 } /* __PHYSFS_platformGetUserName */
97 char *__PHYSFS_platformGetUserDir(void)
99 char *retval = __PHYSFS_platformCopyEnvironmentVariable("HOME");
101 retval = getUserDirByUID();
103 } /* __PHYSFS_platformGetUserDir */
106 int __PHYSFS_platformExists(const char *fname)
109 BAIL_IF_MACRO(lstat(fname, &statbuf) == -1, strerror(errno), 0);
111 } /* __PHYSFS_platformExists */
114 int __PHYSFS_platformIsSymLink(const char *fname)
117 BAIL_IF_MACRO(lstat(fname, &statbuf) == -1, strerror(errno), 0);
118 return( (S_ISLNK(statbuf.st_mode)) ? 1 : 0 );
119 } /* __PHYSFS_platformIsSymlink */
122 int __PHYSFS_platformIsDirectory(const char *fname)
125 BAIL_IF_MACRO(stat(fname, &statbuf) == -1, strerror(errno), 0);
126 return( (S_ISDIR(statbuf.st_mode)) ? 1 : 0 );
127 } /* __PHYSFS_platformIsDirectory */
130 char *__PHYSFS_platformCvtToDependent(const char *prepend,
134 int len = ((prepend) ? strlen(prepend) : 0) +
135 ((append) ? strlen(append) : 0) +
137 char *retval = (char *) allocator.Malloc(len);
139 BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
141 /* platform-independent notation is Unix-style already. :) */
144 strcpy(retval, prepend);
148 strcat(retval, dirName);
151 strcat(retval, append);
154 } /* __PHYSFS_platformCvtToDependent */
158 void __PHYSFS_platformEnumerateFiles(const char *dirname,
160 PHYSFS_EnumFilesCallback callback,
170 if (omitSymLinks) /* !!! FIXME: this malloc sucks. */
172 dlen = strlen(dirname);
173 bufsize = dlen + 256;
174 buf = (char *) allocator.Malloc(bufsize);
177 strcpy(buf, dirname);
178 if (buf[dlen - 1] != '/')
186 dir = opendir(dirname);
193 while ((ent = readdir(dir)) != NULL)
195 if (strcmp(ent->d_name, ".") == 0)
198 if (strcmp(ent->d_name, "..") == 0)
204 int len = strlen(ent->d_name) + dlen + 1;
207 p = (char *) allocator.Realloc(buf, len);
214 strcpy(buf + dlen, ent->d_name);
215 if (__PHYSFS_platformIsSymLink(buf))
219 callback(callbackdata, origdir, ent->d_name);
224 } /* __PHYSFS_platformEnumerateFiles */
227 int __PHYSFS_platformMkDir(const char *path)
231 rc = mkdir(path, S_IRWXU);
232 BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
234 } /* __PHYSFS_platformMkDir */
237 static void *doOpen(const char *filename, int mode)
243 fd = open(filename, mode, S_IRUSR | S_IWUSR);
244 BAIL_IF_MACRO(fd < 0, strerror(errno), NULL);
246 retval = (int *) allocator.Malloc(sizeof (int));
250 BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
254 return((void *) retval);
258 void *__PHYSFS_platformOpenRead(const char *filename)
260 return(doOpen(filename, O_RDONLY));
261 } /* __PHYSFS_platformOpenRead */
264 void *__PHYSFS_platformOpenWrite(const char *filename)
266 return(doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC));
267 } /* __PHYSFS_platformOpenWrite */
270 void *__PHYSFS_platformOpenAppend(const char *filename)
272 return(doOpen(filename, O_WRONLY | O_CREAT | O_APPEND));
273 } /* __PHYSFS_platformOpenAppend */
276 PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
277 PHYSFS_uint32 size, PHYSFS_uint32 count)
279 int fd = *((int *) opaque);
280 int max = size * count;
281 int rc = read(fd, buffer, max);
283 BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
286 if ((rc < max) && (size > 1))
287 lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
290 } /* __PHYSFS_platformRead */
293 PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
294 PHYSFS_uint32 size, PHYSFS_uint32 count)
296 int fd = *((int *) opaque);
297 int max = size * count;
298 int rc = write(fd, (void *) buffer, max);
300 BAIL_IF_MACRO(rc == -1, strerror(errno), rc);
303 if ((rc < max) && (size > 1))
304 lseek(fd, -(rc % size), SEEK_CUR); /* rollback to object boundary. */
307 } /* __PHYSFS_platformWrite */
310 int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
312 int fd = *((int *) opaque);
314 #ifdef PHYSFS_HAVE_LLSEEK
315 unsigned long offset_high = ((pos >> 32) & 0xFFFFFFFF);
316 unsigned long offset_low = (pos & 0xFFFFFFFF);
318 int rc = llseek(fd, offset_high, offset_low, &retoffset, SEEK_SET);
319 BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
321 BAIL_IF_MACRO(lseek(fd, (int) pos, SEEK_SET) == -1, strerror(errno), 0);
325 } /* __PHYSFS_platformSeek */
328 PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
330 int fd = *((int *) opaque);
331 PHYSFS_sint64 retval;
333 #ifdef PHYSFS_HAVE_LLSEEK
335 int rc = llseek(fd, 0, &retoffset, SEEK_CUR);
336 BAIL_IF_MACRO(rc == -1, strerror(errno), -1);
337 retval = (PHYSFS_sint64) retoffset;
339 retval = (PHYSFS_sint64) lseek(fd, 0, SEEK_CUR);
340 BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
344 } /* __PHYSFS_platformTell */
347 PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
349 int fd = *((int *) opaque);
351 BAIL_IF_MACRO(fstat(fd, &statbuf) == -1, strerror(errno), -1);
352 return((PHYSFS_sint64) statbuf.st_size);
353 } /* __PHYSFS_platformFileLength */
356 int __PHYSFS_platformEOF(void *opaque)
358 PHYSFS_sint64 pos = __PHYSFS_platformTell(opaque);
359 PHYSFS_sint64 len = __PHYSFS_platformFileLength(opaque);
361 } /* __PHYSFS_platformEOF */
364 int __PHYSFS_platformFlush(void *opaque)
366 int fd = *((int *) opaque);
367 BAIL_IF_MACRO(fsync(fd) == -1, strerror(errno), 0);
369 } /* __PHYSFS_platformFlush */
372 int __PHYSFS_platformClose(void *opaque)
374 int fd = *((int *) opaque);
375 BAIL_IF_MACRO(close(fd) == -1, strerror(errno), 0);
376 allocator.Free(opaque);
378 } /* __PHYSFS_platformClose */
381 int __PHYSFS_platformDelete(const char *path)
383 BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
385 } /* __PHYSFS_platformDelete */
388 PHYSFS_sint64 __PHYSFS_platformGetLastModTime(const char *fname)
391 BAIL_IF_MACRO(stat(fname, &statbuf) < 0, strerror(errno), -1);
392 return statbuf.st_mtime;
393 } /* __PHYSFS_platformGetLastModTime */
395 #endif /* PHYSFS_PLATFORM_POSIX */
397 /* end of posix.c ... */