Beispiel #1
0
int
uio_stat(uio_DirHandle *dir, const char *path, struct stat *statBuf) {
	uio_PDirHandle *pReadDir;
	uio_MountInfo *readMountInfo;
	char *name;
	int result;

	if (uio_getPhysicalAccess(dir, path, O_RDONLY, 0,
			&readMountInfo, &pReadDir, NULL,
			NULL, NULL, NULL, &name) == -1) {
		if (uio_statDir(dir, path, statBuf) == -1) {
			// errno is set
			return -1;
		}
		return 0;
	}

	if (pReadDir->pRoot->handler->stat == NULL) {
		uio_PDirHandle_unref(pReadDir);
		uio_free(name);
		errno = ENOSYS;
		return -1;
	}

	result = (pReadDir->pRoot->handler->stat)(pReadDir, name, statBuf);
	uio_PDirHandle_unref(pReadDir);
	uio_free(name);
	return result;
}
Beispiel #2
0
// Pre: there are no more references to PRoot or anything inside it.
int
uio_GPRoot_umount(uio_PRoot *pRoot) {
	uio_PDirHandle *topDirHandle;
	uio_GPDir *topDir;

	topDirHandle = uio_PRoot_getRootDirHandle(pRoot);
	topDir = topDirHandle->extra;
	if (pRoot->extra->flags & uio_GPRoot_PERSISTENT)
		uio_GPDir_deepPersistentUnref(topDir);
	uio_PDirHandle_unref(topDirHandle);
	(void) pRoot;
	return 0;
}
Beispiel #3
0
int
uio_mkdir(uio_DirHandle *dir, const char *path, mode_t mode) {
	uio_PDirHandle *pReadDir, *pWriteDir;
	uio_MountInfo *readMountInfo, *writeMountInfo;
	char *name;
	uio_PDirHandle *newDirHandle;

	if (uio_getPhysicalAccess(dir, path, O_WRONLY | O_CREAT | O_EXCL, 0,
			&readMountInfo, &pReadDir, NULL,
			&writeMountInfo, &pWriteDir, NULL, &name) == -1) {
		// errno is set
		if (errno == EISDIR)
			errno = EEXIST;
		return -1;
	}
	uio_PDirHandle_unref(pReadDir);
	
	if (pWriteDir->pRoot->handler->mkdir == NULL) {
		uio_free(name);
		uio_PDirHandle_unref(pWriteDir);
		errno = ENOSYS;
		return -1;
	}

	newDirHandle = (pWriteDir->pRoot->handler->mkdir)(pWriteDir, name, mode);
	if (newDirHandle == NULL) {
		int savedErrno = errno;
		uio_free(name);
		uio_PDirHandle_unref(pWriteDir);
		errno = savedErrno;
		return -1;
	}

	uio_PDirHandle_unref(pWriteDir);
	uio_PDirHandle_unref(newDirHandle);
	uio_free(name);
	return 0;
}
Beispiel #4
0
// 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 savedErrno = errno;
					uio_free(name);
					uio_PDirHandle_unref(readPDirHandle);
					uio_free(readPRootPath);
					uio_PDirHandle_unref(writePDirHandle);
					uio_free(writePRootPath);
					errno = savedErrno;
					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;
}
Beispiel #5
0
static void
uio_PDirHandles_delete(uio_PDirHandle *pDirHandles[], int numPDirHandles) {
	while (numPDirHandles--)
		uio_PDirHandle_unref(pDirHandles[numPDirHandles]);
	uio_free(pDirHandles);
}
Beispiel #6
0
uio_Handle *
uio_open(uio_DirHandle *dir, const char *path, int flags, mode_t mode) {
	uio_PDirHandle *readPDirHandle, *writePDirHandle, *pDirHandle;
	uio_MountInfo *readMountInfo, *writeMountInfo;
	char *name;
	uio_Handle *handle;
	
	if (uio_getPhysicalAccess(dir, path, flags, 0,
			&readMountInfo, &readPDirHandle, NULL,
			&writeMountInfo, &writePDirHandle, NULL, &name) == -1) {
		// errno is set
		return NULL;
	}
	
	if ((flags & O_ACCMODE) == O_RDONLY) {
		// WritePDirHandle is not filled in.
		pDirHandle = readPDirHandle;
	} 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(writePDirHandle);
		pDirHandle = readPDirHandle;
	} 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_PDirHandle_unref(writePDirHandle);
				errno = EEXIST;
				return NULL;
			}
			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 savedErrno = errno;
					uio_free(name);
					uio_PDirHandle_unref(readPDirHandle);
					uio_PDirHandle_unref(writePDirHandle);
					errno = savedErrno;
					return NULL;
				}
			}
		} else {
			// file does not exist
			if (((flags & O_ACCMODE) == O_RDONLY) ||
					(flags & O_CREAT) != O_CREAT) {
				uio_free(name);
				uio_PDirHandle_unref(readPDirHandle);
				uio_PDirHandle_unref(writePDirHandle);
				errno = ENOENT;
				return NULL;
			}
		}
		uio_PDirHandle_unref(readPDirHandle);
		pDirHandle = writePDirHandle;
	}

	handle = (pDirHandle->pRoot->handler->open)(pDirHandle, name, flags, mode);
			// Also adds a new entry to the physical dir if appropriate.
	if (handle == NULL) {
		int savedErrno = errno;
		uio_free(name);
		uio_PDirHandle_unref(pDirHandle);
		errno = savedErrno;
		return NULL;
	}

	uio_free(name);
	uio_PDirHandle_unref(pDirHandle);
	return handle;
}
Beispiel #7
0
int
uio_rename(uio_DirHandle *oldDir, const char *oldPath,
		uio_DirHandle *newDir, const char *newPath) {
	uio_PDirHandle *oldPReadDir, *newPReadDir, *newPWriteDir;
	uio_MountInfo *oldReadMountInfo, *newReadMountInfo, *newWriteMountInfo;
	char *oldName, *newName;
	int retVal;

	if (uio_getPhysicalAccess(oldDir, oldPath, O_RDONLY, 0,
			&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, NULL,
			&newWriteMountInfo, &newPWriteDir, NULL, &newName) == -1) {
		int savedErrno = errno;
		uio_PDirHandle_unref(oldPReadDir);
		uio_free(oldName);
		errno = savedErrno;
		return -1;
	}

	if (oldReadMountInfo != newWriteMountInfo) {
		uio_PDirHandle_unref(oldPReadDir);
		uio_PDirHandle_unref(newPReadDir);
		uio_PDirHandle_unref(newPWriteDir);
		uio_free(oldName);
		uio_free(newName);
		errno = EXDEV;
		return -1;
	}

	if (uio_mountInfoIsReadOnly(oldReadMountInfo)) {
		// XXX: Doesn't uio_getPhysicalAccess already handle this?
		//      It doesn't return EROFS though; perhaps it should.
		uio_PDirHandle_unref(oldPReadDir);
		uio_PDirHandle_unref(newPReadDir);
		uio_PDirHandle_unref(newPWriteDir);
		uio_free(oldName);
		uio_free(newName);
		errno = EROFS;
		return -1;
	}
	
	if (oldReadMountInfo->pDirHandle->pRoot->handler->rename == NULL) {
		uio_PDirHandle_unref(oldPReadDir);
		uio_PDirHandle_unref(newPReadDir);
		uio_PDirHandle_unref(newPWriteDir);
		uio_free(oldName);
		uio_free(newName);
		errno = ENOSYS;
		return -1;
	}
	retVal = (oldReadMountInfo->pDirHandle->pRoot->handler->rename)(
			oldPReadDir, oldName, newPWriteDir, newName);
	if (retVal == -1) {
		int savedErrno = errno;
		uio_PDirHandle_unref(oldPReadDir);
		uio_PDirHandle_unref(newPReadDir);
		uio_PDirHandle_unref(newPWriteDir);
		uio_free(oldName);
		uio_free(newName);
		errno = savedErrno;
		return -1;
	}

	uio_PDirHandle_unref(oldPReadDir);
	uio_PDirHandle_unref(newPReadDir);
	uio_PDirHandle_unref(newPWriteDir);
	uio_free(oldName);
	uio_free(newName);
	return 0;
}
Beispiel #8
0
/*
 * Function name: uio_mountDir
 * Description:   Grafts a directory from inside a physical fileSystem
 *                into the locical filesystem, at a specified directory.
 * Arguments:     destRep - the repository where the newly mounted dir
 *                		is to be grafted.
 *                mountPoint - the path to the directory where the dir
 *                		is to be grafted.
 *                fsType - the file system type of physical fileSystem
 *                		pointed to by sourcePath.
 *                sourceDir - the directory to which 'sourcePath' is to
 *                		be taken relative.
 *                sourcePath - a path relative to sourceDir, which contains
 *                		the file/directory to be mounted.
 *                		If sourceDir and sourcePath are NULL, the file
 *                		system of the operating system will be used.
 *                inPath - the location relative to the root of the newly
 *                		mounted fileSystem, pointing to the directory
 *                      that is to be grafted.
 *                      Note: If fsType is uio_FSTYPE_STDIO, inPath is
 *                      relative to the root of the filesystem, NOT to
 *                      the current working dir.
 *                autoMount - array of automount options in function
 *                		in this mountPoint.
 *                flags - one of uio_MOUNT_TOP, uio_MOUNT_BOTTOM,
 *                      uio_MOUNT_BELOW, uio_MOUNT_ABOVE, specifying
 *                      the precedence of this mount, OR'ed with
 *                      one or more of the following flags:
 *                      uio_MOUNT_RDONLY (no writing is allowed)
 *                relative - If 'flags' includes uio_MOUNT_BELOW or
 *                           uio_MOUNT_ABOVE, this is the mount handle
 *                           where the new mount is relative to.
 *                           Otherwise, it should be NULL.
 * Returns:       a handle suitable for uio_unmountDir()
 *                NULL if an error occured. In this case 'errno' is set.
 */
uio_MountHandle *
uio_mountDir(uio_Repository *destRep, const char *mountPoint,
		uio_FileSystemID fsType,
		uio_DirHandle *sourceDir, const char *sourcePath,
		const char *inPath, uio_AutoMount **autoMount, int flags,
		uio_MountHandle *relative) {
	uio_PRoot *pRoot;
	uio_Handle *handle;
	uio_FileSystemHandler *handler;
	uio_MountInfo *relativeInfo;

	switch (flags & uio_MOUNT_LOCATION_MASK) {
		case uio_MOUNT_TOP:
		case uio_MOUNT_BOTTOM:
			if (relative != NULL) {
				errno = EINVAL;
				return NULL;
			}
			relativeInfo = NULL;
			break;
		case uio_MOUNT_BELOW:
		case uio_MOUNT_ABOVE:
			if (relative == NULL) {
				errno = EINVAL;
				return NULL;
			}
			relativeInfo = relative->mountInfo;
			break;
		default:
			abort();
	}

	if (mountPoint[0] == '/')
		mountPoint++;
	if (!validPathName(mountPoint, strlen(mountPoint))) {
		errno = EINVAL;
		return NULL;
	}
	
	// TODO: check if the filesystem is already mounted, and if so, reuse it.
	// A RO filedescriptor will need to be replaced though if the
	// filesystem needs to be remounted RW now.
	if (sourceDir == NULL) {
		if (sourcePath != NULL) {
			// bad: sourceDir is NULL, but sourcePath isn't
			errno = EINVAL;
			return NULL;
		}
		handle = NULL;
	} else {
		if (sourcePath == NULL) {
			// bad: sourcePath is NULL, but sourceDir isn't
			errno = EINVAL;
			return NULL;
		}
		handle = uio_open(sourceDir, sourcePath,
				((flags & uio_MOUNT_RDONLY) == uio_MOUNT_RDONLY ?
				O_RDONLY : O_RDWR)
#ifdef WIN32
				| O_BINARY
#endif
				, 0);
		if (handle == NULL) {
			// errno is set
			return NULL;
		}
	}

	handler = uio_getFileSystemHandler(fsType);
	if (handler == NULL) {
		if (handle)
			uio_close(handle);
		errno = ENODEV;
		return NULL;
	}

	assert(handler->mount != NULL);
	pRoot = (handler->mount)(handle, flags);
	if (pRoot == NULL) {
		int savedErrno;

		savedErrno = errno;
		if (handle)
			uio_close(handle);
		errno = savedErrno;
		return NULL;
	}

	if (handle) {
		// Close this reference to handle.
		// The physical layer may store the link in pRoot, in which it
		// will be cleaned up from uio_unmount().
		uio_close(handle);
	}

	// The new file system is ready, now we need to find the specified
	// dir inside it and put it in its place in the mountTree.
	{
		uio_PDirHandle *endDirHandle;
		const char *endInPath;
		char *dirName;
		uio_MountInfo *mountInfo;
		uio_MountTree *mountTree;
		uio_PDirHandle *pRootHandle;
#ifdef BACKSLASH_IS_PATH_SEPARATOR
		char *unixPath;
		
		unixPath = dosToUnixPath(inPath);
		inPath = unixPath;
#endif  /* BACKSLASH_IS_PATH_SEPARATOR */

		if (inPath[0] == '/')
			inPath++;
		pRootHandle = uio_PRoot_getRootDirHandle(pRoot);
		uio_walkPhysicalPath(pRootHandle, inPath, strlen(inPath),
				&endDirHandle, &endInPath);
		if (*endInPath != '\0') {
			// Path inside the filesystem to mount does not exist.
#ifdef BACKSLASH_IS_PATH_SEPARATOR
			uio_free(unixPath);
#endif  /* BACKSLASH_IS_PATH_SEPARATOR */
			uio_PDirHandle_unref(endDirHandle);
			uio_PRoot_unrefMount(pRoot);
			errno = ENOENT;
			return NULL;
		}
	
		dirName = uio_malloc(endInPath - inPath + 1);
		memcpy(dirName, inPath, endInPath - inPath);
		dirName[endInPath - inPath] = '\0';
#ifdef BACKSLASH_IS_PATH_SEPARATOR
		// InPath is a copy with the paths fixed.
		uio_free(unixPath);
#endif  /* BACKSLASH_IS_PATH_SEPARATOR */
		mountInfo = uio_MountInfo_new(fsType, NULL, endDirHandle, dirName,
				autoMount, NULL, flags);
		uio_repositoryAddMount(destRep, mountInfo,
				flags & uio_MOUNT_LOCATION_MASK, relativeInfo);
		mountTree = uio_mountTreeAddMountInfo(destRep, destRep->mountTree,
				mountInfo, mountPoint, flags & uio_MOUNT_LOCATION_MASK,
				relativeInfo);
		// mountTree is the node in destRep->mountTree where mountInfo
		// leads to.
		mountInfo->mountTree = mountTree;
		mountInfo->mountHandle = uio_MountHandle_new(destRep, mountInfo);
		return mountInfo->mountHandle;
	}
}
Beispiel #9
0
void
uio_MountInfo_delete(uio_MountInfo *mountInfo) {
	uio_free(mountInfo->dirName);
	uio_PDirHandle_unref(mountInfo->pDirHandle);
	uio_MountInfo_free(mountInfo);
}