From 35a64369837f76280ac02df882d19bfc69614891 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 6 Jan 2017 11:24:22 +0000 Subject: [PATCH] mount: implement proper directory handling (mkdir, rmdir) Before this change mount only simulated rmdir & mkdir, now it actually runs mkdir & rmdir on the underlying remote, using the new parmaeters to fs.Mkdir and fs.Rmdir. Fixes #956 --- cmd/mount/dir.go | 28 ++++++++++++++++++++++------ cmd/mount/mount.go | 18 +++++++++--------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/cmd/mount/dir.go b/cmd/mount/dir.go index 4e9761376..e94253ef1 100644 --- a/cmd/mount/dir.go +++ b/cmd/mount/dir.go @@ -273,10 +273,13 @@ var _ fusefs.NodeMkdirer = (*Dir)(nil) // Mkdir creates a new directory func (d *Dir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fusefs.Node, error) { - // We just pretend to have created the directory - rclone will - // actually create the directory if we write files into it path := path.Join(d.path, req.Name) fs.Debug(path, "Dir.Mkdir") + err := d.f.Mkdir(path) + if err != nil { + fs.ErrorLog(path, "Dir.Mkdir failed to create directory: %v", err) + return nil, err + } fsDir := &fs.Dir{ Name: path, When: time.Now(), @@ -308,10 +311,7 @@ func (d *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error { return err } case *fs.Dir: - // Do nothing for deleting directory - rclone can't - // currently remote a random directory - // - // Check directory is empty first though + // Check directory is empty first dir := item.node.(*Dir) empty, err := dir.isEmpty() if err != nil { @@ -323,6 +323,12 @@ func (d *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error { fs.ErrorLog(path, "Dir.Remove not empty") return fuse.EEXIST } + // remove directory + err = d.f.Rmdir(path) + if err != nil { + fs.ErrorLog(path, "Dir.Remove failed to remove directory: %v", err) + return err + } default: fs.ErrorLog(path, "Dir.Remove unknown type %T", item) return errors.Errorf("unknown type %T", item) @@ -380,6 +386,16 @@ func (d *Dir) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fusefs fs.ErrorLog(oldPath, "Dir.Rename can't rename non empty directory") return fuse.EEXIST } + err = d.f.Rmdir(oldPath) + if err != nil { + fs.ErrorLog(oldPath, "Dir.Rename failed to remove directory: %v", err) + return err + } + err = d.f.Mkdir(newPath) + if err != nil { + fs.ErrorLog(newPath, "Dir.Rename failed to create directory: %v", err) + return err + } newObj = &fs.Dir{ Name: newPath, When: time.Now(), diff --git a/cmd/mount/mount.go b/cmd/mount/mount.go index 1fb0337e2..88c177836 100644 --- a/cmd/mount/mount.go +++ b/cmd/mount/mount.go @@ -88,16 +88,16 @@ Or with OS X ### Limitations ### This can only write files seqentially, it can only seek when reading. +This means that many applications won't work with their files on an +rclone mount. -Rclone mount inherits rclone's directory handling. In rclone's world -directories don't really exist. This means that empty directories -will have a tendency to disappear once they fall out of the directory -cache. - -The bucket based FSes (eg swift, s3, google compute storage, b2) won't -work from the root - you will need to specify a bucket, or a path -within the bucket. So ` + "`swift:`" + ` won't work whereas ` + "`swift:bucket`" + ` will -as will ` + "`swift:bucket/path`" + `. +The bucket based remotes (eg Swift, S3, Google Compute Storage, B2, +Hubic) won't work from the root - you will need to specify a bucket, +or a path within the bucket. So ` + "`swift:`" + ` won't work whereas +` + "`swift:bucket`" + ` will as will ` + "`swift:bucket/path`" + `. +None of these support the concept of directories, so empty +directories will have a tendency to disappear once they fall out of +the directory cache. Only supported on Linux, FreeBSD and OS X at the moment.