package main import ( "context" "errors" "io" "log" "os" "path" "strings" "time" "github.com/minio/minio-go/v7" "golang.org/x/net/webdav" ) /* * S3FS lifetime is limited to a single request * Conversely, Golang's abstraction has been thought to be shared between users * Sharing an instance between users would be very dangerous (as we would need many checks between shared values) */ type S3FS struct { cache map[string]*S3Stat mc *minio.Client ctx context.Context } func NewS3FS(mc *minio.Client) S3FS { return S3FS{ cache: make(map[string]*S3Stat), mc: mc, } } func (s S3FS) Mkdir(ctx context.Context, name string, perm os.FileMode) error { s.ctx = ctx p := NewS3Path(name) if p.class == ROOT { return errors.New("Unable to create another root folder") } else if p.class == BUCKET { log.Println("Creating bucket is not implemented yet") return nil } f, err := NewS3File(&s, path.Join(name, ".bagage")) if err != nil { return err } defer f.Close() _, err = io.Copy(f, strings.NewReader("This is a placeholder")) return nil } func (s S3FS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) { s.ctx = ctx // If the file does not exist when opening it, we create a stub if _, ok := s.cache[name]; !ok { st := new(S3Stat) st.fs = &s st.path = NewS3Path(name) st.path.class = OBJECT st.obj.Key = st.path.key st.obj.LastModified = time.Now() s.cache[name] = st } return NewS3File(&s, name) } func (s S3FS) RemoveAll(ctx context.Context, name string) error { //@FIXME nautilus deletes files one by one, at the end, it does not find its folder as it is "already deleted" s.ctx = ctx p := NewS3Path(name) if p.class == ROOT { return errors.New("Unable to create another root folder") } else if p.class == BUCKET { log.Println("Deleting bucket is not implemented yet") return nil } objCh := s.mc.ListObjects(s.ctx, p.bucket, minio.ListObjectsOptions{Prefix: p.key, Recursive: true}) rmCh := s.mc.RemoveObjects(s.ctx, p.bucket, objCh, minio.RemoveObjectsOptions{}) for rErr := range rmCh { return rErr.Err } return nil } func (s S3FS) Rename(ctx context.Context, oldName, newName string) error { s.ctx = ctx return errors.New("Not implemented Rename") } func (s S3FS) Stat(ctx context.Context, name string) (os.FileInfo, error) { s.ctx = ctx return NewS3Stat(&s, name) }