-
Notifications
You must be signed in to change notification settings - Fork 0
/
driver.go
162 lines (135 loc) · 4.87 KB
/
driver.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright 2018 The goftp Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package ftp
import (
"errors"
"io"
"os"
"strings"
)
// FileInfo represents an file interface
type FileInfo interface {
os.FileInfo
Owner() string
Group() string
}
// Driver is an interface that you will implement to create a driver for your
// chosen persistence layer. The server will create a new instance of your
// driver for each client that connects and delegate to it as required.
//
// Note that if the driver also implements the Auth interface then
// this will be called instead of calling Options.Auth. This allows
// the Auth mechanism to change the driver configuration.
type Driver interface {
// params - a file path
// returns - a time indicating when the requested path was last modified
// - an error if the file doesn't exist or the user lacks
// permissions
Stat(*Context, string) (os.FileInfo, error)
// params - path, function on file or subdir found
// returns - error
// path
ListDir(*Context, string, func(os.FileInfo) error) error
// params - path
// returns - nil if the directory was deleted or any error encountered
DeleteDir(*Context, string) error
// params - path
// returns - nil if the file was deleted or any error encountered
DeleteFile(*Context, string) error
// params - from_path, to_path
// returns - nil if the file was renamed or any error encountered
Rename(*Context, string, string) error
// params - path
// returns - nil if the new directory was created or any error encountered
MakeDir(*Context, string) error
// params - path, filepos
// returns - a string containing the file data to send to the client
GetFile(*Context, string, int64) (int64, io.ReadCloser, error)
// params - destination path, an io.Reader containing the file data
// returns - the number of bytes written and the first error encountered while writing, if any.
PutFile(*Context, string, io.Reader, int64) (int64, error)
}
var _ Driver = &MultiDriver{}
// MultiDriver represents a composite driver
type MultiDriver struct {
drivers map[string]Driver
}
// NewMultiDriver creates a multi driver to combind multiple driver
func NewMultiDriver(drivers map[string]Driver) Driver {
return &MultiDriver{
drivers: drivers,
}
}
// Stat implements Driver
func (driver *MultiDriver) Stat(ctx *Context, path string) (os.FileInfo, error) {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(path, prefix) {
return driver.Stat(ctx, strings.TrimPrefix(path, prefix))
}
}
return nil, errors.New("not a file")
}
// ListDir implements Driver
func (driver *MultiDriver) ListDir(ctx *Context, path string, callback func(os.FileInfo) error) error {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(path, prefix) {
return driver.ListDir(ctx, strings.TrimPrefix(path, prefix), callback)
}
}
return errors.New("not a directory")
}
// DeleteDir implements Driver
func (driver *MultiDriver) DeleteDir(ctx *Context, path string) error {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(path, prefix) {
return driver.DeleteDir(ctx, strings.TrimPrefix(path, prefix))
}
}
return errors.New("not a directory")
}
// DeleteFile implements Driver
func (driver *MultiDriver) DeleteFile(ctx *Context, path string) error {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(path, prefix) {
return driver.DeleteFile(ctx, strings.TrimPrefix(path, prefix))
}
}
return errors.New("not a file")
}
// Rename implements Driver
func (driver *MultiDriver) Rename(ctx *Context, fromPath string, toPath string) error {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(fromPath, prefix) {
return driver.Rename(ctx, strings.TrimPrefix(fromPath, prefix), strings.TrimPrefix(toPath, prefix))
}
}
return errors.New("not a file")
}
// MakeDir implements Driver
func (driver *MultiDriver) MakeDir(ctx *Context, path string) error {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(path, prefix) {
return driver.MakeDir(ctx, strings.TrimPrefix(path, prefix))
}
}
return errors.New("not a directory")
}
// GetFile implements Driver
func (driver *MultiDriver) GetFile(ctx *Context, path string, offset int64) (int64, io.ReadCloser, error) {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(path, prefix) {
return driver.GetFile(ctx, strings.TrimPrefix(path, prefix), offset)
}
}
return 0, nil, errors.New("not a file")
}
// PutFile implements Driver
func (driver *MultiDriver) PutFile(ctx *Context, destPath string, data io.Reader, offset int64) (int64, error) {
for prefix, driver := range driver.drivers {
if strings.HasPrefix(destPath, prefix) {
return driver.PutFile(ctx, strings.TrimPrefix(destPath, prefix), data, offset)
}
}
return 0, errors.New("not a file")
}