Implementation compiles and links with no actual archive support. No test
case available at this moment. :)
--- a/Makefile Sat Jul 07 09:05:19 2001 +0000
+++ b/Makefile Sun Jul 08 03:25:12 2001 +0000
@@ -182,7 +182,7 @@
$(BINDIR):
mkdir -p $(BINDIR)
- mkdir -p $(BINDIR)/archive_drivers
+ mkdir -p $(BINDIR)/archivers
mkdir -p $(BINDIR)/platform
distclean: clean
--- a/archivers/dir.c Sat Jul 07 09:05:19 2001 +0000
+++ b/archivers/dir.c Sun Jul 08 03:25:12 2001 +0000
@@ -8,46 +8,309 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
+extern const DirFunctions __PHYSFS_DirFunctions_DIR;
+static const FileFunctions __PHYSFS_FileHandle_DIR;
+static const FileFunctions __PHYSFS_FileHandle_DIRW;
+
+static int DIR_read(FileHandle *handle, void *buffer,
+ unsigned int objSize, unsigned int objCount)
+{
+ FILE *h = (FILE *) (handle->opaque);
+ int retval;
+
+ errno = 0;
+ retval = fread(buffer, objSize, objCount, h);
+ if ( (retval < objCount) && (ferror(h)) )
+ __PHYSFS_setError(strerror(errno));
+
+ return(retval);
+} /* DIR_read */
+
+
+static int DIR_write(FileHandle *handle, void *buffer,
+ unsigned int objSize, unsigned int objCount)
+{
+ FILE *h = (FILE *) (handle->opaque);
+ int retval;
+
+ errno = 0;
+ retval = fwrite(buffer, objSize, objCount, h);
+ if ( (retval < objCount) && (ferror(h)) )
+ __PHYSFS_setError(strerror(errno));
+
+ return(retval);
+} /* DIR_write */
+
+
+static int DIR_eof(FileHandle *handle)
+{
+ return(feof((FILE *) (handle->opaque)));
+} /* DIR_eof */
+
+
+static int DIR_tell(FileHandle *handle)
+{
+ return(ftell((FILE *) (handle->opaque)));
+} /* DIR_tell */
+
+
+static int DIR_seek(FileHandle *handle, int offset)
+{
+ return(fseek((FILE *) (handle->opaque), offset, SEEK_SET) == 0);
+} /* DIR_seek */
+
+
+static int DIR_fileClose(FileHandle *handle)
+{
+ FILE *h = (FILE *) (handle->opaque);
+
+ /*
+ * we manually fflush() the buffer, since that's the place fclose() will
+ * most likely fail, but that will leave the file handle in an undefined
+ * state if it fails. fflush() failures we can recover from.
+ */
+
+ /* keep trying until there's success or an unrecoverable error... */
+ do {
+ __PHYSFS_platformTimeslice();
+ errno = 0;
+ } while ( (fflush(h) == EOF) && ((errno == EAGAIN) || (errno == EINTR)) );
+
+ /* EBADF == "Not open for writing". That's fine. */
+ BAIL_IF_MACRO((errno != 0) && (errno != EBADF), strerror(errno), 0);
+
+ /* if fclose fails anyhow, we just have to pray that it's still usable. */
+ errno = 0;
+ BAIL_IF_MACRO(fclose(h) == EOF, strerror(errno), 0); /* (*shrug*) */
+
+ free(handle);
+ return(1);
+} /* DIR_fileClose */
+
+
+static int DIR_isArchive(const char *filename, int forWriting)
+{
+ /* directories ARE archives in this driver... */
+ return(__PHYSFS_platformIsDirectory(filename));
+} /* DIR_isArchive */
+
+
+static DirHandle *DIR_openArchive(const char *name, int forWriting)
+{
+ const char *dirsep = __PHYSFS_platformDirSeparator;
+ DirHandle *retval = NULL;
+ int namelen = strlen(name);
+ int seplen = strlen(dirsep);
+
+ BAIL_IF_MACRO(!DIR_isArchive(name, 0), ERR_UNSUPPORTED_ARCHIVE, NULL);
+
+ retval = malloc(sizeof (DirHandle));
+ BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+ retval->opaque = malloc(namelen + seplen + 1);
+ if (retval->opaque == NULL)
+ {
+ free(retval);
+ BAIL_IF_MACRO(0, ERR_OUT_OF_MEMORY, NULL);
+ } /* if */
+
+ /* make sure there's a dir separator at the end of the string */
+ strcpy((char *) (retval->opaque), name);
+ if (strcmp((name + namelen) - seplen, dirsep) != 0)
+ strcat((char *) (retval->opaque), dirsep);
+
+ retval->funcs = &__PHYSFS_DirFunctions_DIR;
+ return(retval);
+} /* DIR_openArchive */
+
+
+static LinkedStringList *DIR_enumerateFiles(DirHandle *h, const char *dname)
+{
+ char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque),dname,NULL);
+ LinkedStringList *retval;
+
+ BAIL_IF_MACRO(d == NULL, NULL, NULL);
+ retval = __PHYSFS_platformEnumerateFiles(d);
+ free(d);
+ return(retval);
+} /* DIR_enumerateFiles */
+
+
+static int DIR_exists(DirHandle *h, const char *name)
+{
+ char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
+ int retval;
+
+ BAIL_IF_MACRO(f == NULL, NULL, 0);
+ retval = __PHYSFS_platformExists(f);
+ free(f);
+ return(retval);
+} /* DIR_exists */
+
+
+static int DIR_isDirectory(DirHandle *h, const char *name)
+{
+ char *d = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
+ int retval;
+
+ BAIL_IF_MACRO(d == NULL, NULL, 0);
+ retval = __PHYSFS_platformIsDirectory(d);
+ free(d);
+ return(retval);
+} /* DIR_isDirectory */
+
+
+static int DIR_isSymLink(DirHandle *h, const char *name)
+{
+ char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
+ int retval;
+
+ BAIL_IF_MACRO(f == NULL, NULL, 0); /* !!! might be a problem. */
+ retval = __PHYSFS_platformIsSymLink(f);
+ free(f);
+ return(retval);
+} /* DIR_isSymLink */
+
+
+static FileHandle *doOpen(DirHandle *h, const char *name, const char *mode)
+{
+ char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
+ FILE *rc;
+ FileHandle *retval;
+ char *str;
+
+ BAIL_IF_MACRO(f == NULL, NULL, NULL);
+
+ retval = (FileHandle *) malloc(sizeof (FileHandle));
+ if (!retval)
+ {
+ free(f);
+ BAIL_IF_MACRO(0, ERR_OUT_OF_MEMORY, NULL);
+ } /* if */
+
+ errno = 0;
+ rc = fopen(f, mode);
+ str = strerror(errno);
+ free(f);
+
+ if (!rc)
+ {
+ free(retval);
+ BAIL_IF_MACRO(0, str, NULL);
+ } /* if */
+
+ retval->opaque = (void *) rc;
+ retval->dirHandle = h;
+ retval->funcs = &__PHYSFS_FileHandle_DIR;
+ return(retval);
+} /* doOpen */
+
+
+static FileHandle *DIR_openRead(DirHandle *h, const char *filename)
+{
+ return(doOpen(h, filename, "rb"));
+} /* DIR_openRead */
+
+
+static FileHandle *DIR_openWrite(DirHandle *h, const char *filename)
+{
+ return(doOpen(h, filename, "wb"));
+} /* DIR_openWrite */
+
+
+static FileHandle *DIR_openAppend(DirHandle *h, const char *filename)
+{
+ return(doOpen(h, filename, "ab"));
+} /* DIR_openAppend */
+
+
+static int DIR_remove(DirHandle *h, const char *name)
+{
+ char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
+ int retval;
+
+ BAIL_IF_MACRO(f == NULL, NULL, 0);
+
+ errno = 0;
+ retval = (remove(f) == 0);
+ if (!retval)
+ __PHYSFS_setError(strerror(errno));
+
+ free(f);
+ return(retval);
+} /* DIR_remove */
+
+
+static int DIR_mkdir(DirHandle *h, const char *name)
+{
+ char *f = __PHYSFS_platformCvtToDependent((char *)(h->opaque), name, NULL);
+ int retval;
+
+ BAIL_IF_MACRO(f == NULL, NULL, 0);
+
+ errno = 0;
+ retval = (mkdir(f, S_IRWXU) == 0);
+ if (!retval)
+ __PHYSFS_setError(strerror(errno));
+
+ free(f);
+ return(retval);
+} /* DIR_mkdir */
+
+
+static void DIR_dirClose(DirHandle *h)
+{
+ free(h->opaque);
+ free(h);
+} /* DIR_dirClose */
+
+
+
static const FileFunctions __PHYSFS_FileHandle_DIR =
{
- DIR_read, /* read() method */
- NULL, /* write() method */
- DIR_eof, /* eof() method */
- DIR_tell, /* tell() method */
- DIR_seek, /* seek() method */
- DIR_close, /* close() method */
+ DIR_read, /* read() method */
+ NULL, /* write() method */
+ DIR_eof, /* eof() method */
+ DIR_tell, /* tell() method */
+ DIR_seek, /* seek() method */
+ DIR_fileClose, /* fileClose() method */
};
static const FileFunctions __PHYSFS_FileHandle_DIRW =
{
- NULL, /* read() method */
- DIR_write, /* write() method */
- DIR_eof, /* eof() method */
- DIR_tell, /* tell() method */
- DIR_seek, /* seek() method */
- DIR_close, /* close() method */
+ NULL, /* read() method */
+ DIR_write, /* write() method */
+ DIR_eof, /* eof() method */
+ DIR_tell, /* tell() method */
+ DIR_seek, /* seek() method */
+ DIR_fileClose, /* fileClose() method */
};
const DirFunctions __PHYSFS_DirFunctions_DIR =
{
- DIR_isArchive, /* isArchive() method */
- DIR_openArchive, /* openArchive() method */
- DIR_enumerate, /* enumerateFiles() method */
- DIR_exists, /* exists() method */
- DIR_isDirectory, /* isDirectory() method */
- DIR_isSymLink, /* isSymLink() method */
- DIR_openRead, /* openRead() method */
- DIR_openWrite, /* openWrite() method */
- DIR_openAppend, /* openAppend() method */
- DIR_remove, /* remove() method */
- DIR_mkdir, /* mkdir() method */
- DIR_close, /* close() method */
+ DIR_isArchive, /* isArchive() method */
+ DIR_openArchive, /* openArchive() method */
+ DIR_enumerateFiles, /* enumerateFiles() method */
+ DIR_exists, /* exists() method */
+ DIR_isDirectory, /* isDirectory() method */
+ DIR_isSymLink, /* isSymLink() method */
+ DIR_openRead, /* openRead() method */
+ DIR_openWrite, /* openWrite() method */
+ DIR_openAppend, /* openAppend() method */
+ DIR_remove, /* remove() method */
+ DIR_mkdir, /* mkdir() method */
+ DIR_dirClose, /* dirClose() method */
};
--- a/archivers/zip.c Sat Jul 07 09:05:19 2001 +0000
+++ b/archivers/zip.c Sun Jul 08 03:25:12 2001 +0000
@@ -16,32 +16,101 @@
#error PHYSFS_SUPPORTS_ZIP must be defined.
#endif
+extern const DirFunctions __PHYSFS_DirFunctions_ZIP;
+extern const FileFunctions __PHYSFS_FileHandle_ZIP;
+
+
+static int ZIP_read(FileHandle *handle, void *buffer,
+ unsigned int objSize, unsigned int objCount)
+{
+} /* ZIP_read */
+
+
+static int ZIP_eof(FileHandle *handle)
+{
+} /* ZIP_eof */
+
+
+static int ZIP_tell(FileHandle *handle)
+{
+} /* ZIP_tell */
+
+
+static int ZIP_seek(FileHandle *handle, int offset)
+{
+} /* ZIP_seek */
+
+
+static int ZIP_fileClose(FileHandle *handle)
+{
+} /* ZIP_fileClose */
+
+
+static int ZIP_isArchive(const char *filename, int forWriting)
+{
+} /* ZIP_isArchive */
+
+
+static DirHandle *ZIP_openArchive(const char *name, int forWriting)
+{
+} /* ZIP_openArchive */
+
+
+static LinkedStringList *ZIP_enumerateFiles(DirHandle *r, const char *dirname)
+{
+} /* ZIP_enumerateFiles */
+
+
+static int ZIP_exists(DirHandle *r, const char *name)
+{
+} /* ZIP_exists */
+
+
+static int ZIP_isDirectory(DirHandle *r, const char *name)
+{
+} /* ZIP_isDirectory */
+
+
+static int ZIP_isSymLink(DirHandle *r, const char *name)
+{
+} /* ZIP_isSymLink */
+
+
+static FileHandle *ZIP_openRead(DirHandle *r, const char *filename)
+{
+} /* ZIP_openRead */
+
+
+static void ZIP_dirClose(DirHandle *r)
+{
+} /* ZIP_dirClose */
+
static const FileFunctions __PHYSFS_FileHandle_ZIP =
{
- ZIP_read, /* read() method */
- NULL, /* write() method */
- ZIP_eof, /* eof() method */
- ZIP_tell, /* tell() method */
- ZIP_seek, /* seek() method */
- ZIP_close, /* close() method */
+ ZIP_read, /* read() method */
+ NULL, /* write() method */
+ ZIP_eof, /* eof() method */
+ ZIP_tell, /* tell() method */
+ ZIP_seek, /* seek() method */
+ ZIP_fileClose, /* fileClose() method */
};
const DirFunctions __PHYSFS_DirFunctions_ZIP =
{
- ZIP_isArchive, /* isArchive() method */
- ZIP_openArchive, /* openArchive() method */
- ZIP_enumerate, /* enumerateFiles() method */
- ZIP_exists, /* exists() method */
- ZIP_isDirectory, /* isDirectory() method */
- ZIP_isSymLink, /* isSymLink() method */
- ZIP_openRead, /* openRead() method */
- NULL, /* openWrite() method */
- NULL, /* openAppend() method */
- NULL, /* remove() method */
- NULL, /* mkdir() method */
- ZIP_close, /* close() method */
+ ZIP_isArchive, /* isArchive() method */
+ ZIP_openArchive, /* openArchive() method */
+ ZIP_enumerateFiles, /* enumerateFiles() method */
+ ZIP_exists, /* exists() method */
+ ZIP_isDirectory, /* isDirectory() method */
+ ZIP_isSymLink, /* isSymLink() method */
+ ZIP_openRead, /* openRead() method */
+ NULL, /* openWrite() method */
+ NULL, /* openAppend() method */
+ NULL, /* remove() method */
+ NULL, /* mkdir() method */
+ ZIP_dirClose, /* dirClose() method */
};
const __PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_ZIP =
--- a/physfs.c Sat Jul 07 09:05:19 2001 +0000
+++ b/physfs.c Sun Jul 08 03:25:12 2001 +0000
@@ -194,14 +194,14 @@
di = (DirInfo *) malloc(sizeof (DirInfo));
if (di == NULL)
- dirHandle->funcs->close(dirHandle);
+ dirHandle->funcs->dirClose(dirHandle);
BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
di->dirName = (char *) malloc(strlen(newDir) + 1);
if (di->dirName == NULL)
{
free(di);
- dirHandle->funcs->close(dirHandle);
+ dirHandle->funcs->dirClose(dirHandle);
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
return(0);
} /* if */
@@ -226,7 +226,7 @@
BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
} /* for */
- di->dirHandle->funcs->close(di->dirHandle);
+ di->dirHandle->funcs->dirClose(di->dirHandle);
free(di->dirName);
free(di);
return(1);
@@ -300,7 +300,7 @@
{
next = i->next;
h = (FileHandle *) (i->handle->opaque);
- if (!h->funcs->close(i->handle->opaque))
+ if (!h->funcs->fileClose(i->handle->opaque))
{
*list = i;
return(0);
@@ -624,9 +624,9 @@
/* string manipulation in C makes my ass itch. */
-char *__PHYSFS_convertToDependentNotation(const char *prepend,
- const char *dirName,
- const char *append)
+char *__PHYSFS_convertToDependent(const char *prepend,
+ const char *dirName,
+ const char *append)
{
const char *dirsep = PHYSFS_getDirSeparator();
int sepsize = strlen(dirsep);
@@ -658,13 +658,14 @@
str = (char *) malloc(allocSize);
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, NULL);
- *str = '\0';
- if (prepend)
+ if (prepend == NULL)
+ *str = '\0';
+ else
{
strcpy(str, prepend);
strcat(str, dirsep);
- } /* if */
+ } /* else */
for (i1 = (char *) dirName, i2 = str + strlen(str); *i1; i1++, i2++)
{
@@ -709,6 +710,7 @@
if ( (strcmp(start, ".") == 0) ||
(strcmp(start, "..") == 0) ||
+ (strchr(start, '\\') != NULL) ||
(strchr(start, ':') != NULL) )
{
__PHYSFS_setError(ERR_INSECURE_FNAME);
@@ -1058,7 +1060,7 @@
{
if (i->handle == handle)
{
- rc = h->funcs->close(h);
+ rc = h->funcs->fileClose(h);
if (!rc)
return(0);
--- a/physfs_internal.h Sat Jul 07 09:05:19 2001 +0000
+++ b/physfs_internal.h Sun Jul 08 03:25:12 2001 +0000
@@ -17,6 +17,14 @@
struct __PHYSFS_DIRHANDLE__;
struct __PHYSFS_FILEFUNCTIONS__;
+
+typedef struct __PHYSFS_LINKEDSTRINGLIST__
+{
+ char *str;
+ struct __PHYSFS_LINKEDSTRINGLIST__ *next;
+} LinkedStringList;
+
+
typedef struct __PHYSFS_FILEHANDLE__
{
/*
@@ -79,7 +87,7 @@
* returns non-zero on success, zero if can't close file.
* On failure, call __PHYSFS_setError().
*/
- int (*close)(FileHandle *handle);
+ int (*fileClose)(FileHandle *handle);
} FileFunctions;
@@ -97,12 +105,6 @@
} DirHandle;
-typedef struct __PHYSFS_LINKEDSTRINGLIST__
-{
- char *str;
- struct __PHYSFS_LINKEDSTRINGLIST__ *next;
-} LinkedStringList;
-
/*
* Symlinks should always be followed; PhysicsFS will use
* DirFunctions->isSymLink() and make a judgement on whether to
@@ -162,13 +164,17 @@
* This filename is in platform-independent notation.
* If you can't handle multiple opens of the same file,
* you can opt to fail for the second call.
+ * Fail if the file does not exist.
* Returns NULL on failure, and calls __PHYSFS_setError().
*/
FileHandle *(*openRead)(DirHandle *r, const char *filename);
/*
* Open file for writing, and return a FileHandle.
- * This filename is in platform-independent notation.
+ * If the file does not exist, it should be created. If it exists,
+ * it should be truncated to zero bytes. The writing
+ * offset should be the start of the file.
+ * This filename is in platform-independent notation.
* This method may be NULL.
* If you can't handle multiple opens of the same file,
* you can opt to fail for the second call.
@@ -178,7 +184,9 @@
/*
* Open file for appending, and return a FileHandle.
- * This filename is in platform-independent notation.
+ * If the file does not exist, it should be created. The writing
+ * offset should be the end of the file.
+ * This filename is in platform-independent notation.
* This method may be NULL.
* If you can't handle multiple opens of the same file,
* you can opt to fail for the second call.
@@ -212,7 +220,7 @@
* the "opaque" entry. This should assume that it won't be called if
* there are still files open from this DirHandle.
*/
- void (*close)(DirHandle *r);
+ void (*dirClose)(DirHandle *r);
} DirFunctions;
@@ -248,7 +256,7 @@
* and append (append) to the converted string.
*
* So, on Win32, calling:
- * __PHYSFS_convertToDependentNotation("C:\", "my/files", NULL);
+ * __PHYSFS_convertToDependent("C:\", "my/files", NULL);
* ...will return the string "C:\my\files".
*
* This is a convenience function; you might want to hack something out that
@@ -256,9 +264,9 @@
*
* Be sure to free() the return value when done with it.
*/
-char *__PHYSFS_convertToDependentNotation(const char *prepend,
- const char *dirName,
- const char *append);
+char *__PHYSFS_convertToDependent(const char *prepend,
+ const char *dirName,
+ const char *append);
/*
* Verify that (fname) (in platform-independent notation), in relation
@@ -337,15 +345,61 @@
int __PHYSFS_platformStricmp(const char *str1, const char *str2);
/*
- * Return non-zero if filename (in platform-dependent notation) is a symlink.
+ * Return non-zero if filename (in platform-dependent notation) exists.
+ * Symlinks should be followed; if what the symlink points to is missing,
+ * then the retval is false.
*/
-int __PHYSFS_platformIsSymlink(const char *fname);
+int __PHYSFS_platformExists(const char *fname);
/*
* Return non-zero if filename (in platform-dependent notation) is a symlink.
*/
+int __PHYSFS_platformIsSymLink(const char *fname);
+
+/*
+ * Return non-zero if filename (in platform-dependent notation) is a symlink.
+ * Symlinks should be followed; if what the symlink points to is missing,
+ * or isn't a directory, then the retval is false.
+ */
int __PHYSFS_platformIsDirectory(const char *fname);
+/*
+ * Convert (dirName) to platform-dependent notation, then prepend (prepend)
+ * and append (append) to the converted string.
+ *
+ * So, on Win32, calling:
+ * __PHYSFS_platformCvtToDependent("C:\", "my/files", NULL);
+ * ...will return the string "C:\my\files".
+ *
+ * This can be implemented in a platform-specific manner, so you can get
+ * get a speed boost that the default implementation can't, since
+ * you can make assumptions about the size of strings, etc..
+ *
+ * Platforms that choose not to implement this may just call
+ * __PHYSFS_convertToDependent() as a passthrough.
+ *
+ * Be sure to free() the return value when done with it.
+ */
+char *__PHYSFS_platformCvtToDependent(const char *prepend,
+ const char *dirName,
+ const char *append);
+
+/*
+ * Make the current thread give up a timeslice. This is called in a loop
+ * while waiting for various external forces to get back to us.
+ */
+void __PHYSFS_platformTimeslice(void);
+
+
+/*
+ * Enumerate a directory of files. This follows the rules for the
+ * DirFunctions->enumerateFiles() method (see above), except that the
+ * (dirName) that is passed to this function is converted to
+ * platform-DEPENDENT notation by the caller. The DirFunctions version
+ * uses platform-independent notation.
+ */
+LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname);
+
#ifdef __cplusplus
extern "C" {
--- a/platform/unix.c Sat Jul 07 09:05:19 2001 +0000
+++ b/platform/unix.c Sun Jul 08 03:25:12 2001 +0000
@@ -6,9 +6,39 @@
* This file written by Ryan C. Gordon.
*/
+#if (defined __STRICT_ANSI__)
+#define __PHYSFS_DOING_STRICT_ANSI__
+#endif
+
+/*
+ * We cheat a little: I want the symlink version of stat() (lstat), and
+ * GCC/Linux will not declare it if compiled with the -ansi flag.
+ * If you are really lacking symlink support on your platform,
+ * you should #define __PHYSFS_NO_SYMLINKS__ before compiling this
+ * file. That will open a security hole, though, if you really DO have
+ * symlinks on your platform; it renders PHYSFS_permitSymbolicLinks(0)
+ * useless, since every symlink will be reported as a regular file/dir.
+ */
+#if (defined __PHYSFS_DOING_STRICT_ANSI__)
+#undef __STRICT_ANSI__
+#endif
#include <stdio.h>
+#if (defined __PHYSFS_DOING_STRICT_ANSI__)
+#define __STRICT_ANSI__
+#endif
+
#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <time.h>
+#include <errno.h>
+
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
@@ -18,22 +48,88 @@
char **__PHYSFS_platformDetectAvailableCDs(void)
{
+ /* !!! write me. */
+ char **retval = malloc(sizeof (char *));
+ if (retval != NULL)
+ *retval = NULL;
+
+ return(retval);
} /* __PHYSFS_detectAvailableCDs */
char *__PHYSFS_platformCalcBaseDir(char *argv0)
{
- return(NULL);
+ return(NULL); /* default PhysicsFS behaviour is acceptable. */
} /* __PHYSFS_platformCalcBaseDir */
+static char *copyEnvironmentVariable(const char *varname)
+{
+ const char *envr = getenv(varname);
+ char *retval = NULL;
+
+ if (envr != NULL)
+ {
+ retval = malloc(strlen(envr) + 1);
+ if (retval != NULL)
+ strcpy(retval, envr);
+ } /* if */
+
+ return(retval);
+} /* copyEnvironmentVariable */
+
+
+static char *getUserNameByUID(void)
+{
+ uid_t uid = getuid();
+ struct passwd *pw;
+ char *retval = NULL;
+
+ pw = getpwuid(uid);
+ if ((pw != NULL) && (pw->pw_name != NULL))
+ {
+ retval = malloc(strlen(pw->pw_name) + 1);
+ if (retval != NULL)
+ strcpy(retval, pw->pw_name);
+ } /* if */
+
+ return(retval);
+} /* 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))
+ {
+ retval = malloc(strlen(pw->pw_dir) + 1);
+ if (retval != NULL)
+ strcpy(retval, pw->pw_dir);
+ } /* if */
+
+ return(retval);
+} /* getUserDirByUID */
+
+
char *__PHYSFS_platformGetUserName(void)
{
+ char *retval = getUserNameByUID();
+ if (retval == NULL)
+ retval = copyEnvironmentVariable("USER");
+ return(retval);
} /* __PHYSFS_platformGetUserName */
char *__PHYSFS_platformGetUserDir(void)
{
+ char *retval = copyEnvironmentVariable("HOME");
+ if (retval == NULL)
+ retval = getUserDirByUID();
+ return(retval);
} /* __PHYSFS_platformGetUserDir */
@@ -43,21 +139,149 @@
} /* __PHYSFS_platformGetThreadID */
-int __PHYSFS_platformStricmp(const char *str1, const char *str2)
+/* -ansi and -pedantic flags prevent use of strcasecmp() on Linux. */
+int __PHYSFS_platformStricmp(const char *x, const char *y)
{
- return(strcasecmp(str1, str2));
+ int ux, uy;
+
+ do
+ {
+ ux = toupper((int) *x);
+ uy = toupper((int) *y);
+ if (ux > uy)
+ return(1);
+ else if (ux < uy)
+ return(-1);
+ x++;
+ y++;
+ } while ((ux) && (uy));
+
+ return(0);
} /* __PHYSFS_platformStricmp */
-int __PHYSFS_platformIsSymlink(const char *fname)
+int __PHYSFS_platformExists(const char *fname)
+{
+ struct stat statbuf;
+ return(stat(fname, &statbuf) == 0);
+} /* __PHYSFS_platformExists */
+
+
+int __PHYSFS_platformIsSymLink(const char *fname)
{
+#if (defined __PHYSFS_NO_SYMLINKS__)
+ return(0);
+#else
+
+ struct stat statbuf;
+ int retval = 0;
+
+ if (lstat(fname, &statbuf) == 0)
+ {
+ if (S_ISLNK(statbuf.st_mode))
+ retval = 1;
+ } /* if */
+
+ return(retval);
+
+#endif
} /* __PHYSFS_platformIsSymlink */
int __PHYSFS_platformIsDirectory(const char *fname)
{
+ struct stat statbuf;
+ int retval = 0;
+
+ if (stat(fname, &statbuf) == 0)
+ {
+ if (S_ISDIR(statbuf.st_mode))
+ retval = 1;
+ } /* if */
+
+ return(retval);
} /* __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;
+ char *retval = malloc(len);
+
+ 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);
+
+ return(retval);
+} /* __PHYSFS_platformCvtToDependent */
+
+
+/* Much like my college days, try to sleep for 10 milliseconds at a time... */
+void __PHYSFS_platformTimeslice(void)
+{
+ struct timespec napTime;
+ napTime.tv_sec = 0;
+ napTime.tv_nsec = 10 * 1000 * 1000; /* specified in nanoseconds. */
+ nanosleep(&napTime, NULL); /* don't care if it fails. */
+} /* __PHYSFS_platformTimeslice */
+
+
+LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname)
+{
+ LinkedStringList *retval = NULL;
+ LinkedStringList *l = NULL;
+ LinkedStringList *prev = NULL;
+ DIR *dir;
+ struct dirent *ent;
+
+ errno = 0;
+ dir = opendir(dirname);
+ BAIL_IF_MACRO(dir == NULL, strerror(errno), NULL);
+
+ while (1)
+ {
+ ent = readdir(dir);
+ if (ent == NULL) /* we're done. */
+ break;
+
+ l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
+ if (l != NULL)
+ break;
+
+ l->str = (char *) malloc(strlen(ent->d_name) + 1);
+ if (l->str == NULL)
+ {
+ free(l);
+ break;
+ } /* if */
+
+ if (retval == NULL)
+ retval = l;
+ else
+ prev->next = l;
+
+ prev = l;
+ l->next = NULL;
+ } /* while */
+
+ closedir(dir);
+ return(retval);
+} /* __PHYSFS_platformEnumerateFiles */
+
+
/* end of unix.c ... */