Implementation compiles and links with no actual archive support. No test

case available at this moment.  :)
This commit is contained in:
Ryan C. Gordon 2001-07-08 03:25:12 +00:00
parent f053b90111
commit 2622be385d
6 changed files with 686 additions and 74 deletions

View File

@ -182,7 +182,7 @@ $(MAINLIB) : $(BINDIR) $(MAINOBJS)
$(BINDIR):
mkdir -p $(BINDIR)
mkdir -p $(BINDIR)/archive_drivers
mkdir -p $(BINDIR)/archivers
mkdir -p $(BINDIR)/platform
distclean: clean

View File

@ -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 */
};

View File

@ -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 =

View File

@ -194,14 +194,14 @@ static DirInfo *buildDirInfo(const char *newDir, int forWriting)
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 @@ static int freeDirInfo(DirInfo *di, FileHandleList *openList)
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 @@ static int closeFileHandleList(FileHandleList **list)
{
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 @@ void PHYSFS_permitSymbolicLinks(int allow)
/* 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 @@ char *__PHYSFS_convertToDependentNotation(const char *prepend,
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 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
if ( (strcmp(start, ".") == 0) ||
(strcmp(start, "..") == 0) ||
(strchr(start, '\\') != NULL) ||
(strchr(start, ':') != NULL) )
{
__PHYSFS_setError(ERR_INSECURE_FNAME);
@ -1058,7 +1060,7 @@ int PHYSFS_close(PHYSFS_file *handle)
{
if (i->handle == handle)
{
rc = h->funcs->close(h);
rc = h->funcs->fileClose(h);
if (!rc)
return(0);

View File

@ -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 @@ typedef struct __PHYSFS_FILEFUNCTIONS__
* 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 @@ typedef struct __PHYSFS_DIRHANDLE__
} 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 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
* 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 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
/*
* 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 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
* 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 @@ void __PHYSFS_setError(const char *err);
* 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 @@ void __PHYSFS_setError(const char *err);
*
* 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_platformGetThreadID(void);
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" {

View File

@ -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 @@ const char *__PHYSFS_platformDirSeparator = "/";
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 @@ int __PHYSFS_platformGetThreadID(void)
} /* __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 ... */