From 83949a60dc0e34582ee1e2ffb95aec0c7781dcc8 Mon Sep 17 00:00:00 2001 From: Meep-Eep Date: Thu, 8 Oct 2009 21:17:42 +0000 Subject: [PATCH] uio_access() work in progress. Commented out for now. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3208 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/src/sc2code/libs/uio/doc/todo | 3 + sc2/src/sc2code/libs/uio/fstypes.h | 1 + sc2/src/sc2code/libs/uio/io.c | 140 +++++++++++++++++++++++++ sc2/src/sc2code/libs/uio/stdio/stdio.c | 24 +++++ sc2/src/sc2code/libs/uio/stdio/stdio.h | 2 + sc2/src/sc2code/libs/uio/zip/zip.c | 56 +++++++++- sc2/src/sc2code/libs/uio/zip/zip.h | 9 ++ 7 files changed, 233 insertions(+), 2 deletions(-) diff --git a/sc2/src/sc2code/libs/uio/doc/todo b/sc2/src/sc2code/libs/uio/doc/todo index 807bc8d99..b9f232cb5 100644 --- a/sc2/src/sc2code/libs/uio/doc/todo +++ b/sc2/src/sc2code/libs/uio/doc/todo @@ -57,6 +57,9 @@ Bugs: - Network paths on Windows are not accepted. - No CRLF translation (and ^Z recognition) is done for files read from zip files, even though that may be expected on Windows. +- The order in which "uio_unmountAllDirs() unmounts the directories, may lead + it to unmount a dir while there still is a file descriptor for another + dir open, causing a warning. Extra features (not necessary for UQM): - Make functions to use for uio_malloc, uio_free and uio_realloc diff --git a/sc2/src/sc2code/libs/uio/fstypes.h b/sc2/src/sc2code/libs/uio/fstypes.h index 27986d6fe..3b6883a50 100644 --- a/sc2/src/sc2code/libs/uio/fstypes.h +++ b/sc2/src/sc2code/libs/uio/fstypes.h @@ -59,6 +59,7 @@ struct uio_FileSystemHandler { struct uio_PRoot * (*mount) (uio_Handle *, int); int (*umount) (uio_PRoot *); + int (*access) (uio_PDirHandle *, const char *, int mode); void (*close) (uio_Handle *); // called when the last reference is closed, not // necessarilly each time when uio_close() is called diff --git a/sc2/src/sc2code/libs/uio/io.c b/sc2/src/sc2code/libs/uio/io.c index 4fa332b23..a7c721e67 100644 --- a/sc2/src/sc2code/libs/uio/io.c +++ b/sc2/src/sc2code/libs/uio/io.c @@ -39,6 +39,10 @@ # include "memdebug.h" #endif +#if 0 +static int uio_accessDir(uio_DirHandle *dirHandle, const char *path, + int mode); +#endif static int uio_statDir(uio_DirHandle *dirHandle, const char *path, struct stat *statBuf); static int uio_statOneDir(uio_PDirHandle *pDirHandle, struct stat *statBuf); @@ -414,6 +418,134 @@ uio_rename(uio_DirHandle *oldDir, const char *oldPath, return 0; } +int +uio_access(uio_DirHandle *dir, const char *path, int mode) { + (void) dir; + (void) path; + (void) mode; + errno = ENOSYS; // Not implemented. + return -1; + +#if 0 + uio_PDirHandle *pReadDir; + uio_MountInfo *readMountInfo; + char *name; + int result; + + if (uio_getPhysicalAccess(dir, path, O_RDONLY, 0, + &readMountInfo, &pReadDir, NULL, + NULL, NULL, NULL, &name) == -1) { + // XXX: I copied this part from uio_stat(). Is this what I need? + if (uio_accessDir(dir, path, statBuf) == -1) { + // errno is set + return -1; + } + return 0; + } + + if (pReadDir->pRoot->handler->access == NULL) { + uio_PDirHandle_unref(pReadDir); + uio_free(name); + errno = ENOSYS; + return -1; + } + + result = (pReadDir->pRoot->handler->access)(pReadDir, name, mode); + if (result == -1) { + int savedErrno = errno; + uio_PDirHandle_unref(pReadDir); + uio_free(name); + errno = savedErrno; + return -1; + } + + uio_PDirHandle_unref(pReadDir); + uio_free(name); + return result; +#endif +} + +#if 0 +// auxiliary function to uio_access +static int +uio_accessDir(uio_DirHandle *dirHandle, const char *path, int mode) { + int numPDirHandles; + uio_PDirHandle **pDirHandles; + + if (mode & R_OK) + { + // Read permission is always granted. Nothing to check here. + } + + if (uio_getPathPhysicalDirs(dirHandle, path, strlen(path), + &pDirHandles, &numPDirHandles, NULL) == -1) { + // errno is set + return -1; + } + + if (numPDirHandles == 0) { + errno = ENOENT; + return -1; + } + + if (mode & F_OK) + { + // We need to check whether each of the directories is complete + + // WORK + } + + if (mode & W_OK) { + // If there is any directory where writing is allowed, then + // we can write. + + // WORK + errno = ENOENT; + return -1; + +#if 0 + if (uio_statOneDir(pDirHandles[0], statBuf) == -1) { + int savedErrno = errno; + uio_PDirHandles_delete(pDirHandles, numPDirHandles); + errno = savedErrno; + return -1; + } + // TODO: atm, fstat'ing a dir will show the info for the topmost + // dir. Maybe it would make sense of merging the bits. (How?) + +#if 0 + for (i = 1; i < numPDirHandles; i++) { + struct stat statOne; + uio_PDirHandle *pDirHandle; + + if (statOneDir(pDirHandles[i], &statOne) == -1) { + // errno is set + int savedErrno = errno; + uio_PDirHandles_delete(pDirHandles, numPDirHandles); + errno = savedErrno; + return -1; + } + + // Merge dirs: + + + } +#endif +#endif + } + + if (mode & X_OK) { + // XXX: Not implemented. + uio_PDirHandles_delete(pDirHandles, numPDirHandles); + errno = ENOSYS; + return -1; + } + + uio_PDirHandles_delete(pDirHandles, numPDirHandles); + return 0; +} +#endif + int uio_fstat(uio_Handle *handle, struct stat *statBuf) { if (handle->root->handler->fstat == NULL) { @@ -448,6 +580,14 @@ uio_stat(uio_DirHandle *dir, const char *path, struct stat *statBuf) { } result = (pReadDir->pRoot->handler->stat)(pReadDir, name, statBuf); + if (result == -1) { + int savedErrno = errno; + uio_PDirHandle_unref(pReadDir); + uio_free(name); + errno = savedErrno; + return -1; + } + uio_PDirHandle_unref(pReadDir); uio_free(name); return result; diff --git a/sc2/src/sc2code/libs/uio/stdio/stdio.c b/sc2/src/sc2code/libs/uio/stdio/stdio.c index 3d8b5a963..a4421d120 100644 --- a/sc2/src/sc2code/libs/uio/stdio/stdio.c +++ b/sc2/src/sc2code/libs/uio/stdio/stdio.c @@ -70,6 +70,7 @@ uio_FileSystemHandler stdio_fileSystemHandler = { /* .mount = */ stdio_mount, /* .umount = */ uio_GPRoot_umount, + /* .access = */ stdio_access, /* .close = */ stdio_close, /* .fstat = */ stdio_fstat, /* .stat = */ stdio_stat, @@ -120,6 +121,29 @@ stdio_close(uio_Handle *handle) { } } +int +stdio_access(uio_PDirHandle *pDirHandle, const char *name, int mode) { + char *path; + int result; + + path = joinPaths(stdio_getPath(pDirHandle->extra), name); + if (path == NULL) { + // errno is set + return -1; + } + + result = access(path, mode); + if (result == -1) { + int savedErrno = errno; + uio_free(path); + errno = savedErrno; + return -1; + } + + uio_free(path); + return result; +} + int stdio_fstat(uio_Handle *handle, struct stat *statBuf) { return fstat(handle->native->fd, statBuf); diff --git a/sc2/src/sc2code/libs/uio/stdio/stdio.h b/sc2/src/sc2code/libs/uio/stdio/stdio.h index f59b3f18c..914a1d778 100644 --- a/sc2/src/sc2code/libs/uio/stdio/stdio.h +++ b/sc2/src/sc2code/libs/uio/stdio/stdio.h @@ -83,6 +83,8 @@ uio_PDirHandle *stdio_mkdir(uio_PDirHandle *pDirHandle, const char *name, uio_Handle *stdio_open(uio_PDirHandle *pDirHandle, const char *file, int flags, mode_t mode); void stdio_close(uio_Handle *handle); +int zip_access(uio_PDirHandle *pDirHandle, const char *name, int mode); +int stdio_access(uio_PDirHandle *pDirHandle, const char *name, int mode); int stdio_fstat(uio_Handle *handle, struct stat *statBuf); int stdio_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf); diff --git a/sc2/src/sc2code/libs/uio/zip/zip.c b/sc2/src/sc2code/libs/uio/zip/zip.c index 119491f6a..6da462bca 100644 --- a/sc2/src/sc2code/libs/uio/zip/zip.c +++ b/sc2/src/sc2code/libs/uio/zip/zip.c @@ -98,6 +98,7 @@ uio_FileSystemHandler zip_fileSystemHandler = { /* .mount = */ zip_mount, /* .umount = */ uio_GPRoot_umount, + /* .access = */ zip_access, /* .close = */ zip_close, /* .fstat = */ zip_fstat, /* .stat = */ zip_stat, @@ -218,6 +219,55 @@ zip_fillStat(struct stat *statBuf, const zip_GPFileData *gPFileData) { statBuf->st_ctime = gPFileData->ctime; } +int +zip_access(uio_PDirHandle *pDirHandle, const char *name, int mode) { + errno = ENOSYS; // Not implemented. + (void) pDirHandle; + (void) name; + (void) mode; + return -1; + +#if 0 + uio_GPDirEntry *entry; + + if (name[0] == '.' && name[1] == '\0') { + entry = (uio_GPDirEntry *) pDirHandle->extra; + } else { + entry = uio_GPDir_getGPDirEntry(pDirHandle->extra, name); + if (entry == NULL) { + errno = ENOENT; + return -1; + } + } + + if (mode & R_OK) + { + // Read permission is always granted. Nothing to check here. + } + + if (mode & W_OK) { + errno = EACCES; + return -1; + } + + if (mode & X_OK) { + if (uio_GPDirEntry_isDir(entry)) { + // Search permission on directories is always granted. + } else { + // WORK +#error + } + } + + if (mode & F_OK) { + // WORK +#error + } + + return 0; +#endif +} + int zip_fstat(uio_Handle *handle, struct stat *statBuf) { #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS @@ -229,7 +279,7 @@ zip_fstat(uio_Handle *handle, struct stat *statBuf) { return -1; } } -#endif +#endif /* zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS */ zip_fillStat(statBuf, handle->native->file->extra); return 0; } @@ -261,6 +311,7 @@ zip_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf) { } #if zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS +#ifndef zip_INCOMPLETE_STAT if (((zip_GPFileData *) entry->extra)->fileOffset == -1) { // The local header wasn't read in yet. if (zip_updateFileDataFromLocalHeader(pDirHandle->pRoot->handle, @@ -269,7 +320,8 @@ zip_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf) { return -1; } } -#endif +#endif /* !defined(zip_INCOMPLETE_STAT) */ +#endif /* zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS */ zip_fillStat(statBuf, (zip_GPFileData *) entry->extra); return 0; diff --git a/sc2/src/sc2code/libs/uio/zip/zip.h b/sc2/src/sc2code/libs/uio/zip/zip.h index 0c02f385e..4b2762f37 100644 --- a/sc2/src/sc2code/libs/uio/zip/zip.h +++ b/sc2/src/sc2code/libs/uio/zip/zip.h @@ -47,6 +47,14 @@ typedef struct uio_GPDirEntries_Iterator *uio_NativeEntriesContext; #define zip_USE_CENTRAL_HEADERS 1 #define zip_USE_LOCAL_HEADERS 2 +#define zip_INCOMPLETE_STAT + // Ignored unless zip_USE_HEADERS == zip_USE_CENTRAL_HEADERS. + // If defined, extra meta-data for files in the .zip archive + // isn't retrieved from the local file header when zip_stat() + // is called. The uid, gid, file mode, and file times may be + // inaccurate. The advantage is that a possibly costly seek and + // read can be avoided. + typedef struct zip_GPFileData { off_t compressedSize; off_t uncompressedSize; @@ -86,6 +94,7 @@ int zip_umount(struct uio_PRoot *); uio_Handle *zip_open(uio_PDirHandle *pDirHandle, const char *file, int flags, mode_t mode); void zip_close(uio_Handle *handle); +int zip_access(uio_PDirHandle *pDirHandle, const char *name, int mode); int zip_fstat(uio_Handle *handle, struct stat *statBuf); int zip_stat(uio_PDirHandle *pDirHandle, const char *name, struct stat *statBuf);