alist/server/s3/utils.go

161 lines
3.7 KiB
Go

// Credits: https://pkg.go.dev/github.com/rclone/rclone@v1.65.2/cmd/serve/s3
// Package s3 implements a fake s3 server for alist
package s3
import (
"context"
"encoding/json"
"strings"
"github.com/Mikubill/gofakes3"
"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/fs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/internal/setting"
)
type Bucket struct {
Name string `json:"name"`
Path string `json:"path"`
}
func getAndParseBuckets() ([]Bucket, error) {
var res []Bucket
err := json.Unmarshal([]byte(setting.GetStr(conf.S3Buckets)), &res)
return res, err
}
func getBucketByName(name string) (Bucket, error) {
buckets, err := getAndParseBuckets()
if err != nil {
return Bucket{}, err
}
for _, b := range buckets {
if b.Name == name {
return b, nil
}
}
return Bucket{}, gofakes3.BucketNotFound(name)
}
func getDirEntries(path string) ([]model.Obj, error) {
ctx := context.Background()
meta, _ := op.GetNearestMeta(path)
fi, err := fs.Get(context.WithValue(ctx, "meta", meta), path, &fs.GetArgs{})
if errs.IsNotFoundError(err) {
return nil, gofakes3.ErrNoSuchKey
} else if err != nil {
return nil, gofakes3.ErrNoSuchKey
}
if !fi.IsDir() {
return nil, gofakes3.ErrNoSuchKey
}
dirEntries, err := fs.List(context.WithValue(ctx, "meta", meta), path, &fs.ListArgs{})
if err != nil {
return nil, err
}
return dirEntries, nil
}
// func getFileHashByte(node interface{}) []byte {
// b, err := hex.DecodeString(getFileHash(node))
// if err != nil {
// return nil
// }
// return b
// }
func getFileHash(node interface{}) string {
// var o fs.Object
// switch b := node.(type) {
// case vfs.Node:
// fsObj, ok := b.DirEntry().(fs.Object)
// if !ok {
// fs.Debugf("serve s3", "File uploading - reading hash from VFS cache")
// in, err := b.Open(os.O_RDONLY)
// if err != nil {
// return ""
// }
// defer func() {
// _ = in.Close()
// }()
// h, err := hash.NewMultiHasherTypes(hash.NewHashSet(hash.MD5))
// if err != nil {
// return ""
// }
// _, err = io.Copy(h, in)
// if err != nil {
// return ""
// }
// return h.Sums()[hash.MD5]
// }
// o = fsObj
// case fs.Object:
// o = b
// }
// hash, err := o.Hash(context.Background(), hash.MD5)
// if err != nil {
// return ""
// }
// return hash
return ""
}
func prefixParser(p *gofakes3.Prefix) (path, remaining string) {
idx := strings.LastIndexByte(p.Prefix, '/')
if idx < 0 {
return "", p.Prefix
}
return p.Prefix[:idx], p.Prefix[idx+1:]
}
// // FIXME this could be implemented by VFS.MkdirAll()
// func mkdirRecursive(path string, VFS *vfs.VFS) error {
// path = strings.Trim(path, "/")
// dirs := strings.Split(path, "/")
// dir := ""
// for _, d := range dirs {
// dir += "/" + d
// if _, err := VFS.Stat(dir); err != nil {
// err := VFS.Mkdir(dir, 0777)
// if err != nil {
// return err
// }
// }
// }
// return nil
// }
// func rmdirRecursive(p string, VFS *vfs.VFS) {
// dir := path.Dir(p)
// if !strings.ContainsAny(dir, "/\\") {
// // might be bucket(root)
// return
// }
// if _, err := VFS.Stat(dir); err == nil {
// err := VFS.Remove(dir)
// if err != nil {
// return
// }
// rmdirRecursive(dir, VFS)
// }
// }
func authlistResolver() map[string]string {
s3accesskeyid := setting.GetStr(conf.S3AccessKeyId)
s3secretaccesskey := setting.GetStr(conf.S3SecretAccessKey)
if s3accesskeyid == "" && s3secretaccesskey == "" {
return nil
}
authList := make(map[string]string)
authList[s3accesskeyid] = s3secretaccesskey
return authList
}