diff --git a/storage.go b/storage.go index e072dc9..aa5ef51 100644 --- a/storage.go +++ b/storage.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "strings" + "time" ) var ( @@ -120,7 +121,7 @@ func (s *Storage) Open(name string) (*File, error) { returnFile.Name = objectStat.Key returnFile.file = object } else { - if _, err := os.Stat(filepath.Join(s.config.Path, name)); err != nil && os.IsNotExist(err) { + if _, err := os.Stat(filepath.Join(s.config.Path, name)); err != nil && errors.Is(err, fs.ErrNotExist) { return nil, ErrFileNotFound } else if err != nil { return nil, err @@ -198,3 +199,49 @@ func (s *Storage) Delete(name string) error { return os.Remove(filepath.Join(s.config.Path, name)) } } + +type FileInfo struct { + Name string + Size int64 + ModTime time.Time + IsDir bool + Mode os.FileMode +} + +// Stat grabs the file info from the Storage interface. +// It takes a file name as its parameter. +// The function returns FileInfo, and an error, if any. +func (s *Storage) Stat(name string) (*FileInfo, error) { + fileInfo := new(FileInfo) + + if s.s3Client != nil { + objInfo, err := s.s3Client.StatObject(s.ctx, s.config.S3BucketName, name, minio.StatObjectOptions{}) + if err != nil { + errResp := minio.ToErrorResponse(err) + if errResp.StatusCode == http.StatusNotFound { + return nil, ErrFileNotFound + } else { + return nil, err + } + } + + fileInfo.Name = objInfo.Key + fileInfo.Size = objInfo.Size + fileInfo.ModTime = objInfo.LastModified + fileInfo.Mode = 0777 // Used as a fake perm. Doesn't actually do anything. + } else { + fInfo, err := os.Stat(filepath.Join(s.config.Path, name)) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return nil, ErrFileNotFound + } + return nil, err + } + fileInfo.Name = fInfo.Name() + fileInfo.Size = fInfo.Size() + fileInfo.ModTime = fInfo.ModTime() + fileInfo.Mode = fInfo.Mode() + } + + return fileInfo, nil +} diff --git a/storage_test.go b/storage_test.go index 3fb3c0d..8313616 100644 --- a/storage_test.go +++ b/storage_test.go @@ -3,6 +3,7 @@ package fsys import ( "github.com/stretchr/testify/assert" "io" + "io/fs" "testing" ) @@ -18,6 +19,13 @@ func TestStorageLocal(t *testing.T) { err = stor.Write("test.txt", []byte("hi"), WriteOptions{}) assert.NoError(t, err) + t.Log("== Stat ==") + fileInfo, err := stor.Stat("test.txt") + assert.NoError(t, err) + assert.Equal(t, "test.txt", fileInfo.Name) + assert.Equal(t, int64(len("hi")), fileInfo.Size) + assert.Equal(t, fs.FileMode(0600), fileInfo.Mode) + t.Log("== Read ==") fileContent, err := stor.Read("test.txt") assert.NoError(t, err) @@ -56,6 +64,13 @@ func TestStorageS3(t *testing.T) { err = stor.Write("test.txt", []byte("hi"), WriteOptions{}) assert.NoError(t, err) + t.Log("== Stat ==") + fileInfo, err := stor.Stat("test.txt") + assert.NoError(t, err) + assert.Equal(t, "test.txt", fileInfo.Name) + assert.Equal(t, int64(len("hi")), fileInfo.Size) + assert.Equal(t, fs.FileMode(0777), fileInfo.Mode) + t.Log("== Read ==") fileContent, err := stor.Read("test.txt") assert.NoError(t, err)