@@ -3,7 +3,7 @@ package s3afero
33import (
44 "crypto/md5"
55 "encoding/hex"
6- "fmt "
6+ "errors "
77 "io"
88 "log"
99 "os"
@@ -131,13 +131,12 @@ func (db *SingleBucketBackend) getBucketWithFilePrefixLocked(bucket string, pref
131131 }
132132
133133 if entry .IsDir () {
134- response .AddPrefix (path .Join (prefixPath , prefixPart ) )
134+ response .AddPrefix (path .Join (prefixPath , entry . Name ()) + "/" )
135135
136136 } else {
137137 size := entry .Size ()
138138 mtime := entry .ModTime ()
139-
140- meta , err := db .metaStore .loadMeta (bucket , objectPath , size , mtime )
139+ meta , err := db .ensureMeta (bucket , objectPath , size , mtime )
141140 if err != nil {
142141 return nil , err
143142 }
@@ -157,31 +156,25 @@ func (db *SingleBucketBackend) getBucketWithFilePrefixLocked(bucket string, pref
157156func (db * SingleBucketBackend ) getBucketWithArbitraryPrefixLocked (bucket string , prefix * gofakes3.Prefix ) (* gofakes3.ObjectList , error ) {
158157 response := gofakes3 .NewObjectList ()
159158
160- if err := afero .Walk (db .fs , filepath .FromSlash (bucket ), func (path string , info os.FileInfo , err error ) error {
159+ if err := afero .Walk (db .fs , filepath .FromSlash ("." ), func (path string , info os.FileInfo , err error ) error {
161160 if err != nil || info .IsDir () {
162161 return err
163162 }
164163
165164 objectPath := filepath .ToSlash (path )
166- parts := strings .SplitN (objectPath , "/" , 2 )
167- if len (parts ) != 2 {
168- panic (fmt .Errorf ("unexpected path %q" , path )) // should never happen
169- }
170- objectName := parts [1 ]
171-
172- if ! prefix .Match (objectName , nil ) {
165+ if ! prefix .Match (objectPath , nil ) {
173166 return nil
174167 }
175168
176169 size := info .Size ()
177170 mtime := info .ModTime ()
178- meta , err := db .metaStore . loadMeta (bucket , objectName , size , mtime )
171+ meta , err := db .ensureMeta (bucket , objectPath , size , mtime )
179172 if err != nil {
180173 return err
181174 }
182175
183176 response .Add (& gofakes3.Content {
184- Key : objectName ,
177+ Key : objectPath ,
185178 LastModified : gofakes3 .NewContentTime (mtime ),
186179 ETag : `"` + hex .EncodeToString (meta .Hash ) + `"` ,
187180 Size : size ,
@@ -196,6 +189,46 @@ func (db *SingleBucketBackend) getBucketWithArbitraryPrefixLocked(bucket string,
196189 return response , nil
197190}
198191
192+ func (db * SingleBucketBackend ) ensureMeta (
193+ bucket string ,
194+ objectPath string ,
195+ size int64 ,
196+ mtime time.Time ,
197+ ) (meta * Metadata , err error ) {
198+ existingMeta , err := db .metaStore .loadMeta (bucket , objectPath , size , mtime )
199+ if errors .Is (err , os .ErrNotExist ) {
200+ f , err := db .fs .Open (filepath .FromSlash (objectPath ))
201+ if err != nil {
202+ return nil , err
203+ }
204+ defer f .Close ()
205+
206+ hasher := md5 .New ()
207+ if _ , err := io .Copy (hasher , f ); err != nil {
208+ return nil , err
209+ }
210+
211+ hash , err := hasher .Sum (nil ), nil
212+ if err != nil {
213+ return nil , err
214+ }
215+
216+ return & Metadata {
217+ objectPath ,
218+ mtime ,
219+ size ,
220+ hash ,
221+ map [string ]string {},
222+ }, nil
223+
224+ } else if err != nil {
225+ return nil , err
226+
227+ } else {
228+ return existingMeta , nil
229+ }
230+ }
231+
199232func (db * SingleBucketBackend ) HeadObject (bucketName , objectName string ) (* gofakes3.Object , error ) {
200233 if bucketName != db .name {
201234 return nil , gofakes3 .BucketNotFound (bucketName )
@@ -209,11 +242,12 @@ func (db *SingleBucketBackend) HeadObject(bucketName, objectName string) (*gofak
209242 return nil , gofakes3 .KeyNotFound (objectName )
210243 } else if err != nil {
211244 return nil , err
245+ } else if stat .IsDir () {
246+ return nil , gofakes3 .KeyNotFound (objectName )
212247 }
213248
214249 size , mtime := stat .Size (), stat .ModTime ()
215-
216- meta , err := db .metaStore .loadMeta (bucketName , objectName , size , mtime )
250+ meta , err := db .ensureMeta (bucketName , objectName , size , mtime )
217251 if err != nil {
218252 return nil , err
219253 }
@@ -242,7 +276,6 @@ func (db *SingleBucketBackend) GetObject(bucketName, objectName string, rangeReq
242276 } else if err != nil {
243277 return nil , err
244278 }
245-
246279 defer func () {
247280 // If an error occurs, the caller may not have access to Object.Body in order to close it:
248281 if err != nil && obj == nil {
@@ -253,6 +286,8 @@ func (db *SingleBucketBackend) GetObject(bucketName, objectName string, rangeReq
253286 stat , err := f .Stat ()
254287 if err != nil {
255288 return nil , err
289+ } else if stat .IsDir () {
290+ return nil , gofakes3 .KeyNotFound (objectName )
256291 }
257292
258293 size , mtime := stat .Size (), stat .ModTime ()
@@ -270,7 +305,7 @@ func (db *SingleBucketBackend) GetObject(bucketName, objectName string, rangeReq
270305 rdr = limitReadCloser (rdr , f .Close , rnge .Length )
271306 }
272307
273- meta , err := db .metaStore . loadMeta (bucketName , objectName , size , mtime )
308+ meta , err := db .ensureMeta (bucketName , objectName , size , mtime )
274309 if err != nil {
275310 return nil , err
276311 }
@@ -387,6 +422,10 @@ func (db *SingleBucketBackend) DeleteMulti(bucketName string, objects ...string)
387422 return result , nil
388423}
389424
425+ func (db * SingleBucketBackend ) CopyObject (srcBucket , srcKey , dstBucket , dstKey string , meta map [string ]string ) (result gofakes3.CopyObjectResult , err error ) {
426+ return gofakes3 .CopyObject (db , srcBucket , srcKey , dstBucket , dstKey , meta )
427+ }
428+
390429func (db * SingleBucketBackend ) DeleteObject (bucketName , objectName string ) (result gofakes3.ObjectDeleteResult , rerr error ) {
391430 if bucketName != db .name {
392431 return result , gofakes3 .BucketNotFound (bucketName )
0 commit comments