Fsutil mount: added truncate, mkdir, rmdir, link and unlink calls.

This commit is contained in:
Serge Vakulenko
2014-07-18 00:13:27 -07:00
parent 847e2bff77
commit d6e558bea0

View File

@@ -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);