123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- //go:build unix
- package nfs
- import (
- "os"
- "path"
- "strings"
- "time"
- billy "github.com/go-git/go-billy/v5"
- "github.com/rclone/rclone/fs"
- "github.com/rclone/rclone/vfs"
- "github.com/rclone/rclone/vfs/vfscommon"
- )
- // FS is our wrapper around the VFS to properly support billy.Filesystem interface
- type FS struct {
- vfs *vfs.VFS
- }
- // ReadDir implements read dir
- func (f *FS) ReadDir(path string) (dir []os.FileInfo, err error) {
- fs.Debugf("nfs", "ReadDir %v", path)
- return f.vfs.ReadDir(path)
- }
- // Create implements creating new files
- func (f *FS) Create(filename string) (billy.File, error) {
- fs.Debugf("nfs", "Create %v", filename)
- return f.vfs.Create(filename)
- }
- // Open opens a file
- func (f *FS) Open(filename string) (billy.File, error) {
- file, err := f.vfs.Open(filename)
- fs.Debugf("nfs", "Open %v file: %v err: %v", filename, file, err)
- return file, err
- }
- // OpenFile opens a file
- func (f *FS) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
- file, err := f.vfs.OpenFile(filename, flag, perm)
- fs.Debugf("nfs", "OpenFile %v flag: %v perm: %v file: %v err: %v", filename, flag, perm, file, err)
- return file, err
- }
- // Stat gets the file stat
- func (f *FS) Stat(filename string) (os.FileInfo, error) {
- node, err := f.vfs.Stat(filename)
- fs.Debugf("nfs", "Stat %v node: %v err: %v", filename, node, err)
- return node, err
- }
- // Rename renames a file
- func (f *FS) Rename(oldpath, newpath string) error {
- return f.vfs.Rename(oldpath, newpath)
- }
- // Remove deletes a file
- func (f *FS) Remove(filename string) error {
- return f.vfs.Remove(filename)
- }
- // Join joins path elements
- func (f *FS) Join(elem ...string) string {
- return path.Join(elem...)
- }
- // TempFile is not implemented
- func (f *FS) TempFile(dir, prefix string) (billy.File, error) {
- return nil, os.ErrInvalid
- }
- // MkdirAll creates a directory and all the ones above it
- // it does not redirect to VFS.MkDirAll because that one doesn't
- // honor the permissions
- func (f *FS) MkdirAll(filename string, perm os.FileMode) error {
- parts := strings.Split(filename, "/")
- for i := range parts {
- current := strings.Join(parts[:i+1], "/")
- _, err := f.Stat(current)
- if err == vfs.ENOENT {
- err = f.vfs.Mkdir(current, perm)
- if err != nil {
- return err
- }
- }
- }
- return nil
- }
- // Lstat gets the stats for symlink
- func (f *FS) Lstat(filename string) (os.FileInfo, error) {
- node, err := f.vfs.Stat(filename)
- fs.Debugf("nfs", "Lstat %v node: %v err: %v", filename, node, err)
- return node, err
- }
- // Symlink is not supported over NFS
- func (f *FS) Symlink(target, link string) error {
- return os.ErrInvalid
- }
- // Readlink is not supported
- func (f *FS) Readlink(link string) (string, error) {
- return "", os.ErrInvalid
- }
- // Chmod changes the file modes
- func (f *FS) Chmod(name string, mode os.FileMode) error {
- file, err := f.vfs.Open(name)
- if err != nil {
- return err
- }
- defer func() {
- if err := file.Close(); err != nil {
- fs.Logf(f, "Error while closing file: %e", err)
- }
- }()
- return file.Chmod(mode)
- }
- // Lchown changes the owner of symlink
- func (f *FS) Lchown(name string, uid, gid int) error {
- return f.Chown(name, uid, gid)
- }
- // Chown changes owner of the file
- func (f *FS) Chown(name string, uid, gid int) error {
- file, err := f.vfs.Open(name)
- if err != nil {
- return err
- }
- defer func() {
- if err := file.Close(); err != nil {
- fs.Logf(f, "Error while closing file: %e", err)
- }
- }()
- return file.Chown(uid, gid)
- }
- // Chtimes changes the acces time and modified time
- func (f *FS) Chtimes(name string, atime time.Time, mtime time.Time) error {
- return f.vfs.Chtimes(name, atime, mtime)
- }
- // Chroot is not supported in VFS
- func (f *FS) Chroot(path string) (billy.Filesystem, error) {
- return nil, os.ErrInvalid
- }
- // Root returns the root of a VFS
- func (f *FS) Root() string {
- return f.vfs.Fs().Root()
- }
- // Capabilities exports the filesystem capabilities
- func (f *FS) Capabilities() billy.Capability {
- if f.vfs.Opt.CacheMode == vfscommon.CacheModeOff {
- return billy.ReadCapability | billy.SeekCapability
- }
- return billy.WriteCapability | billy.ReadCapability |
- billy.ReadAndWriteCapability | billy.SeekCapability | billy.TruncateCapability
- }
- // Interface check
- var _ billy.Filesystem = (*FS)(nil)
|