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:
@@ -1,7 +1,8 @@
|
|||||||
uqm_SUBDIRS="stdio"
|
uqm_SUBDIRS="stdio"
|
||||||
uqm_CFILES="charhashtable.c defaultfs.c fileblock.c fstypes.c
|
uqm_CFILES="charhashtable.c defaultfs.c fileblock.c fstypes.c
|
||||||
gphys.c hashtable.c io.c ioaux.c match.c mount.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
|
if [ -n "$uqm_USE_ZIP_IO" ]; then
|
||||||
uqm_SUBDIRS="$uqm_SUBDIRS zip"
|
uqm_SUBDIRS="$uqm_SUBDIRS zip"
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "uioport.h"
|
#include "uioport.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "uioutils.h"
|
#include "uioutils.h"
|
||||||
@@ -134,11 +135,11 @@ debugMountOne(uio_Repository *destRep, const char *mountPoint,
|
|||||||
mountHandle = uio_mountDir(destRep, mountPoint, fsType, sourceDir,
|
mountHandle = uio_mountDir(destRep, mountPoint, fsType, sourceDir,
|
||||||
sourcePath, inPath, autoMount, flags, relative);
|
sourcePath, inPath, autoMount, flags, relative);
|
||||||
if (mountHandle == NULL) {
|
if (mountHandle == NULL) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
fprintf(stderr, "Could not mount '%s' and graft '%s' from that "
|
fprintf(stderr, "Could not mount '%s' and graft '%s' from that "
|
||||||
"into the repository at '%s': %s\n",
|
"into the repository at '%s': %s\n",
|
||||||
sourcePath, inPath, mountPoint, strerror(errno));
|
sourcePath, inPath, mountPoint, strerror(errno));
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
}
|
}
|
||||||
return mountHandle;
|
return mountHandle;
|
||||||
}
|
}
|
||||||
@@ -213,9 +214,15 @@ initRepository(void) {
|
|||||||
uio_closeDir(rootDir);
|
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/",
|
mountHandles[8] = debugMountOne(repository, "/root/root/",
|
||||||
uio_FSTYPE_STDIO, NULL, NULL, "/", autoMount,
|
uio_FSTYPE_STDIO, NULL, NULL, "/", autoMount,
|
||||||
uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL);
|
uio_MOUNT_TOP | uio_MOUNT_RDONLY, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,40 +439,55 @@ debugCmdCd(DebugContext *debugContext, int argc, char *argv[]) {
|
|||||||
static int
|
static int
|
||||||
debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
|
debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
|
||||||
int i;
|
int i;
|
||||||
char **newArgs;
|
const char **newArgs;
|
||||||
int errCode = 0;
|
int errCode = 0;
|
||||||
|
uio_StdioAccessHandle **handles;
|
||||||
|
uio_DirHandle *tempDir;
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
fprintf(debugContext->err, "Invalid number of arguments.\n");
|
fprintf(debugContext->err, "Invalid number of arguments.\n");
|
||||||
return 1;
|
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 = uio_malloc(argc * sizeof (char *));
|
||||||
newArgs[0] = argv[1];
|
newArgs[0] = argv[1];
|
||||||
|
handles = uio_malloc(argc * sizeof (uio_StdioAccessHandle *));
|
||||||
|
handles[0] = NULL;
|
||||||
|
|
||||||
for (i = 2; i < argc; i++) {
|
for (i = 2; i < argc; i++) {
|
||||||
int retVal;
|
#if 0
|
||||||
uio_FileSystemID fsID;
|
if (argv[i][0] == '-') {
|
||||||
uio_MountHandle *mountHandle;
|
// Don't try to parse arguments that start with '-'.
|
||||||
|
// They are probably option flags.
|
||||||
retVal = uio_getFileLocation(debugContext->cwd, argv[i], O_RDONLY,
|
newArgs[i - 1] = argv[i];
|
||||||
&mountHandle, &newArgs[i - 1]);
|
}
|
||||||
if (retVal == -1) {
|
#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.
|
// No match; we keep what's typed litterally.
|
||||||
newArgs[i - 1] = argv[i];
|
newArgs[i - 1] = argv[i];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsID = uio_getMountFileSystemType(mountHandle);
|
// error
|
||||||
if (fsID != uio_FSTYPE_STDIO) {
|
|
||||||
// Wrong file system type.
|
|
||||||
fprintf(debugContext->err,
|
fprintf(debugContext->err,
|
||||||
"Cannot execute: %s is not in a stdio filesystem.\n",
|
"Cannot execute: Cannot get stdio access to %s: %s.\n",
|
||||||
argv[i]);
|
argv[i], strerror(errno));
|
||||||
errCode = 0;
|
errCode = 1;
|
||||||
argc = i + 1;
|
argc = i + 1;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newArgs[i - 1] = uio_StdioAccessHandle_getPath(handles[i - 1]);
|
||||||
}
|
}
|
||||||
newArgs[argc - 1] = NULL;
|
newArgs[argc - 1] = NULL;
|
||||||
|
|
||||||
@@ -486,7 +508,7 @@ debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
// child
|
// child
|
||||||
execvp(newArgs[0], newArgs);
|
execvp(newArgs[0], (char * const *) newArgs);
|
||||||
fprintf(debugContext->err, "Error: execvp() failed: %s.\n",
|
fprintf(debugContext->err, "Error: execvp() failed: %s.\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
@@ -528,11 +550,13 @@ debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
err:
|
err:
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc - 1; i++) {
|
||||||
if (argv[i] != newArgs[i - 1])
|
if (handles[i] != NULL)
|
||||||
uio_free(newArgs[i - 1]);
|
uio_releaseStdioAccess(handles[i]);
|
||||||
}
|
}
|
||||||
|
uio_free(handles);
|
||||||
uio_free(newArgs);
|
uio_free(newArgs);
|
||||||
|
uio_closeDir(tempDir);
|
||||||
|
|
||||||
return errCode;
|
return errCode;
|
||||||
}
|
}
|
||||||
@@ -822,11 +846,11 @@ debugCmdStat(DebugContext *debugContext, int argc, char *argv[]) {
|
|||||||
|
|
||||||
if (uio_stat(debugContext->cwd, argv[1], &statBuf) == -1) {
|
if (uio_stat(debugContext->cwd, argv[1], &statBuf) == -1) {
|
||||||
// errno is set
|
// errno is set
|
||||||
int saveErrno;
|
int savedErrno;
|
||||||
saveErrno = errno;
|
savedErrno = errno;
|
||||||
fprintf(debugContext->err, "Could not stat file: %s\n",
|
fprintf(debugContext->err, "Could not stat file: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
Needed before use in UQM:
|
Needed before use in UQM:
|
||||||
- documentation
|
- documentation
|
||||||
- configuring for HAVE_REGEX and GLOB
|
- 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:
|
Documentation:
|
||||||
- use doxygen
|
- use doxygen
|
||||||
@@ -35,6 +38,7 @@ Bugs:
|
|||||||
- uio_Stream file might get unaligned (not sure).
|
- uio_Stream file might get unaligned (not sure).
|
||||||
- 'openDir(repository, "dir/")' will have the trailing '/'
|
- 'openDir(repository, "dir/")' will have the trailing '/'
|
||||||
in the dirHandle, which will cause problems.
|
in the dirHandle, which will cause problems.
|
||||||
|
- 'openDirRelative(repository, "/")' causes segfaults lateron
|
||||||
- uio_rename() doesn't work on directories
|
- uio_rename() doesn't work on directories
|
||||||
uio_getPhysicalAccess() needs to be changed so that it works the same on
|
uio_getPhysicalAccess() needs to be changed so that it works the same on
|
||||||
dirs as on files. stat() can be cleaned up too then.
|
dirs as on files. stat() can be cleaned up too then.
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ static inline void uio_PDirHandle_free(uio_PDirHandle *pDirHandle);
|
|||||||
static inline uio_PFileHandle *uio_PFileHandle_alloc(void);
|
static inline uio_PFileHandle *uio_PFileHandle_alloc(void);
|
||||||
static inline void uio_PFileHandle_free(uio_PFileHandle *pFileHandle);
|
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);
|
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 void uio_DirHandle_free(uio_DirHandle *dirHandle);
|
||||||
|
|
||||||
static inline uio_Handle *uio_Handle_alloc(void);
|
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,
|
if (uio_getPhysicalAccess(newDir, newPath, O_WRONLY | O_CREAT | O_EXCL,
|
||||||
uio_GPA_NOWRITE, &newReadMountInfo, &newPReadDir, NULL,
|
uio_GPA_NOWRITE, &newReadMountInfo, &newPReadDir, NULL,
|
||||||
&newWriteMountInfo, &newPWriteDir, NULL, &newName) == -1) {
|
&newWriteMountInfo, &newPWriteDir, NULL, &newName) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_PDirHandle_unref(oldPReadDir);
|
uio_PDirHandle_unref(oldPReadDir);
|
||||||
uio_free(oldName);
|
uio_free(oldName);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,13 +393,13 @@ uio_rename(uio_DirHandle *oldDir, const char *oldPath,
|
|||||||
retVal = oldReadMountInfo->pDirHandle->pRoot->handler->rename(
|
retVal = oldReadMountInfo->pDirHandle->pRoot->handler->rename(
|
||||||
oldPReadDir, oldName, newPReadDir, newName);
|
oldPReadDir, oldName, newPReadDir, newName);
|
||||||
if (retVal == -1) {
|
if (retVal == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_PDirHandle_unref(oldPReadDir);
|
uio_PDirHandle_unref(oldPReadDir);
|
||||||
uio_PDirHandle_unref(newPReadDir);
|
uio_PDirHandle_unref(newPReadDir);
|
||||||
uio_PDirHandle_unref(newPWriteDir);
|
uio_PDirHandle_unref(newPWriteDir);
|
||||||
uio_free(oldName);
|
uio_free(oldName);
|
||||||
uio_free(newName);
|
uio_free(newName);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,9 +469,9 @@ uio_statDir(uio_DirHandle *dirHandle, const char *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uio_statOneDir(pDirHandles[0], statBuf) == -1) {
|
if (uio_statOneDir(pDirHandles[0], statBuf) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// TODO: atm, fstat'ing a dir will show the info for the topmost
|
// 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) {
|
if (statOneDir(pDirHandles[i], &statOne) == -1) {
|
||||||
// errno is set
|
// errno is set
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
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);
|
newDirHandle = pWriteDir->pRoot->handler->mkdir(pWriteDir, name, mode);
|
||||||
if (newDirHandle == NULL) {
|
if (newDirHandle == NULL) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(name);
|
uio_free(name);
|
||||||
uio_PDirHandle_unref(pWriteDir);
|
uio_PDirHandle_unref(pWriteDir);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,11 +597,11 @@ uio_open(uio_DirHandle *dir, const char *path, int flags, mode_t mode) {
|
|||||||
// file needs to be copied
|
// file needs to be copied
|
||||||
if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle,
|
if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle,
|
||||||
name) == -1) {
|
name) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(name);
|
uio_free(name);
|
||||||
uio_PDirHandle_unref(readPDirHandle);
|
uio_PDirHandle_unref(readPDirHandle);
|
||||||
uio_PDirHandle_unref(writePDirHandle);
|
uio_PDirHandle_unref(writePDirHandle);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return NULL;
|
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);
|
handle = pDirHandle->pRoot->handler->open(pDirHandle, name, flags, mode);
|
||||||
// Also adds a new entry to the physical dir if appropriate.
|
// Also adds a new entry to the physical dir if appropriate.
|
||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(name);
|
uio_free(name);
|
||||||
uio_PDirHandle_unref(pDirHandle);
|
uio_PDirHandle_unref(pDirHandle);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,14 +640,17 @@ uio_openDir(uio_Repository *repository, const char *path, int flags) {
|
|||||||
uio_DirHandle *dirHandle;
|
uio_DirHandle *dirHandle;
|
||||||
const char * const rootStr = "/";
|
const char * const rootStr = "/";
|
||||||
|
|
||||||
dirHandle = uio_newDirHandle(repository,
|
dirHandle = uio_DirHandle_new(repository,
|
||||||
unconst(rootStr), unconst(rootStr));
|
unconst(rootStr), unconst(rootStr));
|
||||||
|
// dirHandle->path will be replaced before uio_openDir()
|
||||||
|
// exits()
|
||||||
if (uio_verifyPath(dirHandle, path, &dirHandle->path) == -1) {
|
if (uio_verifyPath(dirHandle, path, &dirHandle->path) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_DirHandle_free(dirHandle);
|
uio_DirHandle_free(dirHandle);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// dirHandle->path is no longer equal to 'path' at this point.
|
||||||
// TODO: increase ref in repository?
|
// TODO: increase ref in repository?
|
||||||
dirHandle->rootEnd = dirHandle->path;
|
dirHandle->rootEnd = dirHandle->path;
|
||||||
if (flags & uio_OD_ROOT)
|
if (flags & uio_OD_ROOT)
|
||||||
@@ -665,12 +668,12 @@ uio_openDirRelative(uio_DirHandle *base, const char *path, int flags) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (flags & uio_OD_ROOT) {
|
if (flags & uio_OD_ROOT) {
|
||||||
dirHandle = uio_newDirHandle(base->repository,
|
dirHandle = uio_DirHandle_new(base->repository,
|
||||||
newPath, newPath + strlen(newPath));
|
newPath, newPath + strlen(newPath));
|
||||||
// TODO: increase ref in base->repository?
|
// TODO: increase ref in base->repository?
|
||||||
} else {
|
} else {
|
||||||
// use the root of the base dir
|
// use the root of the base dir
|
||||||
dirHandle = uio_newDirHandle(base->repository,
|
dirHandle = uio_DirHandle_new(base->repository,
|
||||||
newPath, newPath + (base->rootEnd - base->path));
|
newPath, newPath + (base->rootEnd - base->path));
|
||||||
}
|
}
|
||||||
return dirHandle;
|
return dirHandle;
|
||||||
@@ -678,8 +681,7 @@ uio_openDirRelative(uio_DirHandle *base, const char *path, int flags) {
|
|||||||
|
|
||||||
int
|
int
|
||||||
uio_closeDir(uio_DirHandle *dirHandle) {
|
uio_closeDir(uio_DirHandle *dirHandle) {
|
||||||
uio_free(dirHandle->path);
|
uio_DirHandle_unref(dirHandle);
|
||||||
uio_DirHandle_free(dirHandle);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,12 +767,12 @@ uio_rmdir(uio_DirHandle *dirHandle, const char *path) {
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
{
|
{
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
||||||
uio_free(items);
|
uio_free(items);
|
||||||
if (entry != NULL)
|
if (entry != NULL)
|
||||||
uio_PDirEntryHandle_unref(entry);
|
uio_PDirEntryHandle_unref(entry);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -875,12 +877,12 @@ uio_unlink(uio_DirHandle *dirHandle, const char *path) {
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
{
|
{
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
||||||
uio_free(items);
|
uio_free(items);
|
||||||
if (entry != NULL)
|
if (entry != NULL)
|
||||||
uio_PDirEntryHandle_unref(entry);
|
uio_PDirEntryHandle_unref(entry);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -945,13 +947,13 @@ uio_getFileLocation(uio_DirHandle *dir, const char *inPath,
|
|||||||
// file needs to be copied
|
// file needs to be copied
|
||||||
if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle,
|
if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle,
|
||||||
name) == -1) {
|
name) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(name);
|
uio_free(name);
|
||||||
uio_PDirHandle_unref(readPDirHandle);
|
uio_PDirHandle_unref(readPDirHandle);
|
||||||
uio_free(readPRootPath);
|
uio_free(readPRootPath);
|
||||||
uio_PDirHandle_unref(writePDirHandle);
|
uio_PDirHandle_unref(writePDirHandle);
|
||||||
uio_free(writePRootPath);
|
uio_free(writePRootPath);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1054,16 +1056,16 @@ uio_getDirList(uio_DirHandle *dirHandle, const char *path, const char *pattern,
|
|||||||
matchType);
|
matchType);
|
||||||
|
|
||||||
{
|
{
|
||||||
int saveErrno;
|
int savedErrno;
|
||||||
saveErrno = errno;
|
savedErrno = errno;
|
||||||
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
uio_PDirHandles_delete(pDirHandles, numPDirHandles);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names and newNames may point to the same location.
|
// 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
|
static void
|
||||||
uio_filterDoubleNames(const char * const *names, int numNames,
|
uio_filterDoubleNames(const char * const *names, int numNames,
|
||||||
const char **newNames, int *numNewNames) {
|
const char **newNames, int *numNewNames) {
|
||||||
@@ -1538,19 +1540,27 @@ uio_Handle_free(uio_Handle *handle) {
|
|||||||
uio_free(handle);
|
uio_free(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ref count set to 1
|
||||||
static uio_DirHandle *
|
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;
|
uio_DirHandle *result;
|
||||||
|
|
||||||
result = uio_allocDirHandle();
|
result = uio_DirHandle_alloc();
|
||||||
|
result->ref = 1;
|
||||||
result->repository = repository;
|
result->repository = repository;
|
||||||
result->path = path;
|
result->path = path;
|
||||||
result->rootEnd = rootEnd;
|
result->rootEnd = rootEnd;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uio_DirHandle_delete(uio_DirHandle *dirHandle) {
|
||||||
|
uio_free(dirHandle->path);
|
||||||
|
uio_DirHandle_free(dirHandle);
|
||||||
|
}
|
||||||
|
|
||||||
static inline uio_DirHandle *
|
static inline uio_DirHandle *
|
||||||
uio_allocDirHandle(void) {
|
uio_DirHandle_alloc(void) {
|
||||||
uio_DirHandle *result = uio_malloc(sizeof (uio_DirHandle));
|
uio_DirHandle *result = uio_malloc(sizeof (uio_DirHandle));
|
||||||
#ifdef uio_MEM_DEBUG
|
#ifdef uio_MEM_DEBUG
|
||||||
uio_MemDebug_debugAlloc(uio_DirHandle, (void *) result);
|
uio_MemDebug_debugAlloc(uio_DirHandle, (void *) result);
|
||||||
|
|||||||
@@ -124,9 +124,9 @@ uio_makePath(uio_PDirHandle *pDirHandle, const char *path, size_t pathLen,
|
|||||||
|
|
||||||
newPDirHandle = mkdirFun(pDirHandle, buf, mode);
|
newPDirHandle = mkdirFun(pDirHandle, buf, mode);
|
||||||
if (newPDirHandle == NULL) {
|
if (newPDirHandle == NULL) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_PDirHandle_unref(pDirHandle);
|
uio_PDirHandle_unref(pDirHandle);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
uio_PDirHandle_unref(pDirHandle);
|
uio_PDirHandle_unref(pDirHandle);
|
||||||
@@ -366,8 +366,8 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
|
|||||||
// component is present in this dir.
|
// component is present in this dir.
|
||||||
entry = uio_getPDirEntryHandle(pDirHandle, rest);
|
entry = uio_getPDirEntryHandle(pDirHandle, rest);
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
// Entry is not a dir, as otherwise uio_getPDirEntryHandle
|
// 'rest' exists, and it is not a dir, as otherwise
|
||||||
// wouldn't have stopped where it did.
|
// uio_getPDirEntryHandle wouldn't have stopped where it did.
|
||||||
uio_PDirEntryHandle_unref(entry);
|
uio_PDirEntryHandle_unref(entry);
|
||||||
readItem = item;
|
readItem = item;
|
||||||
if (readPDirHandle != NULL)
|
if (readPDirHandle != NULL)
|
||||||
@@ -378,7 +378,9 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
|
|||||||
entryExists = true;
|
entryExists = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
} 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.
|
// Keep the first one.
|
||||||
readItem = item;
|
readItem = item;
|
||||||
assert(readPDirHandle == NULL);
|
assert(readPDirHandle == NULL);
|
||||||
@@ -490,17 +492,17 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
|
|||||||
writePDirHandle = uio_makePath(writeItem->mountInfo->pDirHandle,
|
writePDirHandle = uio_makePath(writeItem->mountInfo->pDirHandle,
|
||||||
pRootPath, rest - pRootPath, 0777);
|
pRootPath, rest - pRootPath, 0777);
|
||||||
if (writePDirHandle == NULL) {
|
if (writePDirHandle == NULL) {
|
||||||
int saveErrno;
|
int savedErrno;
|
||||||
if (errno == ENOSYS) {
|
if (errno == ENOSYS) {
|
||||||
// mkdir not supported. We want to report that we failed
|
// mkdir not supported. We want to report that we failed
|
||||||
// because of an error in the underlying layer.
|
// because of an error in the underlying layer.
|
||||||
// EIO sounds like the best choice.
|
// EIO sounds like the best choice.
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
}
|
}
|
||||||
saveErrno = errno;
|
savedErrno = errno;
|
||||||
uio_PDirHandle_unref(readPDirHandle);
|
uio_PDirHandle_unref(readPDirHandle);
|
||||||
uio_free(fullPath);
|
uio_free(fullPath);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rest++; // skip the '/'
|
rest++; // skip the '/'
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ struct uio_Handle {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct uio_DirHandle {
|
struct uio_DirHandle {
|
||||||
|
int ref;
|
||||||
struct uio_Repository *repository;
|
struct uio_Repository *repository;
|
||||||
char *path;
|
char *path;
|
||||||
// does not contain any '.' or '..'
|
// does not contain any '.' or '..'
|
||||||
@@ -102,6 +103,7 @@ struct uio_EntriesContext {
|
|||||||
uio_Handle *uio_Handle_new(uio_PRoot *root, uio_NativeHandle native,
|
uio_Handle *uio_Handle_new(uio_PRoot *root, uio_NativeHandle native,
|
||||||
int openFlags);
|
int openFlags);
|
||||||
void uio_Handle_delete(uio_Handle *handle);
|
void uio_Handle_delete(uio_Handle *handle);
|
||||||
|
void uio_DirHandle_delete(uio_DirHandle *dirHandle);
|
||||||
|
|
||||||
uio_PDirEntryHandle *uio_getPDirEntryHandle(
|
uio_PDirEntryHandle *uio_getPDirEntryHandle(
|
||||||
const uio_PDirHandle *dirHandle, const char *name);
|
const uio_PDirHandle *dirHandle, const char *name);
|
||||||
@@ -130,6 +132,19 @@ uio_Handle_unref(uio_Handle *handle) {
|
|||||||
uio_Handle_delete(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
|
static inline uio_bool
|
||||||
uio_PDirEntryHandle_isDir(const uio_PDirEntryHandle *handle) {
|
uio_PDirEntryHandle_isDir(const uio_PDirEntryHandle *handle) {
|
||||||
return (handle->flags & uio_PDirEntryHandle_TYPEMASK) ==
|
return (handle->flags & uio_PDirEntryHandle_TYPEMASK) ==
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ joinPathsAbsolute(const char *first, const char *second) {
|
|||||||
result = uio_malloc(secondLen + 2);
|
result = uio_malloc(secondLen + 2);
|
||||||
result[0] = '/';
|
result[0] = '/';
|
||||||
memcpy(&result[1], second, secondLen);
|
memcpy(&result[1], second, secondLen);
|
||||||
|
result[secondLen + 1] = '\0';
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,12 +63,57 @@ uio_PRoot_new(uio_PDirHandle *topDirHandle,
|
|||||||
pRoot->handle = handle;
|
pRoot->handle = handle;
|
||||||
pRoot->extra = extra;
|
pRoot->extra = extra;
|
||||||
pRoot->flags = flags;
|
pRoot->flags = flags;
|
||||||
|
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
|
||||||
|
pRoot->numCloseHandlers = 0;
|
||||||
|
pRoot->closeHandlers = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
return pRoot;
|
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
|
static inline void
|
||||||
uio_PRoot_delete(uio_PRoot *pRoot) {
|
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);
|
assert(pRoot->handler->umount != NULL);
|
||||||
pRoot->handler->umount(pRoot);
|
pRoot->handler->umount(pRoot);
|
||||||
if (pRoot->handle)
|
if (pRoot->handle)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ typedef void *uio_NativeEntriesContext;
|
|||||||
|
|
||||||
// 'forward' declarations
|
// 'forward' declarations
|
||||||
typedef struct uio_PRoot uio_PRoot;
|
typedef struct uio_PRoot uio_PRoot;
|
||||||
|
typedef struct uio_PRoot_CloseHandler uio_PRoot_CloseHandler;
|
||||||
|
|
||||||
|
|
||||||
#include "iointrn.h"
|
#include "iointrn.h"
|
||||||
@@ -55,14 +56,31 @@ struct uio_PRoot {
|
|||||||
/* The handle through which this PRoot is opened,
|
/* The handle through which this PRoot is opened,
|
||||||
* this is NULL for the top PRoot */
|
* this is NULL for the top PRoot */
|
||||||
// TODO: move this to extra?
|
// TODO: move this to extra?
|
||||||
|
#ifdef uio_PROOT_HAVE_CLOSE_HANDLERS
|
||||||
|
int numCloseHandlers;
|
||||||
|
uio_PRoot_CloseHandler *closeHandlers;
|
||||||
|
#endif
|
||||||
uio_PRootExtra extra;
|
uio_PRootExtra extra;
|
||||||
/* extra internal data for some filesystem types */
|
/* 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);
|
void uio_PRoot_deletePRootExtra(uio_PRoot *pRoot);
|
||||||
uio_PRoot *uio_PRoot_new(uio_PDirHandle *topDirHandle,
|
uio_PRoot *uio_PRoot_new(uio_PDirHandle *topDirHandle,
|
||||||
uio_FileSystemHandler *handler, uio_Handle *handle,
|
uio_FileSystemHandler *handler, uio_Handle *handle,
|
||||||
uio_PRootExtra extra, int flags);
|
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);
|
uio_PDirHandle *uio_PRoot_getRootDirHandle(uio_PRoot *pRoot);
|
||||||
void uio_PRoot_refHandle(uio_PRoot *pRoot);
|
void uio_PRoot_refHandle(uio_PRoot *pRoot);
|
||||||
void uio_PRoot_unrefHandle(uio_PRoot *pRoot);
|
void uio_PRoot_unrefHandle(uio_PRoot *pRoot);
|
||||||
|
|||||||
@@ -137,9 +137,9 @@ stdio_stat(uio_PDirHandle *pDirHandle, const char *name,
|
|||||||
|
|
||||||
result = stat(path, statBuf);
|
result = stat(path, statBuf);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(path);
|
uio_free(path);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,9 +159,9 @@ stdio_mkdir(uio_PDirHandle *pDirHandle, const char *name, mode_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (MKDIR(path, mode) == -1) {
|
if (MKDIR(path, mode) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(path);
|
uio_free(path);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
uio_free(path);
|
uio_free(path);
|
||||||
@@ -244,10 +244,10 @@ stdio_rename(uio_PDirHandle *oldPDirHandle, const char *oldName,
|
|||||||
|
|
||||||
result = rename(oldPath, newPath);
|
result = rename(oldPath, newPath);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(oldPath);
|
uio_free(oldPath);
|
||||||
uio_free(newPath);
|
uio_free(newPath);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,9 +283,9 @@ stdio_rmdir(uio_PDirHandle *pDirHandle, const char *name) {
|
|||||||
|
|
||||||
result = rmdir(path);
|
result = rmdir(path);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(path);
|
uio_free(path);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,9 +319,9 @@ stdio_unlink(uio_PDirHandle *pDirHandle, const char *name) {
|
|||||||
|
|
||||||
result = unlink(path);
|
result = unlink(path);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_free(path);
|
uio_free(path);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _UTILS_H
|
#ifndef _UIOUTILS_H
|
||||||
#define _UTILS_H
|
#define _UIOUTILS_H
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@@ -88,5 +88,5 @@ minu(unsigned int i1, unsigned int i2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif /* _UIOUTILS_H */
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 */
|
||||||
|
|
||||||
@@ -580,13 +580,13 @@ zip_mount(uio_Handle *handle, int flags) {
|
|||||||
|
|
||||||
rootDirHandle = uio_PRoot_getRootDirHandle(result);
|
rootDirHandle = uio_PRoot_getRootDirHandle(result);
|
||||||
if (zip_fillDirStructure(rootDirHandle->extra, handle) == -1) {
|
if (zip_fillDirStructure(rootDirHandle->extra, handle) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "Error: failed to read the zip directory "
|
fprintf(stderr, "Error: failed to read the zip directory "
|
||||||
"structure - %d.\n", errno);
|
"structure - %d.\n", errno);
|
||||||
#endif
|
#endif
|
||||||
uio_GPRoot_umount(result);
|
uio_GPRoot_umount(result);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,11 +662,11 @@ zip_fillDirStructureCentral(uio_GPDir *top, uio_Handle *handle) {
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
{
|
{
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
|
|
||||||
if (fileBlock != NULL)
|
if (fileBlock != NULL)
|
||||||
uio_closeFileBlock(fileBlock);
|
uio_closeFileBlock(fileBlock);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -845,10 +845,10 @@ zip_findEndOfCentralDirectoryRecord(uio_Handle *handle,
|
|||||||
bufLen = uio_accessFileBlock(fileBlock, startPos, endPos - startPos + 4,
|
bufLen = uio_accessFileBlock(fileBlock, startPos, endPos - startPos + 4,
|
||||||
&buf);
|
&buf);
|
||||||
if (bufLen == -1) {
|
if (bufLen == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
fprintf(stderr, "Error: Read error while searching for "
|
fprintf(stderr, "Error: Read error while searching for "
|
||||||
"'end-of-central-directory record'.\n");
|
"'end-of-central-directory record'.\n");
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (bufLen != endPos - startPos + 4) {
|
if (bufLen != endPos - startPos + 4) {
|
||||||
@@ -973,8 +973,8 @@ zip_fillDirStructureLocal(uio_GPDir *top, uio_Handle *handle) {
|
|||||||
|
|
||||||
pos = uio_lseek(handle, 0, SEEK_SET);
|
pos = uio_lseek(handle, 0, SEEK_SET);
|
||||||
if (pos == -1) {
|
if (pos == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (pos != 0) {
|
if (pos != 0) {
|
||||||
@@ -1015,10 +1015,10 @@ zip_fillDirStructureLocal(uio_GPDir *top, uio_Handle *handle) {
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
{
|
{
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
|
|
||||||
uio_closeFileBlock(fileBlock);
|
uio_closeFileBlock(fileBlock);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1209,9 +1209,9 @@ zip_updateFileDataFromLocalHeader(uio_Handle *handle,
|
|||||||
}
|
}
|
||||||
if (zip_updatePFileDataFromLocalFileHeader(gPFileData,
|
if (zip_updatePFileDataFromLocalFileHeader(gPFileData,
|
||||||
fileBlock, gPFileData->headerOffset) == -1) {
|
fileBlock, gPFileData->headerOffset) == -1) {
|
||||||
int saveErrno = errno;
|
int savedErrno = errno;
|
||||||
uio_closeFileBlock(fileBlock);
|
uio_closeFileBlock(fileBlock);
|
||||||
errno = saveErrno;
|
errno = savedErrno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (gPFileData->ctime == (time_t) 0)
|
if (gPFileData->ctime == (time_t) 0)
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|
||||||
Reference in New Issue
Block a user