diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 8471ede..165bb93 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -113,8 +113,7 @@ int op_getattr(const char *path, struct stat *statbuf) fs_t *fs = fuse_get_context()->private_data; fs_inode_t inode; - printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", - path, statbuf); + printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", path, statbuf); if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { printlog("--- search failed\n"); @@ -136,12 +135,8 @@ int op_getattr(const char *path, struct stat *statbuf) int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) { printlog("--- op_fgetattr(path=\"%s\", statbuf=%p, fi=%p)\n", - path, statbuf, fi); + path, statbuf, fi); - // On FreeBSD, trying to do anything with the mountpoint ends up - // opening it, and then using the FD for an fgetattr. So in the - // special case of a path of "/", I need to do a getattr on the - // underlying root directory instead of doing the fgetattr(). if (strcmp(path, "/") == 0) return op_getattr(path, statbuf); @@ -166,7 +161,7 @@ int op_open(const char *path, struct fuse_file_info *fi) int write_flag = (fi->flags & O_ACCMODE) != O_RDONLY; printlog("--- op_open(path=\"%s\", fi=%p) flags=%#x \n", - path, fi, fi->flags); + path, fi, fi->flags); if (! fs_file_open (fs, &file, path, write_flag)) { printlog("--- open failed\n"); @@ -200,7 +195,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) fs_t *fs = fuse_get_context()->private_data; printlog("--- op_create(path=\"%s\", mode=0%03o, fi=%p)\n", - path, mode, fi); + path, mode, fi); file.inode.mode = 0; if (! fs_file_create (fs, &file, path, mode & 07777)) { @@ -209,6 +204,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) return -EISDIR; return -EIO; } + file.inode.mtime = time(0); return 0; } @@ -225,7 +221,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { printlog("--- op_read(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", - path, buf, size, offset, fi); + path, buf, size, offset, fi); if (offset >= file.inode.size) return 0; @@ -253,13 +249,14 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { printlog("--- op_write(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", - path, buf, size, offset, fi); + path, buf, size, offset, fi); file.offset = offset; if (! fs_file_write (&file, (unsigned char*) buf, size)) { printlog("--- read failed\n"); return -EIO; } + file.inode.mtime = time(0); return size; } @@ -278,8 +275,7 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset, */ int op_release(const char *path, struct fuse_file_info *fi) { - printlog("--- op_release(path=\"%s\", fi=%p)\n", - path, fi); + printlog("--- op_release(path=\"%s\", fi=%p)\n", path, fi); if (file.inode.mode == 0) return -EBADF; @@ -289,6 +285,212 @@ int op_release(const char *path, struct fuse_file_info *fi) return 0; } +/* + * Change the size of a file + */ +int op_truncate(const char *path, off_t newsize) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_file_t f; + + printlog("--- op_truncate(path=\"%s\", newsize=%lld)\n", path, newsize); + + if (! fs_file_open (fs, &f, path, 1)) { + printlog("--- open failed\n"); + return -ENOENT; + } + + if ((f.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot truncate special files. */ + return -EINVAL; + } + fs_inode_truncate (&f.inode, newsize); + f.inode.mtime = time(0); + fs_file_close (&f); + return 0; +} + +/* + * Change the size of an open file + * + * This method is called instead of the truncate() method if the + * truncation was invoked from an ftruncate() system call. + */ +int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) +{ + printlog("--- op_ftruncate(path=\"%s\", offset=%lld, fi=%p)\n", + path, offset, fi); + + if (! file.writable) + return -EACCES; + + if ((file.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot truncate special files. */ + return -EINVAL; + } + fs_inode_truncate (&file.inode, offset); + file.inode.mtime = time(0); + fs_file_close (&file); + return 0; +} + +/* + * Remove a file + */ +int op_unlink(const char *path) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("op_unlink(path=\"%s\")\n", path); + + /* Get the file type. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- search failed\n"); + return -ENOENT; + } + if ((file.inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot unlink directories. */ + return -EISDIR; + } + + /* Delete file. */ + if (! fs_inode_by_name (fs, &inode, path, 2, 0)) { + printlog("--- delete failed\n"); + return -EIO; + } + return 0; +} + +/* + * Remove a directory + */ +int op_rmdir(const char *path) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode, parent; + char buf [BSDFS_BSIZE], *p; + + printlog("op_rmdir(path=\"%s\")\n", path); + + /* Get the file type. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- search failed\n"); + return -ENOENT; + } + if ((inode.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { + /* Cannot remove files. */ + return -ENOTDIR; + } + if (inode.nlink > 2) { + /* Cannot remove non-empty directories. */ + return -ENOTEMPTY; + } + + /* Open parent directory. */ + strcpy (buf, path); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { + printlog("--- parent not found\n"); + return -ENOENT; + } + + /* Delete directory. */ + inode.nlink -= 1; + if (! fs_inode_by_name (fs, &inode, path, 2, 0)) { + printlog("--- delete failed\n"); + return -EIO; + } + + /* Decrease a parent's link counter. */ + if (! fs_inode_get (fs, &parent, parent.number)) { + printlog("--- cannot reopen parent\n"); + return -EIO; + } + ++parent.nlink; + fs_inode_save (&parent, 1); + return 0; +} + +/* + * Create a directory + */ +int op_mkdir(const char *path, mode_t mode) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t dir, parent; + char buf [BSDFS_BSIZE], *p; + + printlog("--- op_mkdir(path=\"%s\", mode=0%3o)\n", path, mode); + + /* Open parent directory. */ + strcpy (buf, path); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { + printlog("--- parent not found\n"); + return -ENOENT; + } + + /* Create directory. */ + int done = fs_inode_by_name (fs, &dir, path, 1, INODE_MODE_FDIR | (mode & 07777)); + if (! done) { + printlog("--- cannot create dir inode\n"); + return -ENOENT; + } + if (done == 1) { + /* The directory already existed. */ + return -EEXIST; + } + fs_inode_save (&dir, 0); + + /* Make parent link '..' */ + strcpy (buf, path); + strcat (buf, "/.."); + if (! fs_inode_by_name (fs, &dir, buf, 3, parent.number)) { + printlog("--- dotdot link failed\n"); + return -EIO; + } + if (! fs_inode_get (fs, &parent, parent.number)) { + printlog("--- cannot reopen parent\n"); + return -EIO; + } + ++parent.nlink; + fs_inode_save (&parent, 1); + return 0; +} + +/* + * Create a hard link to a file + */ +int op_link(const char *path, const char *newpath) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t source, target; + + printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", path, newpath); + + /* Find source. */ + if (! fs_inode_by_name (fs, &source, path, 0, 0)) { + printlog("--- source not found\n"); + return -ENOENT; + } + + /* Create target link. */ + if (! fs_inode_by_name (fs, &target, newpath, 3, source.number)) { + printlog("--- link failed\n"); + return -EIO; + } + return 0; +} + /* * Read the target of a symbolic link * @@ -305,7 +507,7 @@ int op_release(const char *path, struct fuse_file_info *fi) int op_readlink(const char *path, char *link, size_t size) { printlog("op_readlink(path=\"%s\", link=\"%s\", size=%d)\n", - path, link, size); + path, link, size); //TODO //retstat = readlink(path, link, size - 1); @@ -328,7 +530,7 @@ int op_readlink(const char *path, char *link, size_t size) int op_mknod(const char *path, mode_t mode, dev_t dev) { printlog("--- op_mknod(path=\"%s\", mode=0%3o, dev=%lld)\n", - path, mode, dev); + path, mode, dev); //TODO //if (S_ISREG(mode)) { @@ -352,54 +554,6 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) return 0; } -/* - * Create a directory - */ -int op_mkdir(const char *path, mode_t mode) -{ - printlog("--- op_mkdir(path=\"%s\", mode=0%3o)\n", - path, mode); - - //TODO - //retstat = mkdir(path, mode); - //if (retstat < 0) - // retstat = print_errno("op_mkdir mkdir"); - - return 0; -} - -/* - * Remove a file - */ -int op_unlink(const char *path) -{ - printlog("op_unlink(path=\"%s\")\n", - path); - - //TODO - //retstat = unlink(path); - //if (retstat < 0) - // retstat = print_errno("op_unlink unlink"); - - return 0; -} - -/* - * Remove a directory - */ -int op_rmdir(const char *path) -{ - printlog("op_rmdir(path=\"%s\")\n", - path); - - //TODO - //retstat = rmdir(path); - //if (retstat < 0) - // retstat = print_errno("op_rmdir rmdir"); - - return 0; -} - /* * Create a symbolic link * The parameters here are a little bit confusing, but do correspond @@ -409,8 +563,7 @@ int op_rmdir(const char *path) */ int op_symlink(const char *path, const char *link) { - printlog("--- op_symlink(path=\"%s\", link=\"%s\")\n", - path, link); + printlog("--- op_symlink(path=\"%s\", link=\"%s\")\n", path, link); //TODO //retstat = symlink(path, link); @@ -427,8 +580,7 @@ int op_symlink(const char *path, const char *link) */ int op_rename(const char *path, const char *newpath) { - printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", - path, newpath); + printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); //TODO //retstat = rename(path, newpath); @@ -438,29 +590,12 @@ int op_rename(const char *path, const char *newpath) return 0; } -/* - * Create a hard link to a file - */ -int op_link(const char *path, const char *newpath) -{ - printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", - path, newpath); - - //TODO - //retstat = link(path, newpath); - //if (retstat < 0) - // retstat = print_errno("op_link link"); - - return 0; -} - /* * Change the permission bits of a file */ int op_chmod(const char *path, mode_t mode) { - printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", - path, mode); + printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", path, mode); //TODO //retstat = chmod(path, mode); @@ -475,8 +610,7 @@ int op_chmod(const char *path, mode_t mode) */ int op_chown(const char *path, uid_t uid, gid_t gid) { - printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", - path, uid, gid); + printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); //TODO //retstat = chown(path, uid, gid); @@ -486,29 +620,12 @@ int op_chown(const char *path, uid_t uid, gid_t gid) return 0; } -/* - * Change the size of a file - */ -int op_truncate(const char *path, off_t newsize) -{ - printlog("--- op_truncate(path=\"%s\", newsize=%lld)\n", - path, newsize); - - //TODO - //retstat = truncate(path, newsize); - //if (retstat < 0) - // print_errno("op_truncate truncate"); - - return 0; -} - /* * Change the access and/or modification times of a file */ int op_utime(const char *path, struct utimbuf *ubuf) { - printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", - path, ubuf); + printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", path, ubuf); //TODO //retstat = utime(path, ubuf); @@ -525,8 +642,7 @@ int op_utime(const char *path, struct utimbuf *ubuf) */ int op_statfs(const char *path, struct statvfs *statv) { - printlog("--- op_statfs(path=\"%s\", statv=%p)\n", - path, statv); + printlog("--- op_statfs(path=\"%s\", statv=%p)\n", path, statv); // get stats for underlying filesystem //TODO @@ -574,7 +690,7 @@ int op_flush(const char *path, struct fuse_file_info *fi) int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) { printlog("--- op_fsync(path=\"%s\", datasync=%d, fi=%p)\n", - path, datasync, fi); + path, datasync, fi); if (datasync == 0 && file.writable) { if (! fs_inode_save (&file.inode, 0)) @@ -591,8 +707,7 @@ int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) */ int op_opendir(const char *path, struct fuse_file_info *fi) { - printlog("--- op_opendir(path=\"%s\", fi=%p)\n", - path, fi); + printlog("--- op_opendir(path=\"%s\", fi=%p)\n", path, fi); return 0; } @@ -629,7 +744,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset } dirent; printlog("--- op_readdir(path=\"%s\", buf=%p, filler=%p, offset=%lld, fi=%p)\n", - path, buf, filler, offset, fi); + path, buf, filler, offset, fi); if (! fs_inode_by_name (fs, &dir, path, 0, 0)) { printlog("--- cannot find path %s\n", path); @@ -668,8 +783,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset */ int op_releasedir(const char *path, struct fuse_file_info *fi) { - printlog("--- op_releasedir(path=\"%s\", fi=%p)\n", - path, fi); + printlog("--- op_releasedir(path=\"%s\", fi=%p)\n", path, fi); return 0; } @@ -692,32 +806,12 @@ void op_destroy(void *userdata) */ int op_access(const char *path, int mask) { - printlog("--- op_access(path=\"%s\", mask=0%o)\n", - path, mask); + printlog("--- op_access(path=\"%s\", mask=0%o)\n", path, mask); /* Always permitted. */ return 0; } -/* - * Change the size of an open file - * - * This method is called instead of the truncate() method if the - * truncation was invoked from an ftruncate() system call. - */ -int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) -{ - printlog("--- op_ftruncate(path=\"%s\", offset=%lld, fi=%p)\n", - path, offset, fi); - - //TODO - //retstat = ftruncate(fi->fh, offset); - //if (retstat < 0) - // retstat = print_errno("op_ftruncate ftruncate"); - - return 0; -} - static struct fuse_operations mount_ops = { .access = op_access, .chmod = op_chmod, @@ -760,10 +854,10 @@ int fs_mount(fs_t *fs, char *dirname) /* Invoke FUSE to mount the filesystem. */ ac = 0; av[ac++] = "fsutil"; - av[ac++] = "-f"; // foreground - av[ac++] = "-s"; // single-threaded + av[ac++] = "-f"; /* foreground */ + av[ac++] = "-s"; /* single-threaded */ if (verbose > 1) - av[ac++] = "-d"; // debug + av[ac++] = "-d"; /* debug */ av[ac++] = dirname; av[ac] = 0; ret = fuse_main(ac, av, &mount_ops, fs);