From eb4099debda21626afe4ef31bff65b0d4a6ee131 Mon Sep 17 00:00:00 2001 From: Frederik Ring Date: Thu, 27 Feb 2025 13:55:14 +0100 Subject: [PATCH] Paths are joined with client side separators when targeting remotes (#547) Currently, filepath.Join is used to join path fragments that are supposed to be created on remote storage backends. This could theoretically cause problems when the separators used by the client and the remotes do not match. It's unlikely this causes problems right now, but it's definitely better to rectify it before it causes further confusion. This was raised in #541 --- internal/storage/azure/azure.go | 5 +++-- internal/storage/dropbox/dropbox.go | 5 ++--- internal/storage/s3/s3.go | 5 ++--- internal/storage/ssh/ssh.go | 5 ++--- internal/storage/webdav/webdav.go | 5 ++--- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/internal/storage/azure/azure.go b/internal/storage/azure/azure.go index 3e0d88a6..6d7dde3f 100644 --- a/internal/storage/azure/azure.go +++ b/internal/storage/azure/azure.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "os" + "path" "path/filepath" "strings" "sync" @@ -128,7 +129,7 @@ func (b *azureBlobStorage) Copy(file string) error { _, err = b.client.UploadStream( context.Background(), b.containerName, - filepath.Join(b.DestinationPath, filepath.Base(file)), + path.Join(b.DestinationPath, filepath.Base(file)), fileReader, b.uploadStreamOptions, ) @@ -141,7 +142,7 @@ func (b *azureBlobStorage) Copy(file string) error { // Prune rotates away backups according to the configuration and provided // deadline for the Azure Blob storage backend. func (b *azureBlobStorage) Prune(deadline time.Time, pruningPrefix string) (*storage.PruneStats, error) { - lookupPrefix := filepath.Join(b.DestinationPath, pruningPrefix) + lookupPrefix := path.Join(b.DestinationPath, pruningPrefix) pager := b.client.NewListBlobsFlatPager(b.containerName, &container.ListBlobsFlatOptions{ Prefix: &lookupPrefix, }) diff --git a/internal/storage/dropbox/dropbox.go b/internal/storage/dropbox/dropbox.go index 1a58a59b..42a39d92 100644 --- a/internal/storage/dropbox/dropbox.go +++ b/internal/storage/dropbox/dropbox.go @@ -7,7 +7,6 @@ import ( "net/url" "os" "path" - "path/filepath" "strings" "sync" "time" @@ -195,7 +194,7 @@ loop: _, err = b.client.UploadSessionFinish( files.NewUploadSessionFinishArg( files.NewUploadSessionCursor(sessionId, 0), - files.NewCommitInfo(filepath.Join(b.DestinationPath, name)), + files.NewCommitInfo(path.Join(b.DestinationPath, name)), ), nil) if err != nil { return errwrap.Wrap(err, "error finishing the upload session") @@ -247,7 +246,7 @@ func (b *dropboxStorage) Prune(deadline time.Time, pruningPrefix string) (*stora pruneErr := b.DoPrune(b.Name(), len(matches), lenCandidates, deadline, func() error { for _, match := range matches { - if _, err := b.client.DeleteV2(files.NewDeleteArg(filepath.Join(b.DestinationPath, match.Name))); err != nil { + if _, err := b.client.DeleteV2(files.NewDeleteArg(path.Join(b.DestinationPath, match.Name))); err != nil { return errwrap.Wrap(err, "error removing file from Dropbox storage") } } diff --git a/internal/storage/s3/s3.go b/internal/storage/s3/s3.go index 4ad50505..923ca8aa 100644 --- a/internal/storage/s3/s3.go +++ b/internal/storage/s3/s3.go @@ -10,7 +10,6 @@ import ( "fmt" "os" "path" - "path/filepath" "time" "github.com/minio/minio-go/v7" @@ -124,7 +123,7 @@ func (b *s3Storage) Copy(file string) error { putObjectOptions.PartSize = uint64(partSize) } - if _, err := b.client.FPutObject(context.Background(), b.bucket, filepath.Join(b.DestinationPath, name), file, putObjectOptions); err != nil { + if _, err := b.client.FPutObject(context.Background(), b.bucket, path.Join(b.DestinationPath, name), file, putObjectOptions); err != nil { if errResp := minio.ToErrorResponse(err); errResp.Message != "" { return errwrap.Wrap( nil, @@ -147,7 +146,7 @@ func (b *s3Storage) Copy(file string) error { // Prune rotates away backups according to the configuration and provided deadline for the S3/Minio storage backend. func (b *s3Storage) Prune(deadline time.Time, pruningPrefix string) (*storage.PruneStats, error) { candidates := b.client.ListObjects(context.Background(), b.bucket, minio.ListObjectsOptions{ - Prefix: filepath.Join(b.DestinationPath, pruningPrefix), + Prefix: path.Join(b.DestinationPath, pruningPrefix), Recursive: true, }) diff --git a/internal/storage/ssh/ssh.go b/internal/storage/ssh/ssh.go index 370868c7..fcdea453 100644 --- a/internal/storage/ssh/ssh.go +++ b/internal/storage/ssh/ssh.go @@ -8,7 +8,6 @@ import ( "io" "os" "path" - "path/filepath" "strings" "time" @@ -115,7 +114,7 @@ func (b *sshStorage) Copy(file string) error { } defer source.Close() - destination, err := b.sftpClient.Create(filepath.Join(b.DestinationPath, name)) + destination, err := b.sftpClient.Create(path.Join(b.DestinationPath, name)) if err != nil { return errwrap.Wrap(err, "error creating file") } @@ -180,7 +179,7 @@ func (b *sshStorage) Prune(deadline time.Time, pruningPrefix string) (*storage.P pruneErr := b.DoPrune(b.Name(), len(matches), len(candidates), deadline, func() error { for _, match := range matches { - if err := b.sftpClient.Remove(filepath.Join(b.DestinationPath, match)); err != nil { + if err := b.sftpClient.Remove(path.Join(b.DestinationPath, match)); err != nil { return errwrap.Wrap(err, "error removing file") } } diff --git a/internal/storage/webdav/webdav.go b/internal/storage/webdav/webdav.go index d9197763..f655caaf 100644 --- a/internal/storage/webdav/webdav.go +++ b/internal/storage/webdav/webdav.go @@ -9,7 +9,6 @@ import ( "net/http" "os" "path" - "path/filepath" "strings" "time" @@ -77,7 +76,7 @@ func (b *webDavStorage) Copy(file string) error { return errwrap.Wrap(err, "error opening the file to be uploaded") } - if err := b.client.WriteStream(filepath.Join(b.DestinationPath, name), r, 0644); err != nil { + if err := b.client.WriteStream(path.Join(b.DestinationPath, name), r, 0644); err != nil { return errwrap.Wrap(err, "error uploading the file") } b.Log(storage.LogLevelInfo, b.Name(), "Uploaded a copy of backup '%s' to '%s' at path '%s'.", file, b.url, b.DestinationPath) @@ -110,7 +109,7 @@ func (b *webDavStorage) Prune(deadline time.Time, pruningPrefix string) (*storag pruneErr := b.DoPrune(b.Name(), len(matches), lenCandidates, deadline, func() error { for _, match := range matches { - if err := b.client.Remove(filepath.Join(b.DestinationPath, match.Name())); err != nil { + if err := b.client.Remove(path.Join(b.DestinationPath, match.Name())); err != nil { return errwrap.Wrap(err, "error removing file") } }