diff --git a/doc/Manual.md b/doc/Manual.md index 27274a9f4..6d4d1f513 100644 --- a/doc/Manual.md +++ b/doc/Manual.md @@ -326,18 +326,16 @@ credentials. Once the server is configured, the setup of the SFTP repository can simply be achieved by changing the URL scheme in the `init` command: - $ restic -r sftp://user@host//tmp/backup init + $ restic -r sftp:user@host:/tmp/backup init enter password for new backend: enter password again: - created restic backend f1c6108821 at sftp://user@host//tmp/backup + created restic backend f1c6108821 at sftp:user@host:/tmp/backup Please note that knowledge of your password is required to access the repository. Losing your password means that your data is irrecoverably lost. -Yes, that's really two slash (`/`) characters after the host name, here the -directory `/tmp/backup` on the server is meant. If you'd rather like to create -a repository in the user's home directory on the server, use the location -`sftp://user@host/foo/bar/repo`. In this case the directory is relative to the -user's home directory: `foo/bar/repo`. +You can also specify a relative (read: no slash (`/`) character at the +beginning) directory, in this case the dir is relative to the remote user's +home directory. # Create an Amazon S3 repository @@ -348,15 +346,16 @@ Restic can backup data to any Amazon S3 bucket. However, in this case, changing You can then easily initialize a repository that uses your Amazon S3 as a backend. - $ restic -r s3://s3.amazonaws.com/bucket_name init + $ restic -r s3:eu-central-1/bucket_name init enter password for new backend: enter password again: - created restic backend eefee03bbd at s3://s3.amazonaws.com/bucket_name + created restic backend eefee03bbd at s3:eu-central-1/bucket_name Please note that knowledge of your password is required to access the repository. Losing your password means that your data is irrecoverably lost. -For an S3-compatible repository without TLS available, use the alternative URI -protocol `s3:http://server:port/bucket_name`. +Fro an s3-compatible server that is not Amazon (like Minio, see below), or is +only available via HTTP, you can specify the URL to the server like this: +`s3:http://server:port/bucket_name`. ## Create a Minio Server repository diff --git a/src/restic/backend/sftp/sftp.go b/src/restic/backend/sftp/sftp.go index 4279b8d5a..801c3075a 100644 --- a/src/restic/backend/sftp/sftp.go +++ b/src/restic/backend/sftp/sftp.go @@ -8,13 +8,14 @@ import ( "log" "os" "os/exec" - "path/filepath" + "path" "strings" + "restic/backend" + "restic/debug" + "github.com/juju/errors" "github.com/pkg/sftp" - "restic/backend" - "restic/debug" ) const ( @@ -78,7 +79,8 @@ func paths(dir string) []string { // Open opens an sftp backend. When the command is started via // exec.Command, it is expected to speak sftp on stdin/stdout. The backend -// is expected at the given path. +// is expected at the given path. `dir` must be delimited by forward slashes +// ("/"), which is required by sftp. func Open(dir string, program string, args ...string) (*SFTP, error) { sftp, err := startClient(program, args...) if err != nil { @@ -118,7 +120,8 @@ func OpenWithConfig(cfg Config) (*SFTP, error) { } // Create creates all the necessary files and directories for a new sftp -// backend at dir. Afterwards a new config blob should be created. +// backend at dir. Afterwards a new config blob should be created. `dir` must +// be delimited by forward slashes ("/"), which is required by sftp. func Create(dir string, program string, args ...string) (*SFTP, error) { sftp, err := startClient(program, args...) if err != nil { @@ -199,7 +202,7 @@ func (r *SFTP) mkdirAll(dir string, mode os.FileMode) error { } // create parent directories - errMkdirAll := r.mkdirAll(filepath.Dir(dir), backend.Modes.Dir) + errMkdirAll := r.mkdirAll(path.Dir(dir), backend.Modes.Dir) // create directory errMkdir := r.c.Mkdir(dir) @@ -225,7 +228,7 @@ func (r *SFTP) renameFile(oldname string, t backend.Type, name string) error { // create directories if necessary if t == backend.Data { - err := r.mkdirAll(filepath.Dir(filename), backend.Modes.Dir) + err := r.mkdirAll(path.Dir(filename), backend.Modes.Dir) if err != nil { return err } @@ -250,9 +253,10 @@ func (r *SFTP) renameFile(oldname string, t backend.Type, name string) error { return r.c.Chmod(filename, fi.Mode()&os.FileMode(^uint32(0222))) } -// Join joins the given paths and cleans them afterwards. +// 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 filepath.Clean(strings.Join(parts, "/")) + return path.Clean(path.Join(parts...)) } // Construct path for given backend.Type and name. @@ -339,7 +343,7 @@ func (r *SFTP) Save(h backend.Handle, p []byte) (err error) { err = r.renameFile(filename, h.Type, h.Name) debug.Log("sftp.Save", "save %v: rename %v: %v", - h, filepath.Base(filename), err) + h, path.Base(filename), err) if err != nil { return fmt.Errorf("sftp: renameFile: %v", err) }