-
Notifications
You must be signed in to change notification settings - Fork 0
/
basic.go
140 lines (114 loc) · 3.78 KB
/
basic.go
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
129
130
131
132
133
134
135
136
137
138
139
140
// basic.go implements the interface billy.Basic
package main
import (
"context"
"errors"
"fmt"
"os"
"path"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/go-git/go-billy/v5"
)
const (
O_RDONLY int = os.O_RDONLY // open the file read-only.
O_WRONLY int = os.O_WRONLY // open the file write-only.
O_WRMULTIPART int = 0x4 // open the file for write-only using multipart upload.
SupportedOFlags = O_RDONLY | O_WRONLY | O_WRMULTIPART // supported open flags for s3fs
)
var (
ErrOpenFlagNotSupported = errors.New("open flag not supported")
)
// Create implements billy.Basic
// Create creates the named file with mode 0666 (before umask), truncating
// it if it already exists. If successful, methods on the returned File can
// be used for I/O; the associated file descriptor has mode O_RDWR.
func (fs3 *S3FS) Create(filename string) (billy.File, error) {
return fs3.OpenFile(filename, O_WRONLY, 0666)
}
// Open opens the named file for reading. If successful, methods on the
// returned file can be used for reading; the associated file descriptor has
// mode O_RDONLY.
func (fs3 *S3FS) Open(filename string) (billy.File, error) {
return fs3.OpenFile(filename, O_RDONLY, 0666)
}
// OpenFile is the generalized open call; most users will use Open or Create
// instead. It opens the named file with specified flag (O_RDONLY etc.) and
// perm, (0666 etc.) if applicable. If successful, methods on the returned
// File can be used for I/O.
func (fs3 *S3FS) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
// Is the supplied flag supported?
if flag&SupportedOFlags != flag {
return nil, errors.New("unsupported open flag")
}
// Get the file path
p := path.Join(fs3.root, filename)
switch flag & SupportedOFlags {
case O_RDONLY:
return newS3ReadFile(fs3.client, fs3.bucket, p)
case O_WRONLY:
return newS3WriteFile(fs3.client, fs3.bucket, p)
case O_WRMULTIPART:
return newS3MultipartUploadFile(fs3.client, fs3.bucket, p)
default:
return nil, errors.New("unsupported open flag")
}
}
// Stat returns a FileInfo describing the named file.
func (fs3 *S3FS) Stat(filename string) (os.FileInfo, error) {
return nil, errors.New("not implemented")
}
// Rename renames (moves) oldpath to newpath. If newpath already exists and
// is not a directory, Rename replaces it. OS-specific restrictions may
// apply when oldpath and newpath are in different directories.
func (fs3 *S3FS) Rename(oldpath, newpath string) error {
// TODO: Validate the paths?
// Create a context
ctx := context.TODO() // TODO: Get user-supplied context?
// Format the paths
src := path.Join(fs3.root, oldpath)
dst := path.Join(fs3.root, newpath)
// Send the copy request
_, err := fs3.client.CopyObject(ctx, &s3.CopyObjectInput{
Bucket: &fs3.bucket,
CopySource: &src,
Key: &dst,
})
if err != nil {
return fmt.Errorf("failed to rename file: %s", err)
}
// Delete the old file
// TODO: Parse the response?
_, err = fs3.client.DeleteObject(ctx, &s3.DeleteObjectInput{
Bucket: &fs3.bucket,
Key: &src,
})
if err != nil {
return fmt.Errorf("failed to remove file: %s", err)
}
return nil
}
// Remove removes the named file or directory.
func (fs3 *S3FS) Remove(filename string) error {
// TODO: Validate the path?
// ...
// Create a context
ctx := context.TODO() // TODO: Get user-supplied context?
// Format the path
p := path.Join(fs3.root, filename)
// Send the request
// TODO: Parse the response?
_, err := fs3.client.DeleteObject(ctx, &s3.DeleteObjectInput{
Bucket: &fs3.bucket,
Key: &p,
})
if err != nil {
return fmt.Errorf("failed to remove file: %s", err)
}
return nil
}
// Join joins any number of path elements into a single path
func (fs3 *S3FS) Join(elem ...string) string {
j := path.Join(elem...)
c := path.Clean(j)
return c
}