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
This commit is contained in:
Nick Craig-Wood 2017-01-06 11:24:22 +00:00
parent 341745d4d5
commit 35a6436983
2 changed files with 31 additions and 15 deletions

View File

@ -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(),

View File

@ -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.