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 // Mkdir creates a new directory
func (d *Dir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fusefs.Node, error) { 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) path := path.Join(d.path, req.Name)
fs.Debug(path, "Dir.Mkdir") 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{ fsDir := &fs.Dir{
Name: path, Name: path,
When: time.Now(), When: time.Now(),
@ -308,10 +311,7 @@ func (d *Dir) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
return err return err
} }
case *fs.Dir: case *fs.Dir:
// Do nothing for deleting directory - rclone can't // Check directory is empty first
// currently remote a random directory
//
// Check directory is empty first though
dir := item.node.(*Dir) dir := item.node.(*Dir)
empty, err := dir.isEmpty() empty, err := dir.isEmpty()
if err != nil { 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") fs.ErrorLog(path, "Dir.Remove not empty")
return fuse.EEXIST 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: default:
fs.ErrorLog(path, "Dir.Remove unknown type %T", item) fs.ErrorLog(path, "Dir.Remove unknown type %T", item)
return errors.Errorf("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") fs.ErrorLog(oldPath, "Dir.Rename can't rename non empty directory")
return fuse.EEXIST 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{ newObj = &fs.Dir{
Name: newPath, Name: newPath,
When: time.Now(), When: time.Now(),

View File

@ -88,16 +88,16 @@ Or with OS X
### Limitations ### ### Limitations ###
This can only write files seqentially, it can only seek when reading. 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 The bucket based remotes (eg Swift, S3, Google Compute Storage, B2,
directories don't really exist. This means that empty directories Hubic) won't work from the root - you will need to specify a bucket,
will have a tendency to disappear once they fall out of the directory or a path within the bucket. So ` + "`swift:`" + ` won't work whereas
cache. ` + "`swift:bucket`" + ` will as will ` + "`swift:bucket/path`" + `.
None of these support the concept of directories, so empty
The bucket based FSes (eg swift, s3, google compute storage, b2) won't directories will have a tendency to disappear once they fall out of
work from the root - you will need to specify a bucket, or a path the directory cache.
within the bucket. So ` + "`swift:`" + ` won't work whereas ` + "`swift:bucket`" + ` will
as will ` + "`swift:bucket/path`" + `.
Only supported on Linux, FreeBSD and OS X at the moment. Only supported on Linux, FreeBSD and OS X at the moment.