diff --git a/internal/backend/azure/azure.go b/internal/backend/azure/azure.go index 1c844f97f..e09593fd6 100644 --- a/internal/backend/azure/azure.go +++ b/internal/backend/azure/azure.go @@ -188,11 +188,6 @@ func (be *Backend) IsPermanentError(err error) bool { return false } -// Join combines path components with slashes. -func (be *Backend) Join(p ...string) string { - return path.Join(p...) -} - func (be *Backend) Connections() uint { return be.connections } diff --git a/internal/backend/gs/gs.go b/internal/backend/gs/gs.go index b4d4ecfd4..ad50f194b 100644 --- a/internal/backend/gs/gs.go +++ b/internal/backend/gs/gs.go @@ -186,11 +186,6 @@ func (be *Backend) IsPermanentError(err error) bool { return false } -// Join combines path components with slashes. -func (be *Backend) Join(p ...string) string { - return path.Join(p...) -} - func (be *Backend) Connections() uint { return be.connections } diff --git a/internal/backend/local/local.go b/internal/backend/local/local.go index ff7e3d35d..8985ef4c4 100644 --- a/internal/backend/local/local.go +++ b/internal/backend/local/local.go @@ -37,7 +37,7 @@ func NewFactory() location.Factory { return location.NewLimitedBackendFactory("local", ParseConfig, location.NoPassword, limiter.WrapBackendConstructor(Create), limiter.WrapBackendConstructor(Open)) } -func open(ctx context.Context, cfg Config) (*Local, error) { +func open(cfg Config) (*Local, error) { l := layout.NewDefaultLayout(cfg.Path, filepath.Join) fi, err := fs.Stat(l.Filename(backend.Handle{Type: backend.ConfigFile})) @@ -52,17 +52,17 @@ func open(ctx context.Context, cfg Config) (*Local, error) { } // Open opens the local backend as specified by config. -func Open(ctx context.Context, cfg Config) (*Local, error) { +func Open(_ context.Context, cfg Config) (*Local, error) { debug.Log("open local backend at %v", cfg.Path) - return open(ctx, cfg) + return open(cfg) } // Create creates all the necessary files and directories for a new local // backend at dir. Afterwards a new config blob should be created. -func Create(ctx context.Context, cfg Config) (*Local, error) { +func Create(_ context.Context, cfg Config) (*Local, error) { debug.Log("create local backend at %v", cfg.Path) - be, err := open(ctx, cfg) + be, err := open(cfg) if err != nil { return nil, err } diff --git a/internal/backend/s3/s3.go b/internal/backend/s3/s3.go index 5ef952891..2176d289d 100644 --- a/internal/backend/s3/s3.go +++ b/internal/backend/s3/s3.go @@ -9,7 +9,6 @@ import ( "os" "path" "strings" - "time" "github.com/restic/restic/internal/backend" "github.com/restic/restic/internal/backend/layout" @@ -37,7 +36,7 @@ func NewFactory() location.Factory { return location.NewHTTPBackendFactory("s3", ParseConfig, location.NoPassword, Create, Open) } -func open(ctx context.Context, cfg Config, rt http.RoundTripper) (*Backend, error) { +func open(cfg Config, rt http.RoundTripper) (*Backend, error) { debug.Log("open, config %#v", cfg) if cfg.KeyID == "" && cfg.Secret.String() != "" { @@ -186,14 +185,14 @@ func getCredentials(cfg Config, tr http.RoundTripper) (*credentials.Credentials, // Open opens the S3 backend at bucket and region. The bucket is created if it // does not exist yet. -func Open(ctx context.Context, cfg Config, rt http.RoundTripper) (backend.Backend, error) { - return open(ctx, cfg, rt) +func Open(_ context.Context, cfg Config, rt http.RoundTripper) (backend.Backend, error) { + return open(cfg, rt) } // Create opens the S3 backend at bucket and region and creates the bucket if // it does not exist yet. func Create(ctx context.Context, cfg Config, rt http.RoundTripper) (backend.Backend, error) { - be, err := open(ctx, cfg, rt) + be, err := open(cfg, rt) if err != nil { return nil, errors.Wrap(err, "open") } @@ -249,78 +248,6 @@ func (be *Backend) IsPermanentError(err error) bool { return false } -// Join combines path components with slashes. -func (be *Backend) Join(p ...string) string { - return path.Join(p...) -} - -type fileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time - isDir bool -} - -func (fi *fileInfo) Name() string { return fi.name } // base name of the file -func (fi *fileInfo) Size() int64 { return fi.size } // length in bytes for regular files; system-dependent for others -func (fi *fileInfo) Mode() os.FileMode { return fi.mode } // file mode bits -func (fi *fileInfo) ModTime() time.Time { return fi.modTime } // modification time -func (fi *fileInfo) IsDir() bool { return fi.isDir } // abbreviation for Mode().IsDir() -func (fi *fileInfo) Sys() interface{} { return nil } // underlying data source (can return nil) - -// ReadDir returns the entries for a directory. -func (be *Backend) ReadDir(ctx context.Context, dir string) (list []os.FileInfo, err error) { - debug.Log("ReadDir(%v)", dir) - - // make sure dir ends with a slash - if dir[len(dir)-1] != '/' { - dir += "/" - } - - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - debug.Log("using ListObjectsV1(%v)", be.cfg.ListObjectsV1) - - for obj := range be.client.ListObjects(ctx, be.cfg.Bucket, minio.ListObjectsOptions{ - Prefix: dir, - Recursive: false, - UseV1: be.cfg.ListObjectsV1, - }) { - if obj.Err != nil { - return nil, err - } - - if obj.Key == "" { - continue - } - - name := strings.TrimPrefix(obj.Key, dir) - // Sometimes s3 returns an entry for the dir itself. Ignore it. - if name == "" { - continue - } - entry := &fileInfo{ - name: name, - size: obj.Size, - modTime: obj.LastModified, - } - - if name[len(name)-1] == '/' { - entry.isDir = true - entry.mode = os.ModeDir | 0755 - entry.name = name[:len(name)-1] - } else { - entry.mode = 0644 - } - - list = append(list, entry) - } - - return list, nil -} - func (be *Backend) Connections() uint { return be.cfg.Connections } @@ -518,40 +445,3 @@ func (be *Backend) Delete(ctx context.Context) error { // Close does nothing func (be *Backend) Close() error { return nil } - -// Rename moves a file based on the new layout l. -func (be *Backend) Rename(ctx context.Context, h backend.Handle, l layout.Layout) error { - debug.Log("Rename %v to %v", h, l) - oldname := be.Filename(h) - newname := l.Filename(h) - - if oldname == newname { - debug.Log(" %v is already renamed", newname) - return nil - } - - debug.Log(" %v -> %v", oldname, newname) - - src := minio.CopySrcOptions{ - Bucket: be.cfg.Bucket, - Object: oldname, - } - - dst := minio.CopyDestOptions{ - Bucket: be.cfg.Bucket, - Object: newname, - } - - _, err := be.client.CopyObject(ctx, dst, src) - if err != nil && be.IsNotExist(err) { - debug.Log("copy failed: %v, seems to already have been renamed", err) - return nil - } - - if err != nil { - debug.Log("copy failed: %v", err) - return err - } - - return be.client.RemoveObject(ctx, be.cfg.Bucket, oldname, minio.RemoveObjectOptions{}) -} diff --git a/internal/backend/sftp/sftp.go b/internal/backend/sftp/sftp.go index 8ac6781e9..0ecf7ae62 100644 --- a/internal/backend/sftp/sftp.go +++ b/internal/backend/sftp/sftp.go @@ -50,8 +50,6 @@ func NewFactory() location.Factory { return location.NewLimitedBackendFactory("sftp", ParseConfig, location.NoPassword, limiter.WrapBackendConstructor(Create), limiter.WrapBackendConstructor(Open)) } -const defaultLayout = "default" - func startClient(cfg Config) (*SFTP, error) { program, args, err := buildSSHCommand(cfg) if err != nil { @@ -145,7 +143,7 @@ func (r *SFTP) clientError() error { // Open opens an sftp backend as described by the config by running // "ssh" with the appropriate arguments (or cfg.Command, if set). -func Open(ctx context.Context, cfg Config) (*SFTP, error) { +func Open(_ context.Context, cfg Config) (*SFTP, error) { debug.Log("open backend with config %#v", cfg) sftp, err := startClient(cfg) @@ -154,10 +152,10 @@ func Open(ctx context.Context, cfg Config) (*SFTP, error) { return nil, err } - return open(ctx, sftp, cfg) + return open(sftp, cfg) } -func open(ctx context.Context, sftp *SFTP, cfg Config) (*SFTP, error) { +func open(sftp *SFTP, cfg Config) (*SFTP, error) { fi, err := sftp.c.Stat(sftp.Layout.Filename(backend.Handle{Type: backend.ConfigFile})) m := util.DeriveModesFromFileInfo(fi, err) debug.Log("using (%03O file, %03O dir) permissions", m.File, m.Dir) @@ -193,16 +191,6 @@ func (r *SFTP) mkdirAllDataSubdirs(ctx context.Context, nconn uint) error { return g.Wait() } -// ReadDir returns the entries for a directory. -func (r *SFTP) ReadDir(_ context.Context, dir string) ([]os.FileInfo, error) { - fi, err := r.c.ReadDir(dir) - - // sftp client does not specify dir name on error, so add it here - err = errors.Wrapf(err, "(%v)", dir) - - return fi, err -} - // IsNotExist returns true if the error is caused by a not existing file. func (r *SFTP) IsNotExist(err error) bool { return errors.Is(err, os.ErrNotExist) @@ -273,7 +261,7 @@ func Create(ctx context.Context, cfg Config) (*SFTP, error) { } // repurpose existing connection - return open(ctx, sftp, cfg) + return open(sftp, cfg) } func (r *SFTP) Connections() uint { @@ -290,12 +278,6 @@ func (r *SFTP) HasAtomicReplace() bool { return r.posixRename } -// Join joins the given paths and cleans them afterwards. This always uses -// forward slashes, which is required by sftp. -func Join(parts ...string) string { - return path.Clean(path.Join(parts...)) -} - // tempSuffix generates a random string suffix that should be sufficiently long // to avoid accidental conflicts func tempSuffix() string { @@ -560,9 +542,9 @@ func (r *SFTP) Close() error { } func (r *SFTP) deleteRecursive(ctx context.Context, name string) error { - entries, err := r.ReadDir(ctx, name) + entries, err := r.c.ReadDir(name) if err != nil { - return errors.Wrap(err, "ReadDir") + return errors.Wrapf(err, "ReadDir(%v)", name) } for _, fi := range entries {