afero/rclonefs/fs.go

203 lines
3.6 KiB
Go
Raw Normal View History

2022-08-18 11:44:33 +03:00
package rclonefs
import (
"context"
2022-08-20 19:59:01 +03:00
"errors"
2022-08-20 11:18:41 +03:00
"io/fs"
2022-08-18 16:15:38 +03:00
"os"
2022-08-18 11:44:33 +03:00
"os/user"
"path/filepath"
2022-08-20 21:51:57 +03:00
"sort"
2022-08-18 11:44:33 +03:00
"strings"
2022-08-18 16:15:38 +03:00
"time"
2022-08-18 11:44:33 +03:00
_ "github.com/rclone/rclone/backend/all"
2022-08-20 11:18:41 +03:00
rclfs "github.com/rclone/rclone/fs"
2022-08-18 11:44:33 +03:00
"github.com/rclone/rclone/fs/config"
"github.com/rclone/rclone/fs/config/configfile"
"github.com/rclone/rclone/vfs"
2022-08-18 16:15:38 +03:00
"github.com/spf13/afero"
2022-08-18 11:44:33 +03:00
)
type RCFS struct {
2022-08-18 16:15:38 +03:00
Fs *vfs.VFS
Cwd string
2022-08-18 11:44:33 +03:00
}
2022-08-18 12:00:12 +03:00
func CreateRCFS(path string) (*RCFS, error) {
2022-08-18 11:44:33 +03:00
u, e := user.Current()
if e != nil {
return nil, e
}
cfgpath := filepath.Join(u.HomeDir, ".config/rclone/rclone.conf")
e = config.SetConfigPath(cfgpath)
if e != nil {
return nil, e
}
configfile.Install()
rootdir, cwd, _ := strings.Cut(path, ":")
rootdir += ":"
2022-08-20 11:18:41 +03:00
cwd = filepath.Join("/", cwd)
2022-08-18 11:44:33 +03:00
2022-08-20 11:18:41 +03:00
rfs, e := rclfs.NewFs(context.Background(), rootdir)
2022-08-18 11:44:33 +03:00
if e != nil {
return nil, e
}
vfs := vfs.New(rfs, nil)
return &RCFS{Fs: vfs, Cwd: cwd}, nil
}
2022-08-18 16:15:38 +03:00
func (rcfs *RCFS) AbsPath(name string) string {
if !filepath.IsAbs(name) {
name = filepath.Join(rcfs.Cwd, name)
}
return name
}
func (rcfs *RCFS) Name() string { return "RClone virtual filesystem" }
func (rcfs *RCFS) Create(name string) (afero.File, error) {
name = rcfs.AbsPath(name)
return rcfs.Fs.Create(name)
}
func (rcfs *RCFS) Mkdir(name string, perm os.FileMode) error {
2022-08-20 21:51:57 +03:00
name = rcfs.AbsPath(name)
return rcfs.Fs.Mkdir(name, perm)
2022-08-18 16:15:38 +03:00
}
func (rcfs *RCFS) MkdirAll(name string, perm os.FileMode) error {
2022-08-21 09:07:08 +03:00
name = rcfs.AbsPath(name)
name = strings.Trim(name, "/")
var (
front string = "/"
current string
back string
ok bool
)
for {
current, back, ok = strings.Cut(name, "/")
if !ok {
front = front + name
if e := rcfs.Fs.Mkdir(front, perm); e != nil && !os.IsExist(e) {
return e
}
break
}
front = front + current + "/"
if e := rcfs.Fs.Mkdir(front, perm); e != nil && !os.IsExist(e) {
return e
}
name = back
}
2022-08-18 16:15:38 +03:00
return nil
}
func (rcfs *RCFS) Open(name string) (afero.File, error) {
name = rcfs.AbsPath(name)
f, e := rcfs.Fs.Open(name)
if f == nil {
return nil, e
}
return f, e
}
func (rcfs *RCFS) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) {
name = rcfs.AbsPath(name)
return rcfs.Fs.OpenFile(name, flag, perm)
}
func (rcfs *RCFS) Stat(name string) (os.FileInfo, error) {
name = rcfs.AbsPath(name)
return rcfs.Fs.Stat(name)
}
func (rcfs *RCFS) Remove(name string) error {
name = rcfs.AbsPath(name)
return rcfs.Fs.Remove(name)
}
func (rcfs *RCFS) RemoveAll(path string) error {
2022-08-20 11:18:41 +03:00
path = rcfs.AbsPath(path)
2022-08-20 21:51:57 +03:00
fileList := make([]string, 0)
dirList := make([]string, 0)
e := afero.Walk(rcfs, path, func(path string, info fs.FileInfo, err error) error {
2022-08-20 12:16:05 +03:00
if err != nil {
return err
}
if info.IsDir() {
2022-08-20 21:51:57 +03:00
dirList = append(dirList, path)
2022-08-20 12:16:05 +03:00
} else {
2022-08-20 21:51:57 +03:00
fileList = append(fileList, path)
2022-08-20 12:16:05 +03:00
}
2022-08-20 21:51:57 +03:00
return nil
2022-08-20 12:16:05 +03:00
})
2022-08-20 11:18:41 +03:00
2022-08-20 21:51:57 +03:00
if e != nil {
return e
}
for _, f := range fileList {
if e := rcfs.Remove(f); e != nil {
return e
2022-08-20 13:21:54 +03:00
}
2022-08-20 21:51:57 +03:00
}
sort.Slice(dirList, func(i, j int) bool {
return len(dirList[i]) > len(dirList[j])
})
2022-08-20 13:21:54 +03:00
2022-08-20 21:51:57 +03:00
for _, d := range dirList {
if e := rcfs.Remove(d); e != nil {
return e
}
2022-08-20 13:21:54 +03:00
}
2022-08-20 21:51:57 +03:00
rcfs.Remove(path)
2022-08-18 16:15:38 +03:00
return nil
}
func (rcfs *RCFS) Rename(oldname, newname string) error {
oldname = rcfs.AbsPath(oldname)
newname = rcfs.AbsPath(newname)
return rcfs.Fs.Rename(oldname, newname)
}
func (rcfs *RCFS) Chmod(name string, mode os.FileMode) error {
2022-08-20 19:59:01 +03:00
return errors.New("Chmod is not supported")
2022-08-18 16:15:38 +03:00
}
func (rcfs *RCFS) Chown(name string, uid, gid int) error {
2022-08-20 19:59:01 +03:00
return errors.New("Chown is not supported")
2022-08-18 16:15:38 +03:00
}
func (rcfs *RCFS) Chtimes(name string, atime time.Time, mtime time.Time) error {
name = rcfs.AbsPath(name)
return rcfs.Fs.Chtimes(name, atime, mtime)
}