1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
package s3
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
}
|