Added uio_getPhysicalAccess(), uio_getMountFileSystemType() and

some small improvements.


git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1283 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
meep-eep
2003-10-24 02:36:27 +00:00
parent c8ba5aed50
commit b45a4e4ffd
9 changed files with 351 additions and 29 deletions
+117 -4
View File
@@ -25,6 +25,9 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#ifdef __unix__
# include <sys/wait.h>
#endif
#include "debug.h"
#include "uioport.h"
@@ -58,6 +61,7 @@ void unInitRepository(void);
static int debugCmdCat(DebugContext *debugContext, int argc, char *argv[]);
static int debugCmdCd(DebugContext *debugContext, int argc, char *argv[]);
static int debugCmdExec(DebugContext *debugContext, int argc, char *argv[]);
static int debugCmdExit(DebugContext *debugContext, int argc, char *argv[]);
static int debugCmdLs(DebugContext *debugContext, int argc, char *argv[]);
static int debugCmdMem(DebugContext *debugContext, int argc, char *argv[]);
@@ -87,6 +91,7 @@ debugMountOne(uio_Repository *destRep, const char *mountPoint,
DebugCommand debugCommands[] = {
{ "cat", debugCmdCat },
{ "cd", debugCmdCd },
{ "exec", debugCmdExec },
{ "exit", debugCmdExit },
{ "fwritetest", debugCmdFwriteTest },
{ "ls", debugCmdLs },
@@ -294,12 +299,12 @@ makeArgs(char *lineBuf, int *argc, char ***argv) {
numArg = 0;
ptr = lineBuf;
while(1) {
while (isspace(*ptr))
while (isspace((int) *ptr))
ptr++;
if (*ptr == '\0')
break;
numArg++;
while (!isspace(*ptr))
while (!isspace((int) *ptr))
ptr++;
}
@@ -307,13 +312,13 @@ makeArgs(char *lineBuf, int *argc, char ***argv) {
numArg = 0;
ptr = lineBuf;
while(1) {
while (isspace(*ptr))
while (isspace((int) *ptr))
ptr++;
if (*ptr == '\0')
break;
args[numArg] = ptr;
numArg++;
while (!isspace(*ptr))
while (!isspace((int) *ptr))
ptr++;
if (*ptr == '\0')
break;
@@ -424,6 +429,114 @@ debugCmdCd(DebugContext *debugContext, int argc, char *argv[]) {
return 0;
}
static int
debugCmdExec(DebugContext *debugContext, int argc, char *argv[]) {
int i;
char **newArgs;
int errCode = 0;
if (argc < 2) {
fprintf(debugContext->err, "Invalid number of arguments.\n");
return 1;
}
newArgs = uio_malloc(argc * sizeof (char *));
newArgs[0] = argv[1];
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.
newArgs[i - 1] = argv[i];
continue;
}
fsID = uio_getMountFileSystemType(mountHandle);
if (fsID != uio_FSTYPE_STDIO) {
// Wrong file system type.
fprintf(debugContext->err,
"Cannot execute: %s is not in a stdio filesystem.\n",
argv[i]);
errCode = 0;
argc = i + 1;
goto err;
}
}
newArgs[argc - 1] = NULL;
fprintf(debugContext->err, "Executing: %s", newArgs[0]);
for (i = 1; i < argc - 1; i++)
fprintf(debugContext->err, " %s", newArgs[i]);
fprintf(debugContext->err, "\n");
#ifdef __unix__
{
pid_t pid;
pid = fork();
switch (pid) {
case -1:
fprintf(debugContext->err, "Error: fork() failed: %s.\n",
strerror(errno));
break;
case 0:
// child
execvp(newArgs[0], newArgs);
fprintf(debugContext->err, "Error: execvp() failed: %s.\n",
strerror(errno));
_exit(EXIT_FAILURE);
break;
default: {
// parent
int status;
pid_t retVal;
while (1) {
retVal = waitpid(pid, &status, 0);
if (retVal != -1)
break;
if (errno != EINTR) {
fprintf(debugContext->err, "Error: waitpid() "
"failed: %s\n", strerror(errno));
break;
}
}
if (retVal == -1)
break;
if (WIFEXITED(status)) {
fprintf(debugContext->err, "Exit status: %d\n",
WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
fprintf(debugContext->err, "Terminated on signal %d.\n",
WTERMSIG(status));
} else {
fprintf(debugContext->err, "Error: weird exit status.\n");
}
break;
}
}
}
#else
fprintf(debugContext->err, "Cannot execute: not supported on this "
"platform.\n");
#endif
err:
for (i = 1; i < argc; i++) {
if (argv[i] != newArgs[i - 1])
uio_free(newArgs[i - 1]);
}
uio_free(newArgs);
return errCode;
}
static int
debugCmdExit(DebugContext *debugContext, int argc, char *argv[]) {
debugContext->exit = true;
+5 -1
View File
@@ -36,8 +36,12 @@ Bugs:
- 'openDir(repository, "dir/")' will have the trailing '/'
in the dirHandle, which will cause problems.
- 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.
- uio_getPhysicalAccess() will not return ENOENT when (only) the last
component does not exist, even when O_RDONLY is used.
For O_RDRW, O_CREAT should probably be checked too (function description
needs to be updated too then).
Extra features (not necessary for UQM):
- Make functions to use for uio_malloc, uio_free and uio_realloc
+113 -10
View File
@@ -325,6 +325,11 @@ uio_unmountAllDirs(uio_Repository *repository) {
return 0;
}
uio_FileSystemID
uio_getMountFileSystemType(uio_MountHandle *mountHandle) {
return mountHandle->mountInfo->fsID;
}
int
uio_close(uio_Handle *handle) {
uio_Handle_unref(handle);
@@ -340,15 +345,15 @@ uio_rename(uio_DirHandle *oldDir, const char *oldPath,
int retVal;
if (uio_getPhysicalAccess(oldDir, oldPath, O_RDONLY, 0,
&oldReadMountInfo, &oldPReadDir,
NULL, NULL, &oldName) == -1) {
&oldReadMountInfo, &oldPReadDir, NULL,
NULL, NULL, NULL, &oldName) == -1) {
// errno is set
return -1;
}
if (uio_getPhysicalAccess(newDir, newPath, O_WRONLY | O_CREAT | O_EXCL,
uio_GPA_NOWRITE, &newReadMountInfo, &newPReadDir,
&newWriteMountInfo, &newPWriteDir, &newName) == -1) {
uio_GPA_NOWRITE, &newReadMountInfo, &newPReadDir, NULL,
&newWriteMountInfo, &newPWriteDir, NULL, &newName) == -1) {
int saveErrno = errno;
uio_PDirHandle_unref(oldPReadDir);
uio_free(oldName);
@@ -423,8 +428,8 @@ uio_stat(uio_DirHandle *dir, const char *path, struct stat *statBuf) {
int result;
if (uio_getPhysicalAccess(dir, path, O_RDONLY, 0,
&readMountInfo, &pReadDir,
NULL, NULL, &name) == -1) {
&readMountInfo, &pReadDir, NULL,
NULL, NULL, NULL, &name) == -1) {
if (uio_statDir(dir, path, statBuf) == -1) {
// errno is set
return -1;
@@ -513,8 +518,8 @@ uio_mkdir(uio_DirHandle *dir, const char *path, mode_t mode) {
uio_PDirHandle *newDirHandle;
if (uio_getPhysicalAccess(dir, path, O_WRONLY | O_CREAT | O_EXCL, 0,
&readMountInfo, &pReadDir,
&writeMountInfo, &pWriteDir, &name) == -1) {
&readMountInfo, &pReadDir, NULL,
&writeMountInfo, &pWriteDir, NULL, &name) == -1) {
// errno is set
if (errno == EISDIR)
errno = EEXIST;
@@ -552,8 +557,8 @@ uio_open(uio_DirHandle *dir, const char *path, int flags, mode_t mode) {
uio_Handle *handle;
if (uio_getPhysicalAccess(dir, path, flags, 0,
&readMountInfo, &readPDirHandle,
&writeMountInfo, &writePDirHandle, &name) == -1) {
&readMountInfo, &readPDirHandle, NULL,
&writeMountInfo, &writePDirHandle, NULL, &name) == -1) {
// errno is set
return NULL;
}
@@ -880,6 +885,104 @@ err:
}
}
// inPath and *outPath may point to the same location
int
uio_getFileLocation(uio_DirHandle *dir, const char *inPath,
int flags, uio_MountHandle **mountHandle, char **outPath) {
uio_PDirHandle *readPDirHandle, *writePDirHandle;
uio_MountInfo *readMountInfo, *writeMountInfo, *mountInfo;
char *name;
char *readPRootPath, *writePRootPath, *pRootPath;
if (uio_getPhysicalAccess(dir, inPath, flags, 0,
&readMountInfo, &readPDirHandle, &readPRootPath,
&writeMountInfo, &writePDirHandle, &writePRootPath,
&name) == -1) {
// errno is set
return -1;
}
// TODO: This code is partly the same as the code in uio_open().
// probably some code could be put in a seperate function.
if ((flags & O_ACCMODE) == O_RDONLY) {
// WritePDirHandle is not filled in.
uio_PDirHandle_unref(readPDirHandle);
pRootPath = readPRootPath;
mountInfo = readMountInfo;
} else if (readPDirHandle == writePDirHandle) {
// In general, the dirs can be the same even when the handles are
// not the same. But here it works, because uio_getPhysicalAccess
// guarantees it.
uio_PDirHandle_unref(readPDirHandle);
uio_PDirHandle_unref(writePDirHandle);
pRootPath = readPRootPath;
mountInfo = readMountInfo;
uio_free(writePRootPath);
} else {
// need to write
uio_PDirEntryHandle *entry;
entry = uio_getPDirEntryHandle(readPDirHandle, name);
if (entry != NULL) {
// file already exists
uio_PDirEntryHandle_unref(entry);
if ((flags & O_CREAT) == O_CREAT &&
(flags & O_EXCL) == O_EXCL) {
uio_free(name);
uio_PDirHandle_unref(readPDirHandle);
uio_free(readPRootPath);
uio_PDirHandle_unref(writePDirHandle);
uio_free(writePRootPath);
errno = EEXIST;
return -1;
}
if ((flags & O_TRUNC) == O_TRUNC) {
// No use copying the file to the writable dir.
// As it doesn't exists there, O_TRUNC needs to be turned off
// though.
flags &= ~O_TRUNC;
} else {
// file needs to be copied
if (uio_copyFilePhysical(readPDirHandle, name, writePDirHandle,
name) == -1) {
int saveErrno = errno;
uio_free(name);
uio_PDirHandle_unref(readPDirHandle);
uio_free(readPRootPath);
uio_PDirHandle_unref(writePDirHandle);
uio_free(writePRootPath);
errno = saveErrno;
return -1;
}
}
} else {
// file does not exist
if (((flags & O_ACCMODE) == O_RDONLY) ||
(flags & O_CREAT) != O_CREAT) {
uio_free(name);
uio_PDirHandle_unref(readPDirHandle);
uio_free(readPRootPath);
uio_PDirHandle_unref(writePDirHandle);
uio_free(writePRootPath);
errno = ENOENT;
return -1;
}
}
uio_PDirHandle_unref(readPDirHandle);
uio_PDirHandle_unref(writePDirHandle);
pRootPath = writePRootPath;
mountInfo = writeMountInfo;
uio_free(readPRootPath);
}
uio_free(name);
*mountHandle = mountInfo->mountHandle;
*outPath = pRootPath;
return 0;
}
// *** begin dirList stuff *** //
#define uio_DIR_BUFFER_SIZE 2048
+6
View File
@@ -87,6 +87,9 @@ int uio_unmountDir(uio_MountHandle *mountHandle);
// Unmount all previously mounted dirs.
int uio_unmountAllDirs(uio_Repository *repository);
// Get the filesystem identifier for a mounted directory.
uio_FileSystemID uio_getMountFileSystemType(uio_MountHandle *mountHandle);
// Open a file
uio_Handle *uio_open(uio_DirHandle *dir, const char *file, int flags,
mode_t mode);
@@ -115,6 +118,9 @@ ssize_t uio_write(uio_Handle *handle, const void *buf, size_t count);
int uio_unlink(uio_DirHandle *dirHandle, const char *path);
int uio_getFileLocation(uio_DirHandle *dir, const char *inPath,
int flags, uio_MountHandle **mountHandle, char **outPath);
// Get a directory handle.
uio_DirHandle *uio_openDir(uio_Repository *repository, const char *path,
int flags);
+46 -10
View File
@@ -260,26 +260,38 @@ copyError(int error,
* extraFlags - either 0 or uio_GPA_NOWRITE
* When 0, the path will be created if it doesn't
* exist in the writing location, but does exist
* in the reading location. With uio_GPA_NOWRITE, it
* won't be created, and -1 will be returned and errno
* will be set to ENOENT.
* in the reading location. With uio_GPA_NOWRITE, it
* won't be created, and -1 will be returned and errno
* will be set to ENOENT.
* mountInfoReadPtr - pointer to location where the pointer
* to the MountInfo structure for the reading location
* should be stored.
* readPDirHandlePtr - pointer to the location where the pointer
* to the PDirHandle used for reading should be stored.
* readPRootPath - pointer to the location where the pointer
* to the physical path to the reading location
* is to be stored.
* The caller is responsible for freeing this.
* Ignored if NULL.
* mountInfoWritePtr - pointer to location where the pointer
* to the MountInfo structure for the writing location
* should be stored.
* writePDirHandlePtr - pointer to the location where the pointer
* to the PDirHandle used for writing should be stored.
* NULL if O_RDONLY was specified.
* If this is the same dir as the one refered
* to by readPDirHandlePtr, the handles will be the
* same too.
* restPtr - pointer to a newly created string with as contents
* the last component of 'path'.
* If this is the same dir as the one refered
* to by readPDirHandlePtr, the handles will be the
* same too.
* writePRootPath - pointer to the location where the pointer
* to the physical path to the writing location
* is to be stored.
* The caller is responsible for freeing this.
* Ignored if NULL.
* restPtr - pointer to the location where a newly created
* string with as contents the last component of 'path'
* is to be stored.
* The caller is responsible for freeing this.
* Ignored if NULL.
* Returns: 0 - success
* -1 - failure (errno set)
* NB: This is the function that would most benefit from
@@ -291,10 +303,13 @@ int
uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
int flags, int extraFlags,
uio_MountInfo **mountInfoReadPtr, uio_PDirHandle **readPDirHandlePtr,
char **readPRootPathPtr,
uio_MountInfo **mountInfoWritePtr, uio_PDirHandle **writePDirHandlePtr,
char **writePRootPathPtr,
char **restPtr) {
char *fullPath; // path from dirHandle with 'path' added
const char *pRootPath; // path from the pRoot of a physical tree
const char *readPRootPath, *writePRootPath;
const char *rest, *readRest;
uio_MountTree *tree;
uio_MountTreeItem *item;
@@ -317,8 +332,10 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
readItem = NULL;
readPDirHandle = NULL;
readPRootPath = NULL;
writeItem = NULL;
writePDirHandle = NULL;
writePRootPath = NULL;
readRest = NULL;
// Satisfy compiler.
entryExists = false;
@@ -356,6 +373,7 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
if (readPDirHandle != NULL)
uio_PDirHandle_unref(readPDirHandle);
readPDirHandle = pDirHandle;
readPRootPath = pRootPath;
readRest = rest;
entryExists = true;
break;
@@ -365,6 +383,7 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
readItem = item;
assert(readPDirHandle == NULL);
readPDirHandle = pDirHandle;
readPRootPath = pRootPath;
readRest = rest;
continue;
}
@@ -399,6 +418,9 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
// write access is not needed
*mountInfoReadPtr = readItem->mountInfo;
*readPDirHandlePtr = readPDirHandle;
if (readPRootPathPtr != NULL)
*readPRootPathPtr = joinPathsAbsolute(
readItem->mountInfo->dirName, readPRootPath);
// Don't touch mountInfoWritePtr and writePDirHandlePtr.
// they'd be NULL.
*restPtr = uio_strdup(readRest);
@@ -419,13 +441,20 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
// The read directory is usable as write directory too.
*mountInfoReadPtr = readItem->mountInfo;
*readPDirHandlePtr = readPDirHandle;
if (readPRootPathPtr != NULL)
*readPRootPathPtr = joinPathsAbsolute(
readItem->mountInfo->dirName, readPRootPath);
*mountInfoWritePtr = writeItem->mountInfo;
// writeItem == readItem
uio_PDirHandle_ref(readPDirHandle);
*writePDirHandlePtr = readPDirHandle;
// No copy&paste error, the read PDirHandle is the write
// pDirHandle too.
*restPtr = uio_strdup(readRest);
if (writePRootPathPtr != NULL)
*writePRootPathPtr = joinPathsAbsolute(
writeItem->mountInfo->dirName, writePRootPath);
if (restPtr != NULL)
*restPtr = uio_strdup(readRest);
uio_free(fullPath);
return 0;
}
@@ -490,9 +519,16 @@ uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
*mountInfoReadPtr = readItem->mountInfo;
*readPDirHandlePtr = readPDirHandle;
if (readPRootPathPtr != NULL)
*readPRootPathPtr = joinPathsAbsolute(
readItem->mountInfo->dirName, readPRootPath);
*mountInfoReadPtr = writeItem->mountInfo;
*writePDirHandlePtr = writePDirHandle;
*restPtr = uio_strdup(rest);
if (writePRootPathPtr != NULL)
*writePRootPathPtr = joinPathsAbsolute(
writeItem->mountInfo->dirName, writePRootPath);
if (restPtr != NULL)
*restPtr = uio_strdup(rest);
uio_free(fullPath);
return 0;
}
+6 -3
View File
@@ -33,9 +33,12 @@ uio_PDirHandle *uio_makePath(uio_PDirHandle *pDirHandle, const char *path,
int uio_copyFilePhysical(uio_PDirHandle *fromDir, const char *fromName,
uio_PDirHandle *toDir, const char *toName);
int uio_getPhysicalAccess(uio_DirHandle *dirHandle, const char *path,
int flags, int extraFlags, uio_MountInfo **mountInfoReadPtr,
uio_PDirHandle **readPDirHandlePtr, uio_MountInfo **mountInfoWritePtr,
uio_PDirHandle **writePDirHandlePtr, char **restPtr);
int flags, int extraFlags,
uio_MountInfo **mountInfoReadPtr, uio_PDirHandle **readPDirHandlePtr,
char **readPRootPathPtr,
uio_MountInfo **mountInfoWritePtr, uio_PDirHandle **writePDirHandlePtr,
char **writePRootPathPtr,
char **restPtr);
#define uio_GPA_NOWRITE 1
int uio_getPathPhysicalDirs(uio_DirHandle *dirHandle, const char *path,
size_t pathLen, uio_PDirHandle ***resPDirHandles,
+47
View File
@@ -142,11 +142,18 @@ getPreviousPathComponent(const char *dir,
(*startComp)--;
}
// Combine two parts of a paths into a new path.
// The new path starts with a '/' only when the first part does.
// The first path may (but doesn't have to) end on a '/', or may be empty.
// Pre: the second path doesn't start with a '/'
char *
joinPaths(const char *first, const char *second) {
char *result, *resPtr;
size_t firstLen, secondLen;
if (first[0] == '\0')
return uio_strdup(second);
firstLen = strlen(first);
if (first[firstLen - 1] == '/')
firstLen--;
@@ -167,6 +174,46 @@ joinPaths(const char *first, const char *second) {
return result;
}
// Combine two parts of a paths into a new path,
// The new path will always start with a '/'.
// The first path may (but doesn't have to) end on a '/', or may be empty.
// Pre: the second path doesn't start with a '/'
char *
joinPathsAbsolute(const char *first, const char *second) {
char *result, *resPtr;
size_t firstLen, secondLen;
if (first[0] == '\0') {
secondLen = strlen(second);
result = uio_malloc(secondLen + 2);
result[0] = '/';
memcpy(&result[1], second, secondLen);
return result;
}
firstLen = strlen(first);
if (first[firstLen - 1] == '/')
firstLen--;
secondLen = strlen(second);
result = uio_malloc(firstLen + secondLen + 3);
resPtr = result;
*resPtr = '/';
resPtr++;
memcpy(resPtr, first, firstLen);
resPtr += firstLen;
*resPtr = '/';
resPtr++;
memcpy(resPtr, second, secondLen);
resPtr += secondLen;
*resPtr = '\0';
return result;
}
uio_bool
validPathName(const char *path, size_t len) {
const char *pathEnd;
+1
View File
@@ -39,6 +39,7 @@ void getPreviousPathComponent(const char *dir, const char **startComp,
const char **endComp);
#define getPreviousPath0Component getPreviousPathComponent
char *joinPaths(const char *first, const char *second);
char *joinPathsAbsolute(const char *first, const char *second);
uio_bool validPathName(const char *path, size_t len);
+10 -1
View File
@@ -579,7 +579,16 @@ zip_mount(uio_Handle *handle, int flags) {
handle, NULL, uio_GPDir_COMPLETE);
rootDirHandle = uio_PRoot_getRootDirHandle(result);
zip_fillDirStructure(rootDirHandle->extra, handle);
if (zip_fillDirStructure(rootDirHandle->extra, handle) == -1) {
int saveErrno = errno;
#ifdef DEBUG
fprintf(stderr, "Error: failed to read the zip directory "
"structure - %d.\n", errno);
#endif
uio_GPRoot_umount(result);
errno = saveErrno;
return NULL;
}
return result;
}