From 62e36b61f7346a92edce908074ca88b0f15788d2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 24 May 2002 09:46:43 +0000 Subject: [PATCH] Initial add. --- extras/.cvsignore | 5 + platform/beos.cpp | 281 +++++++++++++++++++++++++++ platform/posix.c | 474 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 760 insertions(+) create mode 100644 extras/.cvsignore create mode 100644 platform/beos.cpp create mode 100644 platform/posix.c diff --git a/extras/.cvsignore b/extras/.cvsignore new file mode 100644 index 00000000..16fc9496 --- /dev/null +++ b/extras/.cvsignore @@ -0,0 +1,5 @@ +Makefile +.deps +.libs +Makefile.in + diff --git a/platform/beos.cpp b/platform/beos.cpp new file mode 100644 index 00000000..9dd9260e --- /dev/null +++ b/platform/beos.cpp @@ -0,0 +1,281 @@ +/* + * BeOS platform-dependent support routines for PhysicsFS. + * + * Please see the file LICENSE in the source's root directory. + * + * This file written by Ryan C. Gordon. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#ifdef __BEOS__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define __PHYSICSFS_INTERNAL__ +#include "physfs_internal.h" + + +const char *__PHYSFS_platformDirSeparator = "/"; + +/* !!! FIXME: does strerror() work for non-POSIX api calls? */ +#define get_error_str(x) strerror(x) + + +int __PHYSFS_platformInit(void) +{ + return(1); /* always succeed. */ +} /* __PHYSFS_platformInit */ + + +int __PHYSFS_platformDeinit(void) +{ + return(1); /* always succeed. */ +} /* __PHYSFS_platformDeinit */ + + + +/* caller needs to malloc() mntpnt, and expect us to free() it. */ +static void addDisc(char *mntpnt, char ***discs, int *disccount) +{ + char **tmp = (char **) realloc(*discs, sizeof (char *) * (*disccount + 1)); + if (tmp) + { + tmp[*disccount - 1] = mntpnt; + *discs = tmp; + (*disccount)++; + } /* if */ +} /* addDisc */ + + +static char *getMountPoint(const char *devname) +{ + BVolumeRoster mounts; + BVolume vol; + + mounts.Rewind(); + while (mounts.GetNextVolume(&vol) == B_NO_ERROR) + { + fs_info fsinfo; + fs_stat_dev(vol.Device(), &fsinfo); + if (strcmp(devname, fsinfo.device_name) == 0) + { + //char buf[B_FILE_NAME_LENGTH]; + BDirectory directory; + BEntry entry; + BPath path; + status_t rc; + rc = vol.GetRootDirectory(&directory); + BAIL_IF_MACRO(rc < B_OK, get_error_str(rc), NULL); + rc = directory.GetEntry(&entry); + BAIL_IF_MACRO(rc < B_OK, get_error_str(rc), NULL); + rc = entry.GetPath(&path); + BAIL_IF_MACRO(rc < B_OK, get_error_str(rc), NULL); + const char *str = path.Path(); + BAIL_IF_MACRO(str == NULL, ERR_OS_ERROR, NULL); /* ?! */ + char *retval = (char *) malloc(strlen(str) + 1); + BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); + strcpy(retval, str); + return(retval); + } /* if */ + } /* while */ + + return(NULL); +} /* getMountPoint */ + + + /* + * This function is lifted from Simple Directmedia Layer (SDL): + * http://www.libsdl.org/ + */ +static void tryDir(const char *dirname, char ***discs, int *disccount) +{ + BDirectory dir; + dir.SetTo(dirname); + if (dir.InitCheck() != B_NO_ERROR) + return; + + dir.Rewind(); + BEntry entry; + while (dir.GetNextEntry(&entry) >= 0) + { + BPath path; + const char *name; + entry_ref e; + + if (entry.GetPath(&path) != B_NO_ERROR) + continue; + + name = path.Path(); + + if (entry.GetRef(&e) != B_NO_ERROR) + continue; + + if (entry.IsDirectory()) + { + if (strcmp(e.name, "floppy") != 0) + tryDir(name, discs, disccount); + } /* if */ + + else + { + bool add_it = false; + int devfd; + device_geometry g; + + if (strcmp(e.name, "raw") == 0) /* ignore partitions. */ + { + int devfd = open(name, O_RDONLY); + if (devfd >= 0) + { + if (ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) + { + if (g.device_type == B_CD) + { + char *mntpnt = getMountPoint(name); + if (mntpnt != NULL) + addDisc(mntpnt, discs, disccount); + } /* if */ + } /* if */ + } /* if */ + } /* if */ + + close(devfd); + } /* else */ + } /* while */ +} /* tryDir */ + + +char **__PHYSFS_platformDetectAvailableCDs(void) +{ + char **retval = (char **) malloc(sizeof (char *)); + int cd_count = 1; /* We count the NULL entry. */ + BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); + tryDir("/dev/disk", &retval, &cd_count); + retval[cd_count - 1] = NULL; + return(retval); +} /* __PHYSFS_platformDetectAvailableCDs */ + + +static team_id getTeamID(void) +{ + thread_info info; + thread_id tid = find_thread(NULL); + get_thread_info(tid, &info); + return(info.team); +} /* getMyTeamID */ + + +char *__PHYSFS_platformCalcBaseDir(const char *argv0) +{ + /* in case there isn't a BApplication yet, we'll construct a roster. */ + BRoster roster; + app_info info; + status_t rc = roster.GetRunningAppInfo(getTeamID(), &info); + BAIL_IF_MACRO(rc < B_OK, get_error_str(rc), NULL); + BEntry entry(&(info.ref), true); + BPath path; + rc = entry.GetPath(&path); /* (path) now has binary's path. */ + assert(rc == B_OK); + rc = path.GetParent(&path); /* chop filename, keep directory. */ + assert(rc == B_OK); + const char *str = path.Path(); + assert(str != NULL); + char *retval = (char *) malloc(strlen(str) + 1); + BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); + strcpy(retval, str); + return(retval); +} /* __PHYSFS_platformCalcBaseDir */ + + +PHYSFS_uint64 __PHYSFS_platformGetThreadID(void) +{ + return((PHYSFS_uint64) find_thread(NULL)); +} /* __PHYSFS_platformGetThreadID */ + + +/* Much like my college days, try to sleep for 10 milliseconds at a time... */ +void __PHYSFS_platformTimeslice(void) +{ + snooze(10000); /* put thread to sleep for 10 milliseconds. */ +} /* __PHYSFS_platformTimeslice */ + + +char *__PHYSFS_platformRealPath(const char *path) +{ + char *str = (char *) alloca(strlen(path) + 1); + BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, NULL); + strcpy(str, path); + char *leaf = strrchr(str, '/'); + if (leaf != NULL) + *(leaf++) = '\0'; + + BPath normalized(str, leaf, true); /* force normalization of path. */ + const char *resolved_path = normalized.Path(); + BAIL_IF_MACRO(resolved_path == NULL, ERR_FILE_NOT_FOUND, NULL); + char *retval = (char *) malloc(strlen(resolved_path) + 1); + BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); + strcpy(retval, resolved_path); + return(retval); +} /* __PHYSFS_platformRealPath */ + + +void *__PHYSFS_platformCreateMutex(void) +{ + sem_id *retval = (sem_id *) malloc(sizeof (sem_id)); + sem_id rc; + + BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); + rc = create_sem(1, "PhysicsFS semaphore"); + if (rc < B_OK) + { + free(retval); + BAIL_MACRO(get_error_str(rc), NULL); + } // if + + *retval = rc; + return(retval); +} /* __PHYSFS_platformCreateMutex */ + + +void __PHYSFS_platformDestroyMutex(void *mutex) +{ + delete_sem( *((sem_id *) mutex) ); + free(mutex); +} /* __PHYSFS_platformDestroyMutex */ + + +int __PHYSFS_platformGrabMutex(void *mutex) +{ + status_t rc = acquire_sem(*((sem_id *) mutex)); + BAIL_IF_MACRO(rc < B_OK, get_error_str(rc), 0); + return(1); +} /* __PHYSFS_platformGrabMutex */ + + +void __PHYSFS_platformReleaseMutex(void *mutex) +{ + release_sem(*((sem_id *) mutex)); +} /* __PHYSFS_platformReleaseMutex */ + +#endif + +/* end of beos.cpp ... */ + diff --git a/platform/posix.c b/platform/posix.c new file mode 100644 index 00000000..c87d2eb5 --- /dev/null +++ b/platform/posix.c @@ -0,0 +1,474 @@ +/* + * Posix-esque support routines for PhysicsFS. + * + * Please see the file LICENSE in the source's root directory. + * + * This file written by Ryan C. Gordon. + */ + +#if HAVE_CONFIG_H +# include +#endif + +#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 +#if (defined __PHYSFS_DOING_STRICT_ANSI__) +#define __STRICT_ANSI__ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __PHYSICSFS_INTERNAL__ +#include "physfs_internal.h" + + +char *__PHYSFS_platformCopyEnvironmentVariable(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); +} /* __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)) + { + 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 = __PHYSFS_platformCopyEnvironmentVariable("USER"); + return(retval); +} /* __PHYSFS_platformGetUserName */ + + +char *__PHYSFS_platformGetUserDir(void) +{ + char *retval = __PHYSFS_platformCopyEnvironmentVariable("HOME"); + if (retval == NULL) + retval = getUserDirByUID(); + return(retval); +} /* __PHYSFS_platformGetUserDir */ + + +/* -ansi and -pedantic flags prevent use of strcasecmp() on Linux. */ +int __PHYSFS_platformStricmp(const char *x, const char *y) +{ + 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_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 */ + + + +LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname, + int omitSymLinks) +{ + LinkedStringList *retval = NULL; + LinkedStringList *l = NULL; + LinkedStringList *prev = NULL; + DIR *dir; + struct dirent *ent; + int bufsize = 0; + char *buf = NULL; + int dlen = 0; + + if (omitSymLinks) + { + dlen = strlen(dirname); + bufsize = dlen + 256; + buf = malloc(bufsize); + BAIL_IF_MACRO(buf == NULL, ERR_OUT_OF_MEMORY, NULL); + strcpy(buf, dirname); + if (buf[dlen - 1] != '/') + { + buf[dlen++] = '/'; + buf[dlen] = '\0'; + } /* if */ + } /* if */ + + errno = 0; + dir = opendir(dirname); + if (dir == NULL) + { + if (buf != NULL) + free(buf); + BAIL_IF_MACRO(1, strerror(errno), NULL); + } /* if */ + + while (1) + { + ent = readdir(dir); + if (ent == NULL) /* we're done. */ + break; + + 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) + { + p = realloc(buf, len); + if (p == NULL) + continue; + buf = p; + bufsize = len; + } /* if */ + + strcpy(buf + dlen, ent->d_name); + if (__PHYSFS_platformIsSymLink(buf)) + continue; + } /* if */ + + 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 */ + + strcpy(l->str, ent->d_name); + + if (retval == NULL) + retval = l; + else + prev->next = l; + + prev = l; + l->next = NULL; + } /* while */ + + if (buf != NULL) + free(buf); + + closedir(dir); + return(retval); +} /* __PHYSFS_platformEnumerateFiles */ + + +char *__PHYSFS_platformCurrentDir(void) +{ + int allocSize = 0; + char *retval = NULL; + char *ptr; + + do + { + allocSize += 100; + ptr = (char *) realloc(retval, allocSize); + if (ptr == NULL) + { + if (retval != NULL) + free(retval); + BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); + } /* if */ + + retval = ptr; + ptr = getcwd(retval, allocSize); + } while (ptr == NULL && errno == ERANGE); + + if (ptr == NULL && errno) + { + /* + * getcwd() failed for some reason, for example current + * directory not existing. + */ + if (retval != NULL) + free(retval); + BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); + } /* if */ + + return(retval); +} /* __PHYSFS_platformCurrentDir */ + + + +int __PHYSFS_platformMkDir(const char *path) +{ + int rc; + errno = 0; + rc = mkdir(path, S_IRWXU); + BAIL_IF_MACRO(rc == -1, strerror(errno), 0); + return(1); +} /* __PHYSFS_platformMkDir */ + + +static void *doOpen(const char *filename, const char *mode) +{ + FILE *retval; + errno = 0; + + retval = fopen(filename, mode); + if (retval == NULL) + __PHYSFS_setError(strerror(errno)); + + return((void *) retval); +} /* doOpen */ + + +void *__PHYSFS_platformOpenRead(const char *filename) +{ + return(doOpen(filename, "rb")); +} /* __PHYSFS_platformOpenRead */ + + +void *__PHYSFS_platformOpenWrite(const char *filename) +{ + return(doOpen(filename, "wb")); +} /* __PHYSFS_platformOpenWrite */ + + +void *__PHYSFS_platformOpenAppend(const char *filename) +{ + return(doOpen(filename, "ab")); +} /* __PHYSFS_platformOpenAppend */ + + +PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer, + PHYSFS_uint32 size, PHYSFS_uint32 count) +{ + FILE *io = (FILE *) opaque; + int rc = fread(buffer, size, count, io); + if (rc < count) + { + int err = errno; + BAIL_IF_MACRO(ferror(io), strerror(err), rc); + BAIL_MACRO(ERR_PAST_EOF, rc); + } /* if */ + + return(rc); +} /* __PHYSFS_platformRead */ + + +PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, + PHYSFS_uint32 size, PHYSFS_uint32 count) +{ + FILE *io = (FILE *) opaque; + int rc = fwrite((void *) buffer, size, count, io); + if (rc < count) + __PHYSFS_setError(strerror(errno)); + + return(rc); +} /* __PHYSFS_platformWrite */ + + +int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos) +{ + FILE *io = (FILE *) opaque; + + /* !!! FIXME: Use llseek where available. */ + errno = 0; + BAIL_IF_MACRO(fseek(io, pos, SEEK_SET) != 0, strerror(errno), 0); + + return(1); +} /* __PHYSFS_platformSeek */ + + +PHYSFS_sint64 __PHYSFS_platformTell(void *opaque) +{ + FILE *io = (FILE *) opaque; + PHYSFS_sint64 retval = ftell(io); + BAIL_IF_MACRO(retval == -1, strerror(errno), -1); + return(retval); +} /* __PHYSFS_platformTell */ + + +PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque) +{ + FILE *io = (FILE *) opaque; + struct stat statbuf; + errno = 0; + BAIL_IF_MACRO(fstat(fileno(io), &statbuf) == -1, strerror(errno), -1); + return((PHYSFS_sint64) statbuf.st_size); +} /* __PHYSFS_platformFileLength */ + + +int __PHYSFS_platformEOF(void *opaque) +{ + return(feof((FILE *) opaque)); +} /* __PHYSFS_platformEOF */ + + +int __PHYSFS_platformFlush(void *opaque) +{ + errno = 0; + BAIL_IF_MACRO(fflush((FILE *) opaque) == EOF, strerror(errno), 0); + return(1); +} /* __PHYSFS_platformFlush */ + + +int __PHYSFS_platformClose(void *opaque) +{ + errno = 0; + BAIL_IF_MACRO(fclose((FILE *) opaque) == EOF, strerror(errno), 0); + return(1); +} /* __PHYSFS_platformClose */ + + +int __PHYSFS_platformDelete(const char *path) +{ + errno = 0; + BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0); + return(1); +} /* __PHYSFS_platformDelete */ + +/* end of posix.c ... */ +