mirror of
https://github.com/rclone/rclone.git
synced 2025-01-10 16:28:30 +01:00
cmount, mount, mountlib: make --read-only reject modify operations
Normally mount/cmount use `-o ro` to get the kernel to mark the fs as read only. However this is ignored by WinFsp, so in addition if `--read-only` is in effect then return EROFS ("Read only File System") from all methods which attempt to modify something.
This commit is contained in:
parent
8be8a8e41b
commit
b259f8b752
@ -44,6 +44,9 @@ func NewFS(f fs.Fs) *FS {
|
|||||||
if noChecksum {
|
if noChecksum {
|
||||||
fsys.FS.NoChecksum()
|
fsys.FS.NoChecksum()
|
||||||
}
|
}
|
||||||
|
if readOnly {
|
||||||
|
fsys.FS.ReadOnly()
|
||||||
|
}
|
||||||
return fsys
|
return fsys
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,6 +662,8 @@ func translateError(err error) (errc int) {
|
|||||||
return -fuse.ESPIPE
|
return -fuse.ESPIPE
|
||||||
case mountlib.EBADF:
|
case mountlib.EBADF:
|
||||||
return -fuse.EBADF
|
return -fuse.EBADF
|
||||||
|
case mountlib.EROFS:
|
||||||
|
return -fuse.EROFS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fs.Errorf(nil, "IO error: %v", err)
|
fs.Errorf(nil, "IO error: %v", err)
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
package mount
|
package mount
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"bazil.org/fuse"
|
"bazil.org/fuse"
|
||||||
fusefs "bazil.org/fuse/fs"
|
fusefs "bazil.org/fuse/fs"
|
||||||
"github.com/ncw/rclone/cmd/mountlib"
|
"github.com/ncw/rclone/cmd/mountlib"
|
||||||
@ -34,6 +36,9 @@ func NewFS(f fs.Fs) *FS {
|
|||||||
if noChecksum {
|
if noChecksum {
|
||||||
fsys.FS.NoChecksum()
|
fsys.FS.NoChecksum()
|
||||||
}
|
}
|
||||||
|
if readOnly {
|
||||||
|
fsys.FS.ReadOnly()
|
||||||
|
}
|
||||||
return fsys
|
return fsys
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,12 +80,20 @@ func translateError(err error) error {
|
|||||||
cause := errors.Cause(err)
|
cause := errors.Cause(err)
|
||||||
if mErr, ok := cause.(mountlib.Error); ok {
|
if mErr, ok := cause.(mountlib.Error); ok {
|
||||||
switch mErr {
|
switch mErr {
|
||||||
|
case mountlib.OK:
|
||||||
|
return nil
|
||||||
case mountlib.ENOENT:
|
case mountlib.ENOENT:
|
||||||
return fuse.ENOENT
|
return fuse.ENOENT
|
||||||
case mountlib.ENOTEMPTY:
|
case mountlib.ENOTEMPTY:
|
||||||
return fuse.EEXIST // return fuse.ENOTEMPTY - doesn't exist though so use EEXIST
|
return fuse.Errno(syscall.ENOTEMPTY)
|
||||||
case mountlib.EEXIST:
|
case mountlib.EEXIST:
|
||||||
return fuse.EEXIST
|
return fuse.EEXIST
|
||||||
|
case mountlib.ESPIPE:
|
||||||
|
return fuse.Errno(syscall.ESPIPE)
|
||||||
|
case mountlib.EBADF:
|
||||||
|
return fuse.Errno(syscall.EBADF)
|
||||||
|
case mountlib.EROFS:
|
||||||
|
return fuse.Errno(syscall.EROFS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -242,6 +242,9 @@ func (d *Dir) ModTime() time.Time {
|
|||||||
|
|
||||||
// SetModTime sets the modTime for this dir
|
// SetModTime sets the modTime for this dir
|
||||||
func (d *Dir) SetModTime(modTime time.Time) error {
|
func (d *Dir) SetModTime(modTime time.Time) error {
|
||||||
|
if d.fsys.readOnly {
|
||||||
|
return EROFS
|
||||||
|
}
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
d.modTime = modTime
|
d.modTime = modTime
|
||||||
@ -312,6 +315,9 @@ func (d *Dir) ReadDirAll() (items []*DirEntry, err error) {
|
|||||||
|
|
||||||
// Create makes a new file
|
// Create makes a new file
|
||||||
func (d *Dir) Create(name string) (*File, *WriteFileHandle, error) {
|
func (d *Dir) Create(name string) (*File, *WriteFileHandle, error) {
|
||||||
|
if d.fsys.readOnly {
|
||||||
|
return nil, nil, EROFS
|
||||||
|
}
|
||||||
path := path.Join(d.path, name)
|
path := path.Join(d.path, name)
|
||||||
// fs.Debugf(path, "Dir.Create")
|
// fs.Debugf(path, "Dir.Create")
|
||||||
src := newCreateInfo(d.f, path)
|
src := newCreateInfo(d.f, path)
|
||||||
@ -328,6 +334,9 @@ func (d *Dir) Create(name string) (*File, *WriteFileHandle, error) {
|
|||||||
|
|
||||||
// Mkdir creates a new directory
|
// Mkdir creates a new directory
|
||||||
func (d *Dir) Mkdir(name string) (*Dir, error) {
|
func (d *Dir) Mkdir(name string) (*Dir, error) {
|
||||||
|
if d.fsys.readOnly {
|
||||||
|
return nil, EROFS
|
||||||
|
}
|
||||||
path := path.Join(d.path, name)
|
path := path.Join(d.path, name)
|
||||||
// fs.Debugf(path, "Dir.Mkdir")
|
// fs.Debugf(path, "Dir.Mkdir")
|
||||||
err := d.f.Mkdir(path)
|
err := d.f.Mkdir(path)
|
||||||
@ -349,6 +358,9 @@ func (d *Dir) Mkdir(name string) (*Dir, error) {
|
|||||||
// the receiver, which must be a directory. The entry to be removed
|
// the receiver, which must be a directory. The entry to be removed
|
||||||
// may correspond to a file (unlink) or to a directory (rmdir).
|
// may correspond to a file (unlink) or to a directory (rmdir).
|
||||||
func (d *Dir) Remove(name string) error {
|
func (d *Dir) Remove(name string) error {
|
||||||
|
if d.fsys.readOnly {
|
||||||
|
return EROFS
|
||||||
|
}
|
||||||
path := path.Join(d.path, name)
|
path := path.Join(d.path, name)
|
||||||
// fs.Debugf(path, "Dir.Remove")
|
// fs.Debugf(path, "Dir.Remove")
|
||||||
item, err := d.lookupNode(name)
|
item, err := d.lookupNode(name)
|
||||||
@ -393,6 +405,9 @@ func (d *Dir) Remove(name string) error {
|
|||||||
|
|
||||||
// Rename the file
|
// Rename the file
|
||||||
func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
|
func (d *Dir) Rename(oldName, newName string, destDir *Dir) error {
|
||||||
|
if d.fsys.readOnly {
|
||||||
|
return EROFS
|
||||||
|
}
|
||||||
oldPath := path.Join(d.path, oldName)
|
oldPath := path.Join(d.path, oldName)
|
||||||
newPath := path.Join(destDir.path, newName)
|
newPath := path.Join(destDir.path, newName)
|
||||||
// fs.Debugf(oldPath, "Dir.Rename to %q", newPath)
|
// fs.Debugf(oldPath, "Dir.Rename to %q", newPath)
|
||||||
|
@ -7,6 +7,8 @@ import "fmt"
|
|||||||
// Error describes low level errors in a cross platform way
|
// Error describes low level errors in a cross platform way
|
||||||
type Error byte
|
type Error byte
|
||||||
|
|
||||||
|
// NB if changing errors translateError in cmd/mount/fs.go, cmd/cmount/fs.go
|
||||||
|
|
||||||
// Low level errors
|
// Low level errors
|
||||||
const (
|
const (
|
||||||
OK Error = iota
|
OK Error = iota
|
||||||
@ -15,6 +17,7 @@ const (
|
|||||||
EEXIST
|
EEXIST
|
||||||
ESPIPE
|
ESPIPE
|
||||||
EBADF
|
EBADF
|
||||||
|
EROFS
|
||||||
)
|
)
|
||||||
|
|
||||||
var errorNames = []string{
|
var errorNames = []string{
|
||||||
@ -24,6 +27,7 @@ var errorNames = []string{
|
|||||||
EEXIST: "File exists",
|
EEXIST: "File exists",
|
||||||
ESPIPE: "Illegal seek",
|
ESPIPE: "Illegal seek",
|
||||||
EBADF: "Bad file descriptor",
|
EBADF: "Bad file descriptor",
|
||||||
|
EROFS: "Read only file system",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error renders the error as a string
|
// Error renders the error as a string
|
||||||
|
@ -93,6 +93,9 @@ func (f *File) Attr(noModTime bool) (modTime time.Time, Size, Blocks uint64, err
|
|||||||
|
|
||||||
// SetModTime sets the modtime for the file
|
// SetModTime sets the modtime for the file
|
||||||
func (f *File) SetModTime(modTime time.Time) error {
|
func (f *File) SetModTime(modTime time.Time) error {
|
||||||
|
if f.d.fsys.readOnly {
|
||||||
|
return EROFS
|
||||||
|
}
|
||||||
f.mu.Lock()
|
f.mu.Lock()
|
||||||
defer f.mu.Unlock()
|
defer f.mu.Unlock()
|
||||||
|
|
||||||
@ -188,6 +191,9 @@ func (f *File) OpenRead() (fh *ReadFileHandle, err error) {
|
|||||||
|
|
||||||
// OpenWrite open the file for write
|
// OpenWrite open the file for write
|
||||||
func (f *File) OpenWrite() (fh *WriteFileHandle, err error) {
|
func (f *File) OpenWrite() (fh *WriteFileHandle, err error) {
|
||||||
|
if f.d.fsys.readOnly {
|
||||||
|
return nil, EROFS
|
||||||
|
}
|
||||||
// if o is nil it isn't valid yet
|
// if o is nil it isn't valid yet
|
||||||
o, err := f.waitForValidObject()
|
o, err := f.waitForValidObject()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -39,6 +39,7 @@ type FS struct {
|
|||||||
root *Dir
|
root *Dir
|
||||||
noSeek bool // don't allow seeking if set
|
noSeek bool // don't allow seeking if set
|
||||||
noChecksum bool // don't check checksums if set
|
noChecksum bool // don't check checksums if set
|
||||||
|
readOnly bool // if set FS is read only
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFS creates a new filing system and root directory
|
// NewFS creates a new filing system and root directory
|
||||||
@ -66,6 +67,13 @@ func (fsys *FS) NoChecksum() *FS {
|
|||||||
return fsys
|
return fsys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadOnly sets the fs into read only mode, returning EROFS for any
|
||||||
|
// write operations.
|
||||||
|
func (fsys *FS) ReadOnly() *FS {
|
||||||
|
fsys.readOnly = true
|
||||||
|
return fsys
|
||||||
|
}
|
||||||
|
|
||||||
// Root returns the root node
|
// Root returns the root node
|
||||||
func (fsys *FS) Root() (*Dir, error) {
|
func (fsys *FS) Root() (*Dir, error) {
|
||||||
// fs.Debugf(fsys.f, "Root()")
|
// fs.Debugf(fsys.f, "Root()")
|
||||||
|
Loading…
Reference in New Issue
Block a user