diff --git a/src/physfs/archivers/zip.c b/src/physfs/archivers/zip.c index 00f3176d4bf25650f8ae81242001c1aa4665572c..ba10f277068d9575aad8bb03fe5738cc46f849a6 100644 --- a/src/physfs/archivers/zip.c +++ b/src/physfs/archivers/zip.c @@ -375,13 +375,13 @@ static int ZIP_fileClose(fvoid *opaque) static PHYSFS_sint64 zip_find_end_of_central_dir(void *in, PHYSFS_sint64 *len) { PHYSFS_uint8 buf[256]; + PHYSFS_uint8 extra[4] = { 0, 0, 0, 0 }; PHYSFS_sint32 i = 0; PHYSFS_sint64 filelen; PHYSFS_sint64 filepos; PHYSFS_sint32 maxread; PHYSFS_sint32 totalread = 0; int found = 0; - PHYSFS_uint32 extra = 0; filelen = __PHYSFS_platformFileLength(in); BAIL_IF_MACRO(filelen == -1, NULL, 0); /* !!! FIXME: unlocalized string */ @@ -419,7 +419,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(void *in, PHYSFS_sint64 *len) { if (__PHYSFS_platformRead(in, buf, maxread - 4, 1) != 1) return(-1); - *((PHYSFS_uint32 *) (&buf[maxread - 4])) = extra; + memcpy(&buf[maxread - 4], &extra, sizeof (extra)); totalread += maxread - 4; } /* if */ else @@ -429,7 +429,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(void *in, PHYSFS_sint64 *len) totalread += maxread; } /* else */ - extra = *((PHYSFS_uint32 *) (&buf[0])); + memcpy(&extra, buf, sizeof (extra)); for (i = maxread - 4; i > 0; i--) { @@ -544,8 +544,11 @@ static ZIPentry *zip_find_entry(ZIPinfo *info, const char *path, int *isDir) if (thispath[pathlen] == '\0') /* found entry? */ return(&a[middle]); + /* adjust search params, try again. */ + else if (thispath[pathlen] > '/') + hi = middle - 1; else - hi = middle - 1; /* adjust search params, try again. */ + lo = middle + 1; } /* if */ } /* while */ diff --git a/src/physfs/physfs.c b/src/physfs/physfs.c index 1b62eacfa5661654c7318b69484dc833ffa85d60..49281e89e1cd3ab4623390c42c179ac82ec115d4 100644 --- a/src/physfs/physfs.c +++ b/src/physfs/physfs.c @@ -605,18 +605,21 @@ static int freeDirHandle(DirHandle *dh, FileHandle *openList) static char *calculateUserDir(void) { - char *retval = NULL; - const char *str = NULL; + char *retval = __PHYSFS_platformGetUserDir(); + if (retval != NULL) + { + /* make sure it really exists and is normalized. */ + char *ptr = __PHYSFS_platformRealPath(retval); + allocator.Free(retval); + retval = ptr; + } /* if */ - str = __PHYSFS_platformGetUserDir(); - if (str != NULL) - retval = (char *) str; - else + if (retval == NULL) { const char *dirsep = PHYSFS_getDirSeparator(); const char *uname = __PHYSFS_platformGetUserName(); + const char *str = (uname != NULL) ? uname : "default"; - str = (uname != NULL) ? uname : "default"; retval = (char *) allocator.Malloc(strlen(baseDir) + strlen(str) + strlen(dirsep) + 6); @@ -754,13 +757,6 @@ int PHYSFS_init(const char *argv0) BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0); userDir = calculateUserDir(); - if (userDir != NULL) - { - ptr = __PHYSFS_platformRealPath(userDir); - allocator.Free(userDir); - userDir = ptr; - } /* if */ - if ((userDir == NULL) || (!appendDirSep(&userDir))) { allocator.Free(baseDir); diff --git a/src/physfs/physfs.h b/src/physfs/physfs.h index 7a242649249db43a146d96ceeb681be1e4bdbb72..f0d78d72173a058f2754d870506558ce86d33f0c 100644 --- a/src/physfs/physfs.h +++ b/src/physfs/physfs.h @@ -1,4 +1,8 @@ -/** \file physfs.h */ +/** + * \file physfs.h + * + * Main header file for PhysicsFS. + */ #define PHYSFS_NO_CDROM_SUPPORT @@ -403,7 +407,7 @@ typedef struct PHYSFS_Version #ifndef DOXYGEN_SHOULD_IGNORE_THIS #define PHYSFS_VER_MAJOR 2 #define PHYSFS_VER_MINOR 0 -#define PHYSFS_VER_PATCH 0 +#define PHYSFS_VER_PATCH 2 #endif /* DOXYGEN_SHOULD_IGNORE_THIS */ @@ -1000,7 +1004,7 @@ __EXPORT__ const char *PHYSFS_getRealDir(const char *filename); * PHYSFS_freeList(rc); * \endcode * - * ...will print: + * \...will print: * * \verbatim * We've got [x.sav]. @@ -1225,9 +1229,9 @@ __EXPORT__ PHYSFS_sint64 PHYSFS_read(PHYSFS_File *handle, * The file must be opened for writing. * * \param handle retval from PHYSFS_openWrite() or PHYSFS_openAppend(). - * \param buffer buffer to store read data into. - * \param objSize size in bytes of objects being read from (handle). - * \param objCount number of (objSize) objects to read from (handle). + * \param buffer buffer of bytes to write to (handle). + * \param objSize size in bytes of objects being written to (handle). + * \param objCount number of (objSize) objects to write to (handle). * \return number of objects written. PHYSFS_getLastError() can shed light on * the reason this might be < (objCount). -1 if complete failure. */ @@ -2282,7 +2286,7 @@ __EXPORT__ void PHYSFS_enumerateFilesCallback(const char *dir, * * Strings that don't fit in the destination buffer will be truncated, but * will always be null-terminated and never have an incomplete UTF-8 - * sequence at the end. + * sequence at the end. If the buffer length is 0, this function does nothing. * * \param src Null-terminated source string in UCS-4 format. * \param dst Buffer to store converted UTF-8 string. @@ -2304,7 +2308,7 @@ __EXPORT__ void PHYSFS_utf8FromUcs4(const PHYSFS_uint32 *src, char *dst, * * Strings that don't fit in the destination buffer will be truncated, but * will always be null-terminated and never have an incomplete UCS-4 - * sequence at the end. + * sequence at the end. If the buffer length is 0, this function does nothing. * * \param src Null-terminated source string in UTF-8 format. * \param dst Buffer to store converted UCS-4 string. @@ -2327,7 +2331,7 @@ __EXPORT__ void PHYSFS_utf8ToUcs4(const char *src, PHYSFS_uint32 *dst, * * Strings that don't fit in the destination buffer will be truncated, but * will always be null-terminated and never have an incomplete UTF-8 - * sequence at the end. + * sequence at the end. If the buffer length is 0, this function does nothing. * * Please note that UCS-2 is not UTF-16; we do not support the "surrogate" * values at this time. @@ -2353,7 +2357,7 @@ __EXPORT__ void PHYSFS_utf8FromUcs2(const PHYSFS_uint16 *src, char *dst, * * Strings that don't fit in the destination buffer will be truncated, but * will always be null-terminated and never have an incomplete UCS-2 - * sequence at the end. + * sequence at the end. If the buffer length is 0, this function does nothing. * * Please note that UCS-2 is not UTF-16; we do not support the "surrogate" * values at this time. @@ -2379,7 +2383,7 @@ __EXPORT__ void PHYSFS_utf8ToUcs2(const char *src, PHYSFS_uint16 *dst, * * Strings that don't fit in the destination buffer will be truncated, but * will always be null-terminated and never have an incomplete UTF-8 - * sequence at the end. + * sequence at the end. If the buffer length is 0, this function does nothing. * * Please note that we do not supply a UTF-8 to Latin1 converter, since Latin1 * can't express most Unicode codepoints. It's a legacy encoding; you should diff --git a/src/physfs/physfs_internal.h b/src/physfs/physfs_internal.h index 187b50dc2aff985ed27f31f0fd5a4a0e712d6c85..89114954bc6a15c9fd47dabe95310d2b23869fe5 100644 --- a/src/physfs/physfs_internal.h +++ b/src/physfs/physfs_internal.h @@ -29,6 +29,10 @@ #include <malloc.h> #endif +#if defined(__sun) || defined(sun) +#include <alloca.h> +#endif + #ifdef __cplusplus extern "C" { #endif @@ -969,7 +973,7 @@ char *__PHYSFS_convertToDependent(const char *prepend, #define PHYSFS_LIL_ENDIAN 1234 #define PHYSFS_BIG_ENDIAN 4321 -#if defined(__i386__) || defined(__ia64__) || defined(WIN32) || \ +#if defined(__i386__) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || \ (defined(__alpha__) || defined(__alpha)) || \ defined(__arm__) || defined(ARM) || \ (defined(__mips__) && defined(__MIPSEL__)) || \ diff --git a/src/physfs/physfs_unicode.c b/src/physfs/physfs_unicode.c index 030bcc869f7ea33621b32022ee90f3c455c0b55d..d9cc73ffc79dbba36e2ff49ec6b99cdd8c8a9f00 100644 --- a/src/physfs/physfs_unicode.c +++ b/src/physfs/physfs_unicode.c @@ -305,10 +305,11 @@ static void utf8fromcodepoint(PHYSFS_uint32 cp, char **_dst, PHYSFS_uint64 *_len } /* utf8fromcodepoint */ #define UTF8FROMTYPE(typ, src, dst, len) \ + if (len == 0) return; \ len--; \ while (len) \ { \ - const PHYSFS_uint32 cp = (PHYSFS_uint32) *(src++); \ + const PHYSFS_uint32 cp = (PHYSFS_uint32) ((typ) (*(src++))); \ if (cp == 0) break; \ utf8fromcodepoint(cp, &dst, &len); \ } \ diff --git a/src/physfs/platform/posix.c b/src/physfs/platform/posix.c index 22b8408854acc28c0456ff8dec59af2673111ec6..a736b52d0018027ddd755d8ee95fc2a72c751f8a 100644 --- a/src/physfs/platform/posix.c +++ b/src/physfs/platform/posix.c @@ -97,8 +97,21 @@ char *__PHYSFS_platformGetUserName(void) char *__PHYSFS_platformGetUserDir(void) { char *retval = __PHYSFS_platformCopyEnvironmentVariable("HOME"); + + /* 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 */ + if (retval == NULL) retval = getUserDirByUID(); + return(retval); } /* __PHYSFS_platformGetUserDir */ diff --git a/src/physfs/platform/unix.c b/src/physfs/platform/unix.c index 2b47cc99029f7f4e009f3dfac0d02f0a880e3084..4e714b40bb4e5f9d266dba776031c863249f4571 100644 --- a/src/physfs/platform/unix.c +++ b/src/physfs/platform/unix.c @@ -23,9 +23,8 @@ #include <dirent.h> #include <time.h> #include <errno.h> -#include <sys/mount.h> -#if (!defined PHYSFS_NO_PTHREADS_SUPPORT) +#if (!defined PHYSFS_NO_THREAD_SUPPORT) #include <pthread.h> #endif @@ -34,6 +33,7 @@ # undef PHYSFS_HAVE_MNTENT_H /* don't do both... */ # endif # include <sys/ucred.h> +# include <sys/mount.h> #endif #ifdef PHYSFS_HAVE_MNTENT_H @@ -42,6 +42,9 @@ #include "physfs_internal.h" +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif int __PHYSFS_platformInit(void) { @@ -101,6 +104,14 @@ void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data) int add_it = 0; if (strcmp(ent->mnt_type, "iso9660") == 0) add_it = 1; + else if (strcmp(ent->mnt_type, "udf") == 0) + add_it = 1; + + /* !!! FIXME: these might pick up floppy drives, right? */ + else if (strcmp(ent->mnt_type, "auto") == 0) + add_it = 1; + else if (strcmp(ent->mnt_type, "supermount") == 0) + add_it = 1; /* add other mount types here */ @@ -182,12 +193,42 @@ static char *findBinaryInPath(const char *bin, char *envr) } /* findBinaryInPath */ +static char *readSymLink(const char *path) +{ + ssize_t len = 64; + ssize_t rc = -1; + char *retval = NULL; + + while (1) + { + char *ptr = (char *) allocator.Realloc(retval, (size_t) len); + if (ptr == NULL) + break; /* out of memory. */ + retval = ptr; + + rc = readlink(path, retval, len); + if (rc == -1) + break; /* not a symlink, i/o error, etc. */ + + else if (rc < len) + { + retval[rc] = '\0'; /* readlink doesn't null-terminate. */ + return retval; /* we're good to go. */ + } /* else if */ + + len *= 2; /* grow buffer, try again. */ + } /* while */ + + if (retval != NULL) + allocator.Free(retval); + return NULL; +} /* readSymLink */ + + char *__PHYSFS_platformCalcBaseDir(const char *argv0) { - const char *PROC_SELF_EXE = "/proc/self/exe"; char *retval = NULL; char *envr = NULL; - struct stat stbuf; /* fast path: default behaviour can handle this. */ if ( (argv0 != NULL) && (strchr(argv0, '/') != NULL) ) @@ -198,20 +239,22 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0) * /proc filesystem, you can get the full path to the current process from * the /proc/self/exe symlink. */ - if ((lstat(PROC_SELF_EXE, &stbuf) != -1) && (S_ISLNK(stbuf.st_mode))) + retval = readSymLink("/proc/self/exe"); + if (retval == NULL) { - const size_t len = stbuf.st_size; - char *buf = (char *) allocator.Malloc(len+1); - if (buf != NULL) /* if NULL, maybe you'll get lucky later. */ - { - if (readlink(PROC_SELF_EXE, buf, len) != len) - allocator.Free(buf); - else - { - buf[len] = '\0'; /* readlink doesn't null-terminate. */ - retval = buf; /* we're good to go. */ - } /* else */ - } /* if */ + /* older kernels don't have /proc/self ... try PID version... */ + const unsigned long long pid = (unsigned long long) getpid(); + char path[64]; + const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid); + if ( (rc > 0) && (rc < sizeof(path)) ) + retval = readSymLink(path); + } /* if */ + + if (retval != NULL) /* chop off filename. */ + { + char *ptr = strrchr(retval, '/'); + if (ptr != NULL) + *ptr = '\0'; } /* if */ if ((retval == NULL) && (argv0 != NULL)) @@ -223,6 +266,14 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0) allocator.Free(envr); } /* if */ + if (retval != NULL) + { + /* try to shrink buffer... */ + char *ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1); + if (ptr != NULL) + retval = ptr; /* oh well if it failed. */ + } /* if */ + return(retval); } /* __PHYSFS_platformCalcBaseDir */ @@ -289,7 +340,7 @@ int __PHYSFS_platformSetDefaultAllocator(PHYSFS_Allocator *a) } /* __PHYSFS_platformSetDefaultAllocator */ -#if (defined PHYSFS_NO_PTHREADS_SUPPORT) +#if (defined PHYSFS_NO_THREAD_SUPPORT) PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) { return(0x0001); } void *__PHYSFS_platformCreateMutex(void) { return((void *) 0x0001); } @@ -387,7 +438,7 @@ void __PHYSFS_platformReleaseMutex(void *mutex) } /* if */ } /* __PHYSFS_platformReleaseMutex */ -#endif /* !PHYSFS_NO_PTHREADS_SUPPORT */ +#endif /* !PHYSFS_NO_THREAD_SUPPORT */ #endif /* PHYSFS_PLATFORM_UNIX */ diff --git a/src/physfs/platform/windows.c b/src/physfs/platform/windows.c index 02c595bad36efe29da6ad90bf9466dc9e8a4617e..c5b05c7ea2cdce0d254a77b11bb45276a3ab3033 100644 --- a/src/physfs/platform/windows.c +++ b/src/physfs/platform/windows.c @@ -1027,8 +1027,8 @@ static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly) UTF8_TO_UNICODE_STACK_MACRO(wfname, fname); BAIL_IF_MACRO(wfname == NULL, ERR_OUT_OF_MEMORY, NULL); - fileHandle = pCreateFileW(wfname, mode, FILE_SHARE_READ, NULL, - creation, FILE_ATTRIBUTE_NORMAL, NULL); + fileHandle = pCreateFileW(wfname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); __PHYSFS_smallFree(wfname); BAIL_IF_MACRO