summaryrefslogtreecommitdiff
path: root/file.go
diff options
context:
space:
mode:
authorMarin Ivanov <[email protected]>2022-08-15 03:17:26 +0300
committerMarin Ivanov <[email protected]>2022-08-15 03:17:26 +0300
commit2f1bb584258c53d74f97b04a6045f0e0b838f061 (patch)
tree21665e0e5699b55cb28ff413523e4d477998a545 /file.go
parentb135dcf644394394e3250188dea39ff4e91f0e06 (diff)
Add object writing and directory listing
Diffstat (limited to 'file.go')
-rw-r--r--file.go90
1 files changed, 82 insertions, 8 deletions
diff --git a/file.go b/file.go
index 2498bd8..0a7a3e5 100644
--- a/file.go
+++ b/file.go
@@ -5,25 +5,42 @@ import (
"io"
"os"
"path"
+
+ "github.com/minio/minio-go/v7"
)
type File struct {
fs *Fs
key string
- r io.ReadCloser
+ r io.ReadSeekCloser
w io.WriteCloser
+ werrc <-chan error
cancel context.CancelFunc
}
// implements io.Closer
func (f *File) Close() error {
- f.cancel()
+ defer f.cancel()
+ if f.r != nil {
+ return f.r.Close()
+ }
+ if f.w != nil {
+ f.w.Close()
+ return <-f.werrc
+ }
return nil
}
// implements io.Reader
func (f *File) Read(b []byte) (int, error) {
- return f.r.Read(b)
+ if f.r == nil {
+ return 0, ErrUnsupported
+ }
+ n, err := f.r.Read(b)
+ if err != nil {
+ return n, transformError(err)
+ }
+ return n, nil
}
// implements io.ReaderAt
@@ -33,7 +50,15 @@ func (f *File) ReadAt(p []byte, off int64) (int, error) {
// implements io.Writer
func (f *File) Write(p []byte) (int, error) {
- return f.w.Write(p)
+ if f.w == nil {
+ return 0, ErrUnsupported
+ }
+
+ n, err := f.w.Write(p)
+ if err != nil {
+ return n, transformError(err)
+ }
+ return n, nil
}
// implements io.WriterAt
@@ -45,16 +70,65 @@ func (f *File) Name() string {
return path.Base(f.key)
}
+func (f *File) readdir(count int, onlyDir bool) ([]os.FileInfo, error) {
+ if !isDirPath(f.key) {
+ return nil, ErrUnsupported
+ }
+ if count == 0 {
+ return []os.FileInfo{}, nil
+ }
+ ctx, cancel := f.fs.contextWithTimeout()
+ defer cancel()
+ objectsCh := f.fs.client.ListObjects(ctx, f.fs.bucket, minio.ListObjectsOptions{Prefix: f.key})
+ n := 0
+ lastDir := f.key
+ results := make([]os.FileInfo, 0)
+ for objectInfo := range objectsCh {
+ base := path.Base(objectInfo.Key)
+ dir := path.Dir(objectInfo.Key) + "/"
+ if lastDir != dir {
+ lastDir = dir
+ results = append(results, &FileInfo{
+ name: base,
+ isDir: true,
+ })
+ if onlyDir {
+ n += 1
+ }
+ }
+ if !onlyDir {
+ results = append(results, transformObjectInfo(objectInfo))
+ n += 1
+ }
+ if n > count {
+ break
+ }
+ }
+
+ return results, nil
+}
+
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
- panic("not implemented")
+ return f.readdir(count, false)
}
func (f *File) Readdirnames(n int) ([]string, error) {
- panic("not implemented")
+ results, err := f.readdir(n, true)
+ if err != nil {
+ return nil, err
+ }
+ list := make([]string, 0, len(results))
+ for _, info := range results {
+ list = append(list, info.Name())
+ }
+ return list, nil
}
func (f *File) Seek(offset int64, whence int) (int64, error) {
- panic("not implemented")
+ if f.r == nil {
+ return 0, ErrUnsupported
+ }
+ return f.r.Seek(offset, whence)
}
func (f *File) Stat() (os.FileInfo, error) {
@@ -70,5 +144,5 @@ func (f *File) Truncate(size int64) error {
}
func (f *File) WriteString(s string) (ret int, err error) {
- panic("not implemented")
+ return f.Write([]byte(s))
}