Index: lib/xvfs/xvfs.c.rvt ================================================================== --- lib/xvfs/xvfs.c.rvt +++ lib/xvfs/xvfs.c.rvt @@ -80,28 +80,32 @@ return(XVFS_NAME_LOOKUP_ERROR); } -static const char **xvfs__getChildren(const char *path, Tcl_WideInt *count) { +static const char **xvfs__getChildren(const char *path, long inode, Tcl_WideInt *count) { const struct xvfs_file_data *fileInfo; - long inode; /* * Validate input parameters */ if (count == NULL) { return(NULL); } /* - * Get the inode from the lookup function + * Use user-supplied inode, or look up the path */ - inode = xvfs__nameToIndex(path); - if (inode == XVFS_NAME_LOOKUP_ERROR) { - *count = XVFS_RV_ERR_ENOENT; - return(NULL); + if (inode == XVFS_INODE_NULL) { + /* + * Get the inode from the lookup function + */ + inode = xvfs__nameToIndex(path); + if (inode == XVFS_NAME_LOOKUP_ERROR) { + *count = XVFS_RV_ERR_ENOENT; + return(NULL); + } } fileInfo = &xvfs__data[inode]; /* @@ -114,14 +118,13 @@ *count = fileInfo->size; return(fileInfo->data.dirChildren); } -static const unsigned char *xvfs__getData(const char *path, Tcl_WideInt start, Tcl_WideInt *length) { +static const unsigned char *xvfs__getData(const char *path, long inode, Tcl_WideInt start, Tcl_WideInt *length) { const struct xvfs_file_data *fileInfo; Tcl_WideInt resultLength; - long inode; /* * Validate input parameters */ if (length == NULL) { @@ -135,18 +138,24 @@ if (*length < 0) { *length = XVFS_RV_ERR_EINVAL; return(NULL); } - + + /* - * Get the inode from the lookup function + * Use user-supplied inode, or look up the path */ - inode = xvfs__nameToIndex(path); - if (inode == XVFS_NAME_LOOKUP_ERROR) { - *length = XVFS_RV_ERR_ENOENT; - return(NULL); + if (inode == XVFS_INODE_NULL) { + /* + * Get the inode from the lookup function + */ + inode = xvfs__nameToIndex(path); + if (inode == XVFS_NAME_LOOKUP_ERROR) { + *length = XVFS_RV_ERR_ENOENT; + return(NULL); + } } fileInfo = &xvfs__data[inode]; /* @@ -176,27 +185,31 @@ * Return the data */ return(fileInfo->data.fileContents + start); } -static int xvfs__getStat(const char *path, Tcl_StatBuf *statBuf) { +static int xvfs__getStat(const char *path, long inode, Tcl_StatBuf *statBuf) { const struct xvfs_file_data *fileInfo; - long inode; /* * Validate input parameters */ if (!statBuf) { return(XVFS_RV_ERR_EINVAL); } /* - * Get the inode from the lookup function + * Use user-supplied inode, or look up the path */ - inode = xvfs__nameToIndex(path); - if (inode == XVFS_NAME_LOOKUP_ERROR) { - return(XVFS_RV_ERR_ENOENT); + if (inode == XVFS_INODE_NULL) { + /* + * Get the inode from the lookup function + */ + inode = xvfs__nameToIndex(path); + if (inode == XVFS_NAME_LOOKUP_ERROR) { + return(XVFS_RV_ERR_ENOENT); + } } fileInfo = &xvfs__data[inode]; statBuf->st_dev = ; Index: xvfs-core.c ================================================================== --- xvfs-core.c +++ xvfs-core.c @@ -199,11 +199,11 @@ * Xvfs Memory Channel */ struct xvfs_tclfs_channel_id { Tcl_Channel channel; struct xvfs_tclfs_instance_info *fsInstanceInfo; - Tcl_Obj *path; + long inode; Tcl_WideInt currentOffset; Tcl_WideInt fileSize; int eofMarked; int queuedEvents; int closed; @@ -222,11 +222,11 @@ int statRet; XVFS_DEBUG_ENTER; XVFS_DEBUG_PRINTF("Opening file \"%s\" ...", Tcl_GetString(path)); - statRet = instanceInfo->fsInfo->getStatProc(Tcl_GetString(path), &fileInfo); + statRet = instanceInfo->fsInfo->getStatProc(Tcl_GetString(path), XVFS_INODE_NULL, &fileInfo); if (statRet < 0) { XVFS_DEBUG_PRINTF("... failed: %s", xvfs_strerror(statRet)); xvfs_setresults_error(interp, XVFS_RV_ERR_ENOENT); @@ -247,10 +247,11 @@ channelInstanceData->currentOffset = 0; channelInstanceData->eofMarked = 0; channelInstanceData->queuedEvents = 0; channelInstanceData->closed = 0; channelInstanceData->channel = NULL; + channelInstanceData->inode = fileInfo.st_ino; channelName = Tcl_ObjPrintf("xvfs0x%llx", (unsigned long long) channelInstanceData); if (!channelName) { XVFS_DEBUG_PUTS("... failed"); @@ -261,12 +262,10 @@ } Tcl_IncrRefCount(channelName); channelInstanceData->fsInstanceInfo = instanceInfo; channelInstanceData->fileSize = fileInfo.st_size; - channelInstanceData->path = path; - Tcl_IncrRefCount(path); channel = Tcl_CreateChannel(&xvfs_tclfs_channelType, Tcl_GetString(channelName), channelInstanceData, TCL_READABLE); Tcl_DecrRefCount(channelName); if (!channel) { XVFS_DEBUG_PUTS("... failed"); @@ -326,11 +325,10 @@ XVFS_DEBUG_LEAVE; return(0); } - Tcl_DecrRefCount(channelInstanceData->path); Tcl_Free((char *) channelInstanceData); XVFS_DEBUG_PUTS("... ok"); XVFS_DEBUG_LEAVE; @@ -339,11 +337,11 @@ static int xvfs_tclfs_readChannel(ClientData channelInstanceData_p, char *buf, int bufSize, int *errorCodePtr) { struct xvfs_tclfs_channel_id *channelInstanceData; const unsigned char *data; Tcl_WideInt offset, length; - char *path; + long inode; channelInstanceData = (struct xvfs_tclfs_channel_id *) channelInstanceData_p; /* * If we are already at the end of the file we can skip @@ -351,15 +349,15 @@ */ if (channelInstanceData->eofMarked) { return(0); } - path = Tcl_GetString(channelInstanceData->path); + inode = channelInstanceData->inode; offset = channelInstanceData->currentOffset; length = bufSize; - data = channelInstanceData->fsInstanceInfo->fsInfo->getDataProc(path, offset, &length); + data = channelInstanceData->fsInstanceInfo->fsInfo->getDataProc(NULL, inode, offset, &length); if (length < 0) { *errorCodePtr = xvfs_errorToErrno(length); return(-1); @@ -518,11 +516,11 @@ path = xvfs_absolutePath(path); pathStr = xvfs_relativePath(path, instanceInfo); - retval = instanceInfo->fsInfo->getStatProc(pathStr, statBuf); + retval = instanceInfo->fsInfo->getStatProc(pathStr, XVFS_INODE_NULL, statBuf); if (retval < 0) { XVFS_DEBUG_PRINTF("... failed: %s", xvfs_strerror(retval)); Tcl_SetErrno(xvfs_errorToErrno(retval)); @@ -563,11 +561,11 @@ XVFS_DEBUG_LEAVE; return(-1); } - statRetVal = instanceInfo->fsInfo->getStatProc(pathStr, &fileInfo); + statRetVal = instanceInfo->fsInfo->getStatProc(pathStr, XVFS_INODE_NULL, &fileInfo); if (statRetVal < 0) { XVFS_DEBUG_PUTS("... no (not statable)"); Tcl_DecrRefCount(path); @@ -765,11 +763,11 @@ XVFS_DEBUG_LEAVE; return(TCL_OK); } childrenCount = 0; - children = instanceInfo->fsInfo->getChildrenProc(pathStr, &childrenCount); + children = instanceInfo->fsInfo->getChildrenProc(pathStr, XVFS_INODE_NULL, &childrenCount); if (childrenCount < 0) { XVFS_DEBUG_PRINTF("... error: %s", xvfs_strerror(childrenCount)); Tcl_DecrRefCount(path); Index: xvfs-core.h ================================================================== --- xvfs-core.h +++ xvfs-core.h @@ -3,13 +3,13 @@ #include #define XVFS_PROTOCOL_VERSION 1 -typedef const char **(*xvfs_proc_getChildren_t)(const char *path, Tcl_WideInt *count); -typedef const unsigned char *(*xvfs_proc_getData_t)(const char *path, Tcl_WideInt start, Tcl_WideInt *length); -typedef int (*xvfs_proc_getStat_t)(const char *path, Tcl_StatBuf *statBuf); +typedef const char **(*xvfs_proc_getChildren_t)(const char *path, long inode, Tcl_WideInt *count); +typedef const unsigned char *(*xvfs_proc_getData_t)(const char *path, long inode, Tcl_WideInt start, Tcl_WideInt *length); +typedef int (*xvfs_proc_getStat_t)(const char *path, long inode, Tcl_StatBuf *statBuf); /* * Interface for the filesystem to fill out before registering. * The protocolVersion is provided first so that if this * needs to change over time it can be appropriately handled. @@ -32,10 +32,17 @@ #define XVFS_RV_ERR_ENOTDIR (-8195) #define XVFS_RV_ERR_EFAULT (-8196) #define XVFS_RV_ERR_EROFS (-8197) #define XVFS_RV_ERR_INTERNAL (-16383) +/* + * Functions allow user to specify either a path or a inode. + * If a path is specified, the inode must be specified as + * XVFS_INODE_NULL. + */ +#define XVFS_INODE_NULL (-1) + #define XVFS_REGISTER_INTERFACE(name) int name(Tcl_Interp *interp, struct Xvfs_FSInfo *fsInfo); #if defined(XVFS_MODE_STANDALONE) /* * In standalone mode, we just redefine calls to