Bagage is the bridge between our users and garage, it enables them to synchronize files that matter for them from their computer to garage through WebDAV
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

128 lines
2.2 KiB

package main
import (
"errors"
"io/fs"
"path"
"time"
"github.com/minio/minio-go/v7"
)
type S3Stat struct {
fs *S3FS
obj minio.ObjectInfo
path S3Path
}
/*
* Stat a path knowing its ObjectInfo
*/
func NewS3StatFromObjectInfo(fs *S3FS, bucket string, obj minio.ObjectInfo) (*S3Stat, error) {
s := new(S3Stat)
s.path = NewTrustedS3Path(bucket, obj)
s.obj = obj
s.fs = fs
fs.cache[s.path.path] = s
return s, nil
}
/*
* Stat a path without additional information
*/
func NewS3Stat(fs *S3FS, path string) (*S3Stat, error) {
cache := fs.cache
if entry, ok := cache[path]; ok {
return entry, nil
}
s := new(S3Stat)
s.fs = fs
s.path = NewS3Path(path)
if err := s.Refresh(); err != nil {
return nil, err
}
if s.path.class&OPAQUE_KEY != 0 {
return nil, errors.New("Failed to precisely determine the key type, this a logic error.")
}
cache[path] = s
cache[s.path.path] = s
return s, nil
}
func (s *S3Stat) Refresh() error {
if s.path.class == ROOT || s.path.class == BUCKET {
return nil
}
mc := s.fs.mc
// Compute the prefix to have the desired behaviour for our stat logic
prefix := s.path.key
if prefix[len(prefix)-1:] == "/" {
prefix = prefix[:len(prefix)-1]
}
// Get info and check if the key exists
objs_info := mc.ListObjects(s.fs.ctx, s.path.bucket, minio.ListObjectsOptions{
Prefix: prefix,
Recursive: false,
})
found := false
for object := range objs_info {
if object.Err != nil {
return object.Err
}
if object.Key == prefix || object.Key == prefix+"/" {
s.obj = object
s.path = NewTrustedS3Path(s.path.bucket, object)
found = true
break
}
}
if !found {
return fs.ErrNotExist
}
return nil
}
func (s *S3Stat) Name() string {
if s.path.class == ROOT {
return "/"
} else if s.path.class == BUCKET {
return s.path.bucket
} else {
return path.Base(s.path.key)
}
}
func (s *S3Stat) Size() int64 {
return s.obj.Size
}
func (s *S3Stat) Mode() fs.FileMode {
if s.path.class == OBJECT {
return fs.ModePerm
} else {
return fs.ModeDir | fs.ModePerm
}
}
func (s *S3Stat) ModTime() time.Time {
return s.obj.LastModified
}
func (s *S3Stat) IsDir() bool {
return s.path.class != OBJECT
}
func (s *S3Stat) Sys() interface{} {
return nil
}