Support for stdio file access through temporary files.

Added relevant functions:
uio_StdioAccessHandle *uio_getStdioAccess(uio_DirHandle *dir,
        const char *path, int flags, uio_DirHandle *tempDir);
const char *uio_StdioAccessHandle_getPath(uio_StdioAccessHandle *handle);
void uio_releaseStdioAccess(uio_StdioAccessHandle *handle);
These are made available by including "uioutils.h" in addition to "uio.h".

An other function that's available through uioutils is
int uio_copyFile(uio_DirHandle *srcDir, const char *srcName,
        uio_DirHandle *dstDir, const char *newName);


git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1288 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
meep-eep
2003-11-02 00:55:18 +00:00
parent 07fb0bd04e
commit 6065182283
15 changed files with 648 additions and 96 deletions
+2 -1
View File
@@ -1,7 +1,8 @@
uqm_SUBDIRS="stdio"
uqm_CFILES="charhashtable.c defaultfs.c fileblock.c fstypes.c
gphys.c hashtable.c io.c ioaux.c match.c mount.c
mounttree.c paths.c physical.c uiostream.c uioutils.c"
mounttree.c paths.c physical.c uiostream.c uioutils.c
utils.c"
if [ -n "$uqm_USE_ZIP_IO" ]; then
uqm_SUBDIRS="$uqm_SUBDIRS zip"
+50 -26
View File
@@ -32,6 +32,7 @@
#include "debug.h"
#include "uioport.h"
#include "io.h"
#include "utils.h"
#include "types.h"
#include "mem.h"
#include "uioutils.h"
@@ -134,11 +135,11 @@ debugMountOne(uio_Repository *destRep, const char *mountPoint,
mountHandle = uio_mountDir(destRep, mountPoint, fsType, sourceDir,
sourcePath, inPath, autoMount, flags, relative);
if (mountHandle == NULL) {
int saveErrno = errno;
int savedErrno = errno;
fprintf(stderr, "Could not mount '%s' and graft '%s' from that "
"into the repository at '%s': %s\n",
sourcePath, inPath, mountPoint, strerror(errno));
errno = saveErrno;
errno = savedErrno;
}
return mountHandle;
}
@@ -213,9 +214,15 @@ initRepository(void) {
uio_closeDir(rootDir);
}
}
mountHandles[8] = debugMountOne(repository, "/tmp/",
uio_FSTYPE_STDIO, NULL, NULL, "/tmp/", autoMount,
uio_MOUNT_TOP, NULL);
#if 1
mountHandles[8] = debugMountOne(repository, "/root/root/",
uio_FSTYPE_STDIO, NULL, NULL, "/", autoMount,
uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL);
#endif
}
@@ -432,40 +439,55 @@ debugCmdCd(DebugContext *debugContext, int argc, char *argv[]) {
static int
debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
int i;
char **newArgs;
const char **newArgs;
int errCode = 0;
uio_StdioAccessHandle **handles;
uio_DirHandle *tempDir;
if (argc < 2) {
fprintf(debugContext->err, "Invalid number of arguments.\n");
return 1;
}
tempDir = uio_openDirRelative(debugContext->cwd, "/tmp", 0);
if (tempDir == 0) {
fprintf(debugContext->err, "Could not open temp dir: %s.\n",
strerror(errno));
return 1;
}
newArgs = uio_malloc(argc * sizeof (char *));
newArgs[0] = argv[1];
handles = uio_malloc(argc * sizeof (uio_StdioAccessHandle *));
handles[0] = NULL;
for (i = 2; i < argc; i++) {
int retVal;
uio_FileSystemID fsID;
uio_MountHandle *mountHandle;
retVal = uio_getFileLocation(debugContext->cwd, argv[i], O_RDONLY,
&mountHandle, &newArgs[i - 1]);
if (retVal == -1) {
// No match; we keep what's typed litterally.
#if 0
if (argv[i][0] == '-') {
// Don't try to parse arguments that start with '-'.
// They are probably option flags.
newArgs[i - 1] = argv[i];
continue;
}
fsID = uio_getMountFileSystemType(mountHandle);
if (fsID != uio_FSTYPE_STDIO) {
// Wrong file system type.
#endif
handles[i - 1] = uio_getStdioAccess(debugContext->cwd, argv[i],
O_RDONLY, tempDir);
if (handles[i - 1] == NULL) {
if (errno == ENOENT) {
// No match; we keep what's typed litterally.
newArgs[i - 1] = argv[i];
continue;
}
// error
fprintf(debugContext->err,
"Cannot execute: %s is not in a stdio filesystem.\n",
argv[i]);
errCode = 0;
"Cannot execute: Cannot get stdio access to %s: %s.\n",
argv[i], strerror(errno));
errCode = 1;
argc = i + 1;
goto err;
}
newArgs[i - 1] = uio_StdioAccessHandle_getPath(handles[i - 1]);
}
newArgs[argc - 1] = NULL;
@@ -486,7 +508,7 @@ debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
break;
case 0:
// child
execvp(newArgs[0], newArgs);
execvp(newArgs[0], (char * const *) newArgs);
fprintf(debugContext->err, "Error: execvp() failed: %s.\n",
strerror(errno));
_exit(EXIT_FAILURE);
@@ -528,11 +550,13 @@ debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
#endif
err:
for (i = 1; i < argc; i++) {
if (argv[i] != newArgs[i - 1])
uio_free(newArgs[i - 1]);
for (i = 1; i < argc - 1; i++) {
if (handles[i] != NULL)
uio_releaseStdioAccess(handles[i]);
}
uio_free(handles);
uio_free(newArgs);
uio_closeDir(tempDir);
return errCode;
}
@@ -822,11 +846,11 @@ debugCmdStat(DebugContext *debugContext, int argc, char *argv[]) {
if (uio_stat(debugContext->cwd, argv[1], &statBuf) == -1) {
// errno is set
int saveErrno;
saveErrno = errno;
int savedErrno;
savedErrno = errno;
fprintf(debugContext->err, "Could not stat file: %s\n",
strerror(errno));
errno = saveErrno;
errno = savedErrno;
return 1;
}
+4
View File
@@ -1,6 +1,9 @@
Needed before use in UQM:
- documentation
- configuring for HAVE_REGEX and GLOB
- when doing uio_getStdioPhysical(), if write access is required, but
not available on the original location, also copy the file to the
temporary dir.
Documentation:
- use doxygen
@@ -35,6 +38,7 @@ Bugs:
- uio_Stream file might get unaligned (not sure).
- 'openDir(repository, "dir/")' will have the trailing '/'
in the dirHandle, which will cause problems.
- 'openDirRelative(repository, "/")' causes segfaults lateron
- uio_rename() doesn't work on directories
uio_getPhysicalAccess() needs to be changed so that it works the same on
dirs as on files. stat() can be cleaned up too then.
+46 -36
View File
@@ -51,9 +51,9 @@ static inline void uio_PDirHandle_free(uio_PDirHandle *pDirHandle);
static inline uio_PFileHandle *uio_PFileHandle_alloc(void);
static inline void uio_PFileHandle_free(uio_PFileHandle *pFileHandle);
static uio_DirHandle *uio_newDirHandle(uio_Repository *repository, char *path,
static uio_DirHandle *uio_DirHandle_new(uio_Repository *repository, char *path,
char *rootEnd);
static inline uio_DirHandle *uio_allocDirHandle(void);
static inline uio_DirHandle *uio_DirHandle_alloc(void);
static inline void uio_DirHandle_free(uio_DirHandle *dirHandle);
static inline uio_Handle *uio_Handle_alloc(void);
@@ -354,10 +354,10 @@ uio_rename(uio_DirHandle *oldDir, const char *oldPath,
if (uio_getPhysicalAccess(newDir, newPath, O_WRONLY | O_CREAT | O_EXCL,
uio_GPA_NOWRITE, &newReadMountInfo, &newPReadDir, NULL,
&newWriteMountInfo, &newPWriteDir, NULL, &newName) == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_PDirHandle_unref(oldPReadDir);
uio_free(oldName);
errno = saveErrno;
errno = savedErrno;
return -1;
}
@@ -393,13 +393,13 @@ uio_rename(uio_DirHandle *oldDir, const char *oldPath,
retVal = oldReadMountInfo->pDirHandle->pRoot->handler->rename(
oldPReadDir, oldName, newPReadDir, newName);
if (retVal == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_PDirHandle_unref(oldPReadDir);
uio_PDirHandle_unref(newPReadDir);
uio_PDirHandle_unref(newPWriteDir);
uio_free(oldName);
uio_free(newName);
errno = saveErrno;
errno = savedErrno;
return -1;
}
@@ -469,9 +469,9 @@ uio_statDir(uio_DirHandle *dirHandle, const char *path,
}
if (uio_statOneDir(pDirHandles[0], statBuf) == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
errno = saveErrno;
errno = savedErrno;
return -1;
}
// TODO: atm, fstat'ing a dir will show the info for the topmost
@@ -484,9 +484,9 @@ uio_statDir(uio_DirHandle *dirHandle, const char *path,
if (statOneDir(pDirHandles[i], &statOne) == -1) {
// errno is set
int saveErrno = errno;
int savedErrno = errno;
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
errno = saveErrno;
errno = savedErrno;
return -1;
}
@@ -536,10 +536,10 @@ uio_mkdir(uio_DirHandle *dir, const char *path, mode_t mode) {
newDirHandle = pWriteDir->pRoot->handler->mkdir(pWriteDir, name, mode);
if (newDirHandle == NULL) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(name);
uio_PDirHandle_unref(pWriteDir);
errno = saveErrno;
errno = savedErrno;
return -1;
}
@@ -597,11 +597,11 @@ uio_open(uio_DirHandle *dir, const char *path, int flags, mode_t mode) {
// file needs to be copied
if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle,
name) == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(name);
uio_PDirHandle_unref(readPDirHandle);
uio_PDirHandle_unref(writePDirHandle);
errno = saveErrno;
errno = savedErrno;
return NULL;
}
}
@@ -623,10 +623,10 @@ uio_open(uio_DirHandle *dir, const char *path, int flags, mode_t mode) {
handle = pDirHandle->pRoot->handler->open(pDirHandle, name, flags, mode);
// Also adds a new entry to the physical dir if appropriate.
if (handle == NULL) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(name);
uio_PDirHandle_unref(pDirHandle);
errno = saveErrno;
errno = savedErrno;
return NULL;
}
@@ -640,14 +640,17 @@ uio_openDir(uio_Repository *repository, const char *path, int flags) {
uio_DirHandle *dirHandle;
const char * const rootStr = "/";
dirHandle = uio_newDirHandle(repository,
dirHandle = uio_DirHandle_new(repository,
unconst(rootStr), unconst(rootStr));
// dirHandle->path will be replaced before uio_openDir()
// exits()
if (uio_verifyPath(dirHandle, path, &dirHandle->path) == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_DirHandle_free(dirHandle);
errno = saveErrno;
errno = savedErrno;
return NULL;
}
// dirHandle->path is no longer equal to 'path' at this point.
// TODO: increase ref in repository?
dirHandle->rootEnd = dirHandle->path;
if (flags & uio_OD_ROOT)
@@ -665,12 +668,12 @@ uio_openDirRelative(uio_DirHandle *base, const char *path, int flags) {
return NULL;
}
if (flags & uio_OD_ROOT) {
dirHandle = uio_newDirHandle(base->repository,
dirHandle = uio_DirHandle_new(base->repository,
newPath, newPath + strlen(newPath));
// TODO: increase ref in base->repository?
} else {
// use the root of the base dir
dirHandle = uio_newDirHandle(base->repository,
dirHandle = uio_DirHandle_new(base->repository,
newPath, newPath + (base->rootEnd - base->path));
}
return dirHandle;
@@ -678,8 +681,7 @@ uio_openDirRelative(uio_DirHandle *base, const char *path, int flags) {
int
uio_closeDir(uio_DirHandle *dirHandle) {
uio_free(dirHandle->path);
uio_DirHandle_free(dirHandle);
uio_DirHandle_unref(dirHandle);
return 0;
}
@@ -765,12 +767,12 @@ uio_rmdir(uio_DirHandle *dirHandle, const char *path) {
err:
{
int saveErrno = errno;
int savedErrno = errno;
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
uio_free(items);
if (entry != NULL)
uio_PDirEntryHandle_unref(entry);
errno = saveErrno;
errno = savedErrno;
return -1;
}
}
@@ -875,12 +877,12 @@ uio_unlink(uio_DirHandle *dirHandle, const char *path) {
err:
{
int saveErrno = errno;
int savedErrno = errno;
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
uio_free(items);
if (entry != NULL)
uio_PDirEntryHandle_unref(entry);
errno = saveErrno;
errno = savedErrno;
return -1;
}
}
@@ -945,13 +947,13 @@ uio_getFileLocation(uio_DirHandle *dir, const char *inPath,
// file needs to be copied
if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle,
name) == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(name);
uio_PDirHandle_unref(readPDirHandle);
uio_free(readPRootPath);
uio_PDirHandle_unref(writePDirHandle);
uio_free(writePRootPath);
errno = saveErrno;
errno = savedErrno;
return -1;
}
}
@@ -1054,16 +1056,16 @@ uio_getDirList(uio_DirHandle *dirHandle, const char *path, const char *pattern,
matchType);
{
int saveErrno;
saveErrno = errno;
int savedErrno;
savedErrno = errno;
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
errno = saveErrno;
errno = savedErrno;
}
return result;
}
// Names and newNames may point to the same location.
// &numNames and numNewNames may point to the same location.
// numNewNames may point to &numNames.
static void
uio_filterDoubleNames(const char * const *names, int numNames,
const char **newNames, int *numNewNames) {
@@ -1538,19 +1540,27 @@ uio_Handle_free(uio_Handle *handle) {
uio_free(handle);
}
// ref count set to 1
static uio_DirHandle *
uio_newDirHandle(uio_Repository *repository, char *path, char *rootEnd) {
uio_DirHandle_new(uio_Repository *repository, char *path, char *rootEnd) {
uio_DirHandle *result;
result = uio_allocDirHandle();
result = uio_DirHandle_alloc();
result->ref = 1;
result->repository = repository;
result->path = path;
result->rootEnd = rootEnd;
return result;
}
void
uio_DirHandle_delete(uio_DirHandle *dirHandle) {
uio_free(dirHandle->path);
uio_DirHandle_free(dirHandle);
}
static inline uio_DirHandle *
uio_allocDirHandle(void) {
uio_DirHandle_alloc(void) {
uio_DirHandle *result = uio_malloc(sizeof (uio_DirHandle));
#ifdef uio_MEM_DEBUG
uio_MemDebug_debugAlloc(uio_DirHandle, (void *) result);
+10 -8
View File
@@ -124,9 +124,9 @@ uio_makePath(uio_PDirHandle *pDirHandle, const char *path, size_t pathLen,
newPDirHandle = mkdirFun(pDirHandle, buf, mode);
if (newPDirHandle == NULL) {
int saveErrno = errno;
int savedErrno = errno;
uio_PDirHandle_unref(pDirHandle);
errno = saveErrno;
errno = savedErrno;
return NULL;
}
uio_PDirHandle_unref(pDirHandle);
@@ -366,8 +366,8 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
// component is present in this dir.
entry = uio_getPDirEntryHandle(pDirHandle, rest);
if (entry != NULL) {
// Entry is not a dir, as otherwise uio_getPDirEntryHandle
// wouldn't have stopped where it did.
// 'rest' exists, and it is not a dir, as otherwise
// uio_getPDirEntryHandle wouldn't have stopped where it did.
uio_PDirEntryHandle_unref(entry);
readItem = item;
if (readPDirHandle != NULL)
@@ -378,7 +378,9 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
entryExists = true;
break;
} else {
if (readItem == NULL) {
// 'rest' doesn't exist
// We're only interested in this dir if we want to write too.
if (((flags & O_ACCMODE) != O_RDONLY) && readItem == NULL) {
// Keep the first one.
readItem = item;
assert(readPDirHandle == NULL);
@@ -490,17 +492,17 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
writePDirHandle = uio_makePath(writeItem->mountInfo->pDirHandle,
pRootPath, rest - pRootPath, 0777);
if (writePDirHandle == NULL) {
int saveErrno;
int savedErrno;
if (errno == ENOSYS) {
// mkdir not supported. We want to report that we failed
// because of an error in the underlying layer.
// EIO sounds like the best choice.
errno = EIO;
}
saveErrno = errno;
savedErrno = errno;
uio_PDirHandle_unref(readPDirHandle);
uio_free(fullPath);
errno = saveErrno;
errno = savedErrno;
return -1;
}
rest++; // skip the '/'
+15
View File
@@ -50,6 +50,7 @@ struct uio_Handle {
};
struct uio_DirHandle {
int ref;
struct uio_Repository *repository;
char *path;
// does not contain any '.' or '..'
@@ -102,6 +103,7 @@ struct uio_EntriesContext {
uio_Handle *uio_Handle_new(uio_PRoot *root, uio_NativeHandle native,
int openFlags);
void uio_Handle_delete(uio_Handle *handle);
void uio_DirHandle_delete(uio_DirHandle *dirHandle);
uio_PDirEntryHandle *uio_getPDirEntryHandle(
const uio_PDirHandle *dirHandle, const char *name);
@@ -130,6 +132,19 @@ uio_Handle_unref(uio_Handle *handle) {
uio_Handle_delete(handle);
}
static inline void
uio_DirHandle_ref(uio_DirHandle *dirHandle) {
dirHandle->ref++;
}
static inline void
uio_DirHandle_unref(uio_DirHandle *dirHandle) {
assert(dirHandle->ref > 0);
dirHandle->ref--;
if (dirHandle->ref == 0)
uio_DirHandle_delete(dirHandle);
}
static inline uio_bool
uio_PDirEntryHandle_isDir(const uio_PDirEntryHandle *handle) {
return (handle->flags & uio_PDirEntryHandle_TYPEMASK) ==
+1
View File
@@ -188,6 +188,7 @@ joinPathsAbsolute(const char *first, const char *second) {
result = uio_malloc(secondLen + 2);
result[0] = '/';
memcpy(&result[1], second, secondLen);
result[secondLen + 1] = '\0';
return result;
}
+45
View File
@@ -63,12 +63,57 @@ uio_PRoot_new(uio_PDirHandle *topDirHandle,
pRoot->handle = handle;
pRoot->extra = extra;
pRoot->flags = flags;
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
pRoot->numCloseHandlers = 0;
pRoot->closeHandlers = NULL;
#endif
return pRoot;
}
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
// Closehandlers code disabled.
// It was only meant for internal use, but I don't need it any more.
// Keeping it around for a while until I'm confident I won't need it in the
// future.
void
uio_PRoot_addCloseHandler(uio_PRoot *pRoot, void (*fun)(void *), void *arg) {
pRoot->numCloseHandlers++;
pRoot->closeHandlers = uio_realloc(pRoot->closeHandlers,
pRoot->numCloseHandlers * sizeof (uio_PRoot_CloseHandler));
pRoot->closeHandlers[pRoot->numCloseHandlers - 1].fun = fun;
pRoot->closeHandlers[pRoot->numCloseHandlers - 1].arg = arg;
}
void
uio_PRoot_callCloseHandlers(uio_PRoot *pRoot) {
int i;
i = pRoot->numCloseHandlers;
while (i--) {
uio_PRoot_CloseHandler *closeHandler;
closeHandler = &pRoot->closeHandlers[i];
(closeHandler->fun)(closeHandler->arg);
}
}
void
uio_PRoot_removeCloseHandlers(uio_PRoot *pRoot) {
pRoot->numCloseHandlers = 0;
if (pRoot->closeHandlers != NULL)
uio_free(pRoot->closeHandlers);
pRoot->closeHandlers = NULL;
}
#endif
static inline void
uio_PRoot_delete(uio_PRoot *pRoot) {
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
uio_PRoot_callCloseHandlers(pRoot);
uio_PRoot_removeCloseHandlers(pRoot);
#endif
assert(pRoot->handler->umount != NULL);
pRoot->handler->umount(pRoot);
if (pRoot->handle)
+18
View File
@@ -28,6 +28,7 @@ typedef void *uio_NativeEntriesContext;
// 'forward' declarations
typedef struct uio_PRoot uio_PRoot;
typedef struct uio_PRoot_CloseHandler uio_PRoot_CloseHandler;
#include "iointrn.h"
@@ -55,14 +56,31 @@ struct uio_PRoot {
/* The handle through which this PRoot is opened,
* this is NULL for the top PRoot */
// TODO: move this to extra?
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
int numCloseHandlers;
uio_PRoot_CloseHandler *closeHandlers;
#endif
uio_PRootExtra extra;
/* extra internal data for some filesystem types */
};
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
struct uio_PRoot_CloseHandler {
void (*fun)(void *);
void *arg;
};
#endif
void uio_PRoot_deletePRootExtra(uio_PRoot *pRoot);
uio_PRoot *uio_PRoot_new(uio_PDirHandle *topDirHandle,
uio_FileSystemHandler *handler, uio_Handle *handle,
uio_PRootExtra extra, int flags);
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
void uio_PRoot_addCloseHandler(uio_PRoot *pRoot, void (*fun)(void *),
void *arg);
void uio_PRoot_callCloseHandlers(uio_PRoot *pRoot);
void uio_PRoot_removeCloseHandlers(uio_PRoot *pRoot);
#endif
uio_PDirHandle *uio_PRoot_getRootDirHandle(uio_PRoot *pRoot);
void uio_PRoot_refHandle(uio_PRoot *pRoot);
void uio_PRoot_unrefHandle(uio_PRoot *pRoot);
+10 -10
View File
@@ -137,9 +137,9 @@ stdio_stat(uio_PDirHandle *pDirHandle, const char *name,
result = stat(path, statBuf);
if (result == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(path);
errno = saveErrno;
errno = savedErrno;
return -1;
}
@@ -159,9 +159,9 @@ stdio_mkdir(uio_PDirHandle *pDirHandle, const char *name, mode_t mode) {
}
if (MKDIR(path, mode) == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(path);
errno = saveErrno;
errno = savedErrno;
return NULL;
}
uio_free(path);
@@ -244,10 +244,10 @@ stdio_rename(uio_PDirHandle *oldPDirHandle, const char *oldName,
result = rename(oldPath, newPath);
if (result == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(oldPath);
uio_free(newPath);
errno = saveErrno;
errno = savedErrno;
return -1;
}
@@ -283,9 +283,9 @@ stdio_rmdir(uio_PDirHandle *pDirHandle, const char *name) {
result = rmdir(path);
if (result == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(path);
errno = saveErrno;
errno = savedErrno;
return -1;
}
@@ -319,9 +319,9 @@ stdio_unlink(uio_PDirHandle *pDirHandle, const char *name) {
result = unlink(path);
if (result == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_free(path);
errno = saveErrno;
errno = savedErrno;
return -1;
}
+3 -3
View File
@@ -18,8 +18,8 @@
*
*/
#ifndef _UTILS_H
#define _UTILS_H
#ifndef _UIOUTILS_H
#define _UIOUTILS_H
#include <time.h>
@@ -88,5 +88,5 @@ minu(unsigned int i1, unsigned int i2) {
}
#endif
#endif /* _UIOUTILS_H */
+366
View File
@@ -0,0 +1,366 @@
/*
* Copyright (C) 2003 Serge van den Boom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
* Nota bene: later versions of the GNU General Public License do not apply
* to this program.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <errno.h>
#include <time.h>
#include <stdio.h>
#include "iointrn.h"
#include "ioaux.h"
#include "utils.h"
static int uio_copyError(uio_Handle *srcHandle, uio_Handle *dstHandle,
uio_DirHandle *unlinkHandle, const char *unlinkPath, uio_uint8 *buf);
struct uio_StdioAccessHandle {
uio_DirHandle *tempRoot;
char *tempDirName;
uio_DirHandle *tempDir;
char *fileName;
char *stdioPath;
};
static inline uio_StdioAccessHandle *uio_StdioAccessHandle_new(
uio_DirHandle *tempRoot, char *tempDirName,
uio_DirHandle *tempDir, char *fileName,
char *stdioPath);
static inline void uio_StdioAccessHandle_delete(
uio_StdioAccessHandle *handle);
static inline uio_StdioAccessHandle *uio_StdioAccessHandle_alloc(void);
static inline void uio_StdioAccessHandle_free(uio_StdioAccessHandle *handle);
/*
* Copy a file with path srcName to a file with name newName.
* If the destination already exists, the operation fails.
* Links are followed.
* Special files (fifos, char devices, block devices, etc) will be
* read as long as there is data available and the destination will be
* a regular file with that data.
* The new file will have the same permissions as the old.
* If an error occurs during copying, an attempt will be made to
* remove the copy.
*/
int
uio_copyFile(uio_DirHandle *srcDir, const char *srcName,
uio_DirHandle *dstDir, const char *newName) {
uio_Handle *src, *dst;
struct stat sb;
#define BUFSIZE 65536
uio_uint8 *buf, *bufPtr;
ssize_t numInBuf, numWritten;
src = uio_open(srcDir, srcName, O_RDONLY
#ifdef WIN32
| O_BINARY
#endif
, 0);
if (src == NULL)
return -1;
if (uio_fstat(src, &sb) == -1)
return uio_copyError(src, NULL, NULL, NULL, NULL);
dst = uio_open(dstDir, newName, O_WRONLY | O_CREAT | O_EXCL
#ifdef WIN32
| O_BINARY
#endif
, sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
if (dst == NULL)
return uio_copyError(src, NULL, NULL, NULL, NULL);
buf = uio_malloc(BUFSIZE);
// This was originally a statically allocated buffer,
// but as this function might be run from a thread with
// a small Stack, this is better.
while (1) {
numInBuf = uio_read(src, buf, BUFSIZE);
if (numInBuf == -1) {
if (errno == EINTR)
continue;
return uio_copyError(src, dst, dstDir, newName, buf);
}
if (numInBuf == 0)
break;
bufPtr = buf;
do
{
numWritten = uio_write(dst, bufPtr, numInBuf);
if (numWritten == -1) {
if (errno == EINTR)
continue;
return uio_copyError(src, dst, dstDir, newName, buf);
}
numInBuf -= numWritten;
bufPtr += numWritten;
} while (numInBuf > 0);
}
uio_free(buf);
uio_close(src);
uio_close(dst);
errno = 0;
return 0;
}
/*
* Closes srcHandle if it's not -1.
* Closes dstHandle if it's not -1.
* Removes unlinkpath from the unlinkHandle dir if it's not NULL.
* Frees 'buf' if not NULL.
* Always returns -1.
* errno is what was before the call.
*/
static int
uio_copyError(uio_Handle *srcHandle, uio_Handle *dstHandle,
uio_DirHandle *unlinkHandle, const char *unlinkPath, uio_uint8 *buf) {
int savedErrno;
savedErrno = errno;
#ifdef DEBUG
fprintf(stderr, "Error while copying: %s\n", strerror(errno));
#endif
if (srcHandle != NULL)
uio_close(srcHandle);
if (dstHandle != NULL)
uio_close(dstHandle);
if (unlinkPath != NULL)
uio_unlink(unlinkHandle, unlinkPath);
if (buf != NULL)
uio_free(buf);
errno = savedErrno;
return -1;
}
#define NUM_TEMP_RETRIES 16
// Retry this many times to create a temporary dir, before giving
// up. If undefined, keep trying indefinately.
uio_StdioAccessHandle *
uio_getStdioAccess(uio_DirHandle *dir, const char *path, int flags,
uio_DirHandle *tempDir) {
int res;
uio_MountHandle *mountHandle;
const char *name;
char *newPath;
char *tempDirName;
uio_DirHandle *newDir;
uio_FileSystemID fsID;
res = uio_getFileLocation(dir, path, flags, &mountHandle, &newPath);
if (res == -1) {
// errno is set
return NULL;
}
fsID = uio_getMountFileSystemType(mountHandle);
if (fsID == uio_FSTYPE_STDIO) {
// Current location is usable.
return uio_StdioAccessHandle_new(NULL, NULL, NULL, NULL, newPath);
}
uio_free(newPath);
{
uio_uint32 dirNum;
int i;
// Current location is not usable. Create a directory with a
// generated name, as a temporary location to store a copy of
// the file.
dirNum = (uio_uint32) time(NULL);
tempDirName = uio_malloc(sizeof "01234567");
for (i = 0; ; i++) {
#ifdef NUM_TEMP_RETRIES
if (i >= NUM_TEMP_RETRIES) {
// Using ENOSPC to report that we couldn't create a
// temporary dir, getting EEXIST.
uio_free(tempDirName);
errno = ENOSPC;
return NULL;
}
#endif
sprintf(tempDirName, "%08lx", (unsigned long) dirNum + i);
res = uio_mkdir(tempDir, tempDirName, 0700);
if (res == -1) {
int savedErrno;
if (errno == EEXIST)
continue;
savedErrno = errno;
#ifdef DEBUG
fprintf(stderr, "Error: Could not create temporary dir: %s\n",
strerror(errno));
#endif
uio_free(tempDirName);
errno = savedErrno;
return NULL;
}
break;
}
newDir = uio_openDirRelative(tempDir, tempDirName, 0);
if (newDir == NULL) {
#ifdef DEBUG
fprintf(stderr, "Error: Could not open temporary dir: %s\n",
strerror(errno));
#endif
res = uio_rmdir(tempDir, tempDirName);
#ifdef DEBUG
if (res == -1)
fprintf(stderr, "Warning: Could not remove temporary dir: "
"%s.\n", strerror(errno));
#endif
uio_free(tempDirName);
errno = EIO;
return NULL;
}
// Get the last component of path. This should be the file to
// access.
name = strrchr(path, '/');
if (name == NULL)
name = path;
// Copy the file
res = uio_copyFile(dir, path, newDir, name);
if (res == -1) {
int savedErrno = errno;
#ifdef DEBUG
fprintf(stderr, "Error: Could not copy file to temporary dir: "
"%s\n", strerror(errno));
#endif
uio_closeDir(newDir);
uio_free(tempDirName);
errno = savedErrno;
return NULL;
}
}
res = uio_getFileLocation(newDir, name, flags, &mountHandle, &newPath);
if (res == -1) {
int savedErrno = errno;
fprintf(stderr, "Error: %s: Could not get location of temporary "
"dir: %s.\n", __FUNCTION__, strerror(errno));
uio_closeDir(newDir);
uio_free(tempDirName);
errno = savedErrno;
return NULL;
}
fsID = uio_getMountFileSystemType(mountHandle);
if (fsID != uio_FSTYPE_STDIO) {
// Temp dir isn't on a stdio fs either.
fprintf(stderr, "Error: %s: Temporary file location isn't on a "
"stdio filesystem.\n", __FUNCTION__);
uio_closeDir(newDir);
uio_free(tempDirName);
uio_free(newPath);
// errno = EXDEV;
errno = EINVAL;
return NULL;
}
uio_DirHandle_ref(tempDir);
return uio_StdioAccessHandle_new(tempDir, tempDirName, newDir,
uio_strdup(name), newPath);
}
void
uio_releaseStdioAccess(uio_StdioAccessHandle *handle) {
if (handle->tempDir != NULL) {
if (uio_unlink(handle->tempDir, handle->fileName) == -1) {
#ifdef DEBUG
fprintf(stderr, "Error: Could not remove temporary file: "
"%s\n", strerror(errno));
#endif
}
// Need to free this handle in advance. There should be no handles
// to a dir left when removing it.
uio_DirHandle_unref(handle->tempDir);
handle->tempDir = NULL;
if (uio_rmdir(handle->tempRoot, handle->tempDirName) == -1) {
#ifdef DEBUG
fprintf(stderr, "Error: Could not remove temporary directory: "
"%s\n", strerror(errno));
#endif
}
}
uio_StdioAccessHandle_delete(handle);
}
const char *
uio_StdioAccessHandle_getPath(uio_StdioAccessHandle *handle) {
return (const char *) handle->stdioPath;
}
// references to tempRoot and tempDir are not increased.
// no copies of arguments are made.
// By calling this function control of the values is transfered to
// the handle.
static inline uio_StdioAccessHandle *
uio_StdioAccessHandle_new(
uio_DirHandle *tempRoot, char *tempDirName,
uio_DirHandle *tempDir, char *fileName, char *stdioPath) {
uio_StdioAccessHandle *result;
result = uio_StdioAccessHandle_alloc();
result->tempRoot = tempRoot;
result->tempDirName = tempDirName;
result->tempDir = tempDir;
result->fileName = fileName;
result->stdioPath = stdioPath;
return result;
}
static inline void
uio_StdioAccessHandle_delete(uio_StdioAccessHandle *handle) {
if (handle->tempDir != NULL)
uio_DirHandle_unref(handle->tempDir);
if (handle->fileName != NULL)
uio_free(handle->fileName);
if (handle->tempRoot != NULL)
uio_DirHandle_unref(handle->tempRoot);
if (handle->tempDirName != NULL)
uio_free(handle->tempDirName);
uio_free(handle->stdioPath);
uio_StdioAccessHandle_free(handle);
}
static inline uio_StdioAccessHandle *
uio_StdioAccessHandle_alloc(void) {
return uio_malloc(sizeof (uio_StdioAccessHandle));
}
static inline void
uio_StdioAccessHandle_free(uio_StdioAccessHandle *handle) {
uio_free(handle);
}
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2003 Serge van den Boom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
* Nota bene: later versions of the GNU General Public License do not apply
* to this program.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _UTILS_H
#define _UTILS_H
#ifdef uio_INTERNAL
typedef struct uio_StdioAccessHandle uio_StdioAccessHandle;
#else
typedef void uio_StdioAccessHandle;
#endif
int uio_copyFile(uio_DirHandle *srcDir, const char *srcName,
uio_DirHandle *dstDir, const char *newName);
uio_StdioAccessHandle *uio_getStdioAccess(uio_DirHandle *dir,
const char *path, int flags, uio_DirHandle *tempDir);
const char *uio_StdioAccessHandle_getPath(uio_StdioAccessHandle *handle);
void uio_releaseStdioAccess(uio_StdioAccessHandle *handle);
#endif /* _UTILS_H */
+12 -12
View File
@@ -580,13 +580,13 @@ zip_mount(uio_Handle *handle, int flags) {
rootDirHandle = uio_PRoot_getRootDirHandle(result);
if (zip_fillDirStructure(rootDirHandle->extra, handle) == -1) {
int saveErrno = errno;
int savedErrno = errno;
#ifdef DEBUG
fprintf(stderr, "Error: failed to read the zip directory "
"structure - %d.\n", errno);
#endif
uio_GPRoot_umount(result);
errno = saveErrno;
errno = savedErrno;
return NULL;
}
@@ -662,11 +662,11 @@ zip_fillDirStructureCentral(uio_GPDir *top, uio_Handle *handle) {
err:
{
int saveErrno = errno;
int savedErrno = errno;
if (fileBlock != NULL)
uio_closeFileBlock(fileBlock);
errno = saveErrno;
errno = savedErrno;
return -1;
}
}
@@ -845,10 +845,10 @@ zip_findEndOfCentralDirectoryRecord(uio_Handle *handle,
bufLen = uio_accessFileBlock(fileBlock, startPos, endPos - startPos + 4,
&buf);
if (bufLen == -1) {
int saveErrno = errno;
int savedErrno = errno;
fprintf(stderr, "Error: Read error while searching for "
"'end-of-central-directory record'.\n");
errno = saveErrno;
errno = savedErrno;
return -1;
}
if (bufLen != endPos - startPos + 4) {
@@ -973,8 +973,8 @@ zip_fillDirStructureLocal(uio_GPDir *top, uio_Handle *handle) {
pos = uio_lseek(handle, 0, SEEK_SET);
if (pos == -1) {
int saveErrno = errno;
errno = saveErrno;
int savedErrno = errno;
errno = savedErrno;
return -1;
}
if (pos != 0) {
@@ -1015,10 +1015,10 @@ zip_fillDirStructureLocal(uio_GPDir *top, uio_Handle *handle) {
err:
{
int saveErrno = errno;
int savedErrno = errno;
uio_closeFileBlock(fileBlock);
errno = saveErrno;
errno = savedErrno;
return -1;
}
}
@@ -1209,9 +1209,9 @@ zip_updateFileDataFromLocalHeader(uio_Handle *handle,
}
if (zip_updatePFileDataFromLocalFileHeader(gPFileData,
fileBlock, gPFileData->headerOffset) == -1) {
int saveErrno = errno;
int savedErrno = errno;
uio_closeFileBlock(fileBlock);
errno = saveErrno;
errno = savedErrno;
return -1;
}
if (gPFileData->ctime == (time_t) 0)
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2003 Serge van den Boom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
* Nota bene: later versions of the GNU General Public License do not apply
* to this program.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _UIOUTILS_H
#define _UIOUTILS_H
#include "uio/utils.h"
#endif /* _UIOUTILS_H */