diff --git a/src/cmds/restic-server/handlers.go b/src/cmds/restic-server/handlers.go index f7c4d8c5d..3351fdc0e 100644 --- a/src/cmds/restic-server/handlers.go +++ b/src/cmds/restic-server/handlers.go @@ -12,6 +12,8 @@ import ( "path/filepath" "strings" "time" + + "restic/fs" ) // Context contains repository meta-data. @@ -134,7 +136,7 @@ func GetBlob(c *Context) http.HandlerFunc { dir := vars[1] name := vars[2] path := filepath.Join(c.path, dir, name) - file, err := os.Open(path) + file, err := fs.Open(path) if err != nil { http.Error(w, "404 not found", 404) return @@ -152,7 +154,7 @@ func SaveBlob(c *Context) http.HandlerFunc { name := vars[2] path := filepath.Join(c.path, dir, name) tmp := path + "_tmp" - tf, err := os.OpenFile(tmp, os.O_CREATE|os.O_WRONLY, 0600) + tf, err := fs.OpenFile(tmp, os.O_CREATE|os.O_WRONLY, 0600) if err != nil { http.Error(w, "500 internal server error", 500) return diff --git a/src/cmds/restic-server/htpasswd.go b/src/cmds/restic-server/htpasswd.go index 2b7108f7f..6ec67040b 100644 --- a/src/cmds/restic-server/htpasswd.go +++ b/src/cmds/restic-server/htpasswd.go @@ -32,7 +32,8 @@ import ( "encoding/csv" "io" "log" - "os" + + "restic/fs" ) // lookup passwords in a htpasswd file @@ -47,7 +48,7 @@ type HtpasswdFile struct { // file and returns them. If an error is encountered, it is returned, together // with a nil-Pointer for the HtpasswdFile. func NewHtpasswdFromFile(path string) (*HtpasswdFile, error) { - r, err := os.Open(path) + r, err := fs.Open(path) if err != nil { return nil, err } diff --git a/src/cmds/restic/cmd_backup.go b/src/cmds/restic/cmd_backup.go index 400608b97..660200094 100644 --- a/src/cmds/restic/cmd_backup.go +++ b/src/cmds/restic/cmd_backup.go @@ -10,6 +10,7 @@ import ( "restic/backend" "restic/debug" "restic/filter" + "restic/fs" "strings" "time" @@ -221,7 +222,7 @@ func (cmd CmdBackup) newArchiveStdinProgress() *restic.Progress { // items exist at all. func filterExisting(items []string) (result []string, err error) { for _, item := range items { - _, err := os.Lstat(item) + _, err := fs.Lstat(item) if err != nil && os.IsNotExist(err) { continue } @@ -334,7 +335,7 @@ func (cmd CmdBackup) Execute(args []string) error { // add patterns from file if cmd.ExcludeFile != "" { - file, err := os.Open(cmd.ExcludeFile) + file, err := fs.Open(cmd.ExcludeFile) if err != nil { cmd.global.Warnf("error reading exclude patterns: %v", err) return nil diff --git a/src/cmds/restic/cmd_mount.go b/src/cmds/restic/cmd_mount.go index d800bd33c..13643c69a 100644 --- a/src/cmds/restic/cmd_mount.go +++ b/src/cmds/restic/cmd_mount.go @@ -7,6 +7,7 @@ import ( "fmt" "os" + resticfs "restic/fs" "restic/fuse" systemFuse "bazil.org/fuse" @@ -55,9 +56,9 @@ func (cmd CmdMount) Execute(args []string) error { } mountpoint := args[0] - if _, err := os.Stat(mountpoint); os.IsNotExist(err) { + if _, err := resticfs.Stat(mountpoint); os.IsNotExist(err) { cmd.global.Verbosef("Mountpoint %s doesn't exist, creating it\n", mountpoint) - err = os.Mkdir(mountpoint, os.ModeDir|0700) + err = resticfs.Mkdir(mountpoint, os.ModeDir|0700) if err != nil { return err } diff --git a/src/restic/archiver.go b/src/restic/archiver.go index 737801ee5..5aa27dcc4 100644 --- a/src/restic/archiver.go +++ b/src/restic/archiver.go @@ -780,7 +780,7 @@ func Scan(dirs []string, filter pipe.SelectFunc, p *Progress) (Stat, error) { for _, dir := range dirs { debug.Log("Scan", "Start for %v", dir) - err := filepath.Walk(dir, func(str string, fi os.FileInfo, err error) error { + err := fs.Walk(dir, func(str string, fi os.FileInfo, err error) error { // TODO: integrate error reporting if err != nil { fmt.Fprintf(os.Stderr, "error for %v: %v\n", str, err) diff --git a/src/restic/backend/local/local.go b/src/restic/backend/local/local.go index 42d898dd0..0821720c7 100644 --- a/src/restic/backend/local/local.go +++ b/src/restic/backend/local/local.go @@ -34,7 +34,7 @@ func paths(dir string) []string { func Open(dir string) (*Local, error) { // test if all necessary dirs are there for _, d := range paths(dir) { - if _, err := os.Stat(d); err != nil { + if _, err := fs.Stat(d); err != nil { return nil, fmt.Errorf("%s does not exist", d) } } @@ -46,14 +46,14 @@ func Open(dir string) (*Local, error) { // backend at dir. Afterwards a new config blob should be created. func Create(dir string) (*Local, error) { // test if config file already exists - _, err := os.Lstat(filepath.Join(dir, backend.Paths.Config)) + _, err := fs.Lstat(filepath.Join(dir, backend.Paths.Config)) if err == nil { return nil, errors.New("config file already exists") } // create paths for data, refs and temp for _, d := range paths(dir) { - err := os.MkdirAll(d, backend.Modes.Dir) + err := fs.MkdirAll(d, backend.Modes.Dir) if err != nil { return nil, err } @@ -105,7 +105,7 @@ func (b *Local) Load(h backend.Handle, p []byte, off int64) (n int, err error) { return 0, err } - f, err := os.Open(filename(b.p, h.Type, h.Name)) + f, err := fs.Open(filename(b.p, h.Type, h.Name)) if err != nil { return 0, err } @@ -172,19 +172,19 @@ func (b *Local) Save(h backend.Handle, p []byte) (err error) { filename := filename(b.p, h.Type, h.Name) // test if new path already exists - if _, err := os.Stat(filename); err == nil { + if _, err := fs.Stat(filename); err == nil { return fmt.Errorf("Rename(): file %v already exists", filename) } // create directories if necessary, ignore errors if h.Type == backend.Data { - err = os.MkdirAll(filepath.Dir(filename), backend.Modes.Dir) + err = fs.MkdirAll(filepath.Dir(filename), backend.Modes.Dir) if err != nil { return err } } - err = os.Rename(tmpfile, filename) + err = fs.Rename(tmpfile, filename) debug.Log("local.Save", "save %v: rename %v -> %v: %v", h, filepath.Base(tmpfile), filepath.Base(filename), err) @@ -193,7 +193,7 @@ func (b *Local) Save(h backend.Handle, p []byte) (err error) { } // set mode to read-only - fi, err := os.Stat(filename) + fi, err := fs.Stat(filename) if err != nil { return err } @@ -207,7 +207,7 @@ func (b *Local) Stat(h backend.Handle) (backend.BlobInfo, error) { return backend.BlobInfo{}, err } - fi, err := os.Stat(filename(b.p, h.Type, h.Name)) + fi, err := fs.Stat(filename(b.p, h.Type, h.Name)) if err != nil { return backend.BlobInfo{}, err } @@ -217,7 +217,7 @@ func (b *Local) Stat(h backend.Handle) (backend.BlobInfo, error) { // Test returns true if a blob of the given type and name exists in the backend. func (b *Local) Test(t backend.Type, name string) (bool, error) { - _, err := os.Stat(filename(b.p, t, name)) + _, err := fs.Stat(filename(b.p, t, name)) if err != nil { if os.IsNotExist(err) { return false, nil @@ -233,12 +233,12 @@ func (b *Local) Remove(t backend.Type, name string) error { fn := filename(b.p, t, name) // reset read-only flag - err := os.Chmod(fn, 0666) + err := fs.Chmod(fn, 0666) if err != nil { return err } - return os.Remove(fn) + return fs.Remove(fn) } func isFile(fi os.FileInfo) bool { @@ -246,7 +246,7 @@ func isFile(fi os.FileInfo) bool { } func readdir(d string) (fileInfos []os.FileInfo, err error) { - f, e := os.Open(d) + f, e := fs.Open(d) if e != nil { return nil, e } @@ -336,7 +336,7 @@ func (b *Local) List(t backend.Type, done <-chan struct{}) <-chan string { // Delete removes the repository and all files. func (b *Local) Delete() error { - return os.RemoveAll(b.p) + return fs.RemoveAll(b.p) } // Close closes all open files. diff --git a/src/restic/backend/local/local_unix.go b/src/restic/backend/local/local_unix.go index 8b8ecec69..2f0826d79 100644 --- a/src/restic/backend/local/local_unix.go +++ b/src/restic/backend/local/local_unix.go @@ -4,9 +4,10 @@ package local import ( "os" + "restic/fs" ) // set file to readonly func setNewFileMode(f string, fi os.FileInfo) error { - return os.Chmod(f, fi.Mode()&os.FileMode(^uint32(0222))) + return fs.Chmod(f, fi.Mode()&os.FileMode(^uint32(0222))) } diff --git a/src/restic/cache.go b/src/restic/cache.go index 1b00e2f95..e4b8507ca 100644 --- a/src/restic/cache.go +++ b/src/restic/cache.go @@ -11,6 +11,7 @@ import ( "restic/backend" "restic/debug" + "restic/fs" "restic/repository" ) @@ -43,7 +44,7 @@ func (c *Cache) Has(t backend.Type, subtype string, id backend.ID) (bool, error) if err != nil { return false, err } - fd, err := os.Open(filename) + fd, err := fs.Open(filename) defer fd.Close() if err != nil { @@ -70,12 +71,12 @@ func (c *Cache) Store(t backend.Type, subtype string, id backend.ID) (io.WriteCl } dirname := filepath.Dir(filename) - err = os.MkdirAll(dirname, 0700) + err = fs.MkdirAll(dirname, 0700) if err != nil { return nil, err } - file, err := os.Create(filename) + file, err := fs.Create(filename) if err != nil { debug.Log("Cache.Store", "error creating file %v: %v", filename, err) return nil, err @@ -93,7 +94,7 @@ func (c *Cache) Load(t backend.Type, subtype string, id backend.ID) (io.ReadClos return nil, err } - return os.Open(filename) + return fs.Open(filename) } func (c *Cache) purge(t backend.Type, subtype string, id backend.ID) error { @@ -102,7 +103,7 @@ func (c *Cache) purge(t backend.Type, subtype string, id backend.ID) error { return err } - err = os.Remove(filename) + err = fs.Remove(filename) debug.Log("Cache.purge", "Remove file %v: %v", filename, err) if err != nil && os.IsNotExist(err) { @@ -157,7 +158,7 @@ func (c *Cache) list(t backend.Type) ([]cacheEntry, error) { return nil, fmt.Errorf("cache not supported for type %v", t) } - fd, err := os.Open(dir) + fd, err := fs.Open(dir) if err != nil { if os.IsNotExist(err) { return []cacheEntry{}, nil @@ -228,10 +229,10 @@ func getWindowsCacheDir() (string, error) { cachedir = os.TempDir() } cachedir = filepath.Join(cachedir, "restic") - fi, err := os.Stat(cachedir) + fi, err := fs.Stat(cachedir) if os.IsNotExist(err) { - err = os.MkdirAll(cachedir, 0700) + err = fs.MkdirAll(cachedir, 0700) if err != nil { return "", err } @@ -266,14 +267,14 @@ func getXDGCacheDir() (string, error) { cachedir = filepath.Join(home, ".cache", "restic") } - fi, err := os.Stat(cachedir) + fi, err := fs.Stat(cachedir) if os.IsNotExist(err) { - err = os.MkdirAll(cachedir, 0700) + err = fs.MkdirAll(cachedir, 0700) if err != nil { return "", err } - fi, err = os.Stat(cachedir) + fi, err = fs.Stat(cachedir) debug.Log("getCacheDir", "create cache dir %v", cachedir) } diff --git a/src/restic/debug/debug.go b/src/restic/debug/debug.go index a9364aacc..8d20b72e2 100644 --- a/src/restic/debug/debug.go +++ b/src/restic/debug/debug.go @@ -8,6 +8,7 @@ import ( "os" "path" "path/filepath" + "restic/fs" "runtime" "strconv" "strings" @@ -48,7 +49,7 @@ func initDebugLogger() { fmt.Fprintf(os.Stderr, "debug log file %v\n", debugfile) - f, err := os.OpenFile(debugfile, os.O_WRONLY|os.O_APPEND, 0600) + f, err := fs.OpenFile(debugfile, os.O_WRONLY|os.O_APPEND, 0600) if err == nil { _, err = f.Seek(2, 0) @@ -59,7 +60,7 @@ func initDebugLogger() { } if err != nil && os.IsNotExist(err) { - f, err = os.OpenFile(debugfile, os.O_WRONLY|os.O_CREATE, 0600) + f, err = fs.OpenFile(debugfile, os.O_WRONLY|os.O_CREATE, 0600) } if err != nil { diff --git a/src/restic/fs/file.go b/src/restic/fs/file.go index 68a0fb07a..be72d925e 100644 --- a/src/restic/fs/file.go +++ b/src/restic/fs/file.go @@ -11,5 +11,9 @@ type File interface { io.Writer io.Closer + Fd() uintptr + Readdirnames(n int) ([]string, error) + Readdir(int) ([]os.FileInfo, error) + Seek(int64, int) (int64, error) Stat() (os.FileInfo, error) } diff --git a/src/restic/fs/file_all.go b/src/restic/fs/file_all.go index 8c4b0639a..93ce1ba20 100644 --- a/src/restic/fs/file_all.go +++ b/src/restic/fs/file_all.go @@ -2,14 +2,126 @@ package fs -import "os" +import ( + "os" + "path/filepath" + "runtime" +) + +func fixpath(name string) string { + if runtime.GOOS == "windows" { + abspath, err := filepath.Abs(name) + if err == nil { + return "\\\\?\\" + abspath + } + } + return name +} // Open opens a file for reading. func Open(name string) (File, error) { - return os.OpenFile(name, os.O_RDONLY, 0) + return os.OpenFile(fixpath(name), os.O_RDONLY, 0) } // ClearCache syncs and then removes the file's content from the OS cache. func ClearCache(f File) error { return nil } + +// Chmod changes the mode of the named file to mode. +func Chmod(name string, mode os.FileMode) error { + return os.Chmod(fixpath(name), mode) +} + +// Mkdir creates a new directory with the specified name and permission bits. +// If there is an error, it will be of type *PathError. +func Mkdir(name string, perm os.FileMode) error { + return os.Mkdir(fixpath(name), perm) +} + +// MkdirAll creates a directory named path, +// along with any necessary parents, and returns nil, +// or else returns an error. +// The permission bits perm are used for all +// directories that MkdirAll creates. +// If path is already a directory, MkdirAll does nothing +// and returns nil. +func MkdirAll(path string, perm os.FileMode) error { + return os.MkdirAll(fixpath(path), perm) +} + +// Readlink returns the destination of the named symbolic link. +// If there is an error, it will be of type *PathError. +func Readlink(name string) (string, error) { + return os.Readlink(fixpath(name)) +} + +// Remove removes the named file or directory. +// If there is an error, it will be of type *PathError. +func Remove(name string) error { + return os.Remove(fixpath(name)) +} + +// RemoveAll removes path and any children it contains. +// It removes everything it can but returns the first error +// it encounters. If the path does not exist, RemoveAll +// returns nil (no error). +func RemoveAll(path string) error { + return os.RemoveAll(fixpath(path)) +} + +// Rename renames (moves) oldpath to newpath. +// If newpath already exists, Rename replaces it. +// OS-specific restrictions may apply when oldpath and newpath are in different directories. +// If there is an error, it will be of type *LinkError. +func Rename(oldpath, newpath string) error { + return os.Rename(fixpath(oldpath), fixpath(newpath)) +} + +// Symlink creates newname as a symbolic link to oldname. +// If there is an error, it will be of type *LinkError. +func Symlink(oldname, newname string) error { + return os.Symlink(fixpath(oldname), fixpath(newname)) +} + +// Stat returns a FileInfo structure describing the named file. +// If there is an error, it will be of type *PathError. +func Stat(name string) (os.FileInfo, error) { + return os.Stat(fixpath(name)) +} + +// Lstat returns the FileInfo structure describing the named file. +// If the file is a symbolic link, the returned FileInfo +// describes the symbolic link. Lstat makes no attempt to follow the link. +// If there is an error, it will be of type *PathError. +func Lstat(name string) (os.FileInfo, error) { + return os.Lstat(fixpath(name)) +} + +// 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. +// If there is an error, it will be of type *PathError. +func Create(name string) (*os.File, error) { + return os.Create(fixpath(name)) +} + +// 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. +// If there is an error, it will be of type *PathError. +func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { + return os.OpenFile(fixpath(name), flag, perm) +} + +// Walk walks the file tree rooted at root, calling walkFn for each file or +// directory in the tree, including root. All errors that arise visiting files +// and directories are filtered by walkFn. The files are walked in lexical +// order, which makes the output deterministic but means that for very +// large directories Walk can be inefficient. +// Walk does not follow symbolic links. +func Walk(root string, walkFn filepath.WalkFunc) error { + return filepath.Walk(fixpath(root), walkFn) +} diff --git a/src/restic/fs/file_linux.go b/src/restic/fs/file_linux.go index 90152ee68..67e674a97 100644 --- a/src/restic/fs/file_linux.go +++ b/src/restic/fs/file_linux.go @@ -4,6 +4,7 @@ package fs import ( "os" + "path/filepath" "syscall" "golang.org/x/sys/unix" @@ -65,3 +66,101 @@ func ClearCache(file File) error { return unix.Fadvise(int(f.Fd()), 0, 0, _POSIX_FADV_DONTNEED) } + +// Chmod changes the mode of the named file to mode. +func Chmod(name string, mode os.FileMode) error { + return os.Chmod(name, mode) +} + +// Mkdir creates a new directory with the specified name and permission bits. +// If there is an error, it will be of type *PathError. +func Mkdir(name string, perm os.FileMode) error { + return os.Mkdir(name, perm) +} + +// MkdirAll creates a directory named path, +// along with any necessary parents, and returns nil, +// or else returns an error. +// The permission bits perm are used for all +// directories that MkdirAll creates. +// If path is already a directory, MkdirAll does nothing +// and returns nil. +func MkdirAll(path string, perm os.FileMode) error { + return os.MkdirAll(path, perm) +} + +// Readlink returns the destination of the named symbolic link. +// If there is an error, it will be of type *PathError. +func Readlink(name string) (string, error) { + return os.Readlink(name) +} + +// Remove removes the named file or directory. +// If there is an error, it will be of type *PathError. +func Remove(name string) error { + return os.Remove(name) +} + +// RemoveAll removes path and any children it contains. +// It removes everything it can but returns the first error +// it encounters. If the path does not exist, RemoveAll +// returns nil (no error). +func RemoveAll(path string) error { + return os.RemoveAll(path) +} + +// Rename renames (moves) oldpath to newpath. +// If newpath already exists, Rename replaces it. +// OS-specific restrictions may apply when oldpath and newpath are in different directories. +// If there is an error, it will be of type *LinkError. +func Rename(oldpath, newpath string) error { + return os.Rename(oldpath, newpath) +} + +// Symlink creates newname as a symbolic link to oldname. +// If there is an error, it will be of type *LinkError. +func Symlink(oldname, newname string) error { + return os.Symlink(oldname, newname) +} + +// Stat returns a FileInfo structure describing the named file. +// If there is an error, it will be of type *PathError. +func Stat(name string) (os.FileInfo, error) { + return os.Stat(name) +} + +// Lstat returns the FileInfo structure describing the named file. +// If the file is a symbolic link, the returned FileInfo +// describes the symbolic link. Lstat makes no attempt to follow the link. +// If there is an error, it will be of type *PathError. +func Lstat(name string) (os.FileInfo, error) { + return os.Lstat(name) +} + +// 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. +// If there is an error, it will be of type *PathError. +func Create(name string) (*os.File, error) { + return os.Create(name) +} + +// 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. +// If there is an error, it will be of type *PathError. +func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { + return os.OpenFile(name, flag, perm) +} + +// Walk walks the file tree rooted at root, calling walkFn for each file or +// directory in the tree, including root. All errors that arise visiting files +// and directories are filtered by walkFn. The files are walked in lexical +// order, which makes the output deterministic but means that for very +// large directories Walk can be inefficient. +// Walk does not follow symbolic links. +func Walk(root string, walkFn filepath.WalkFunc) error { + return filepath.Walk(root, walkFn) +} diff --git a/src/restic/node.go b/src/restic/node.go index 38c21b204..21c447d1a 100644 --- a/src/restic/node.go +++ b/src/restic/node.go @@ -15,6 +15,7 @@ import ( "github.com/juju/errors" "restic/backend" "restic/debug" + "restic/fs" "restic/pack" "restic/repository" ) @@ -157,7 +158,7 @@ func (node Node) restoreMetadata(path string) error { } if node.Type != "symlink" { - err = os.Chmod(path, node.Mode) + err = fs.Chmod(path, node.Mode) if err != nil { return errors.Annotate(err, "Chmod") } @@ -196,7 +197,7 @@ func (node Node) RestoreTimestamps(path string) error { } func (node Node) createDirAt(path string) error { - err := os.Mkdir(path, node.Mode) + err := fs.Mkdir(path, node.Mode) if err != nil { return errors.Annotate(err, "Mkdir") } @@ -205,7 +206,7 @@ func (node Node) createDirAt(path string) error { } func (node Node) createFileAt(path string, repo *repository.Repository) error { - f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600) + f, err := fs.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600) defer f.Close() if err != nil { @@ -243,7 +244,7 @@ func (node Node) createSymlinkAt(path string) error { if runtime.GOOS == "windows" { return nil } - err := os.Symlink(node.LinkTarget, path) + err := fs.Symlink(node.LinkTarget, path) if err != nil { return errors.Annotate(err, "Symlink") } @@ -477,7 +478,7 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) error { node.Links = uint64(stat.nlink()) case "dir": case "symlink": - node.LinkTarget, err = os.Readlink(path) + node.LinkTarget, err = fs.Readlink(path) case "dev": node.Device = uint64(stat.rdev()) case "chardev": diff --git a/src/restic/node_linux.go b/src/restic/node_linux.go index c6b50ee38..a4652d44c 100644 --- a/src/restic/node_linux.go +++ b/src/restic/node_linux.go @@ -1,16 +1,17 @@ package restic import ( - "os" "path/filepath" "syscall" "unsafe" + "restic/fs" + "github.com/juju/errors" ) func (node Node) restoreSymlinkTimestamps(path string, utimes [2]syscall.Timespec) error { - dir, err := os.Open(filepath.Dir(path)) + dir, err := fs.Open(filepath.Dir(path)) defer dir.Close() if err != nil { return err diff --git a/src/restic/pipe/pipe.go b/src/restic/pipe/pipe.go index e46adc8a4..92343f545 100644 --- a/src/restic/pipe/pipe.go +++ b/src/restic/pipe/pipe.go @@ -8,6 +8,7 @@ import ( "sort" "restic/debug" + "restic/fs" ) type Result interface{} @@ -59,7 +60,7 @@ func (e Dir) Result() chan<- Result { return e.result } // a sorted list of directory entries. // taken from filepath/path.go func readDirNames(dirname string) ([]string, error) { - f, err := os.Open(dirname) + f, err := fs.Open(dirname) if err != nil { return nil, err } @@ -90,7 +91,7 @@ func walk(basedir, dir string, selectFunc SelectFunc, done <-chan struct{}, jobs panic(err) } - info, err := os.Lstat(dir) + info, err := fs.Lstat(dir) if err != nil { debug.Log("pipe.walk", "error for %v: %v, res %p", dir, err, res) select { @@ -135,7 +136,7 @@ func walk(basedir, dir string, selectFunc SelectFunc, done <-chan struct{}, jobs for _, name := range names { subpath := filepath.Join(dir, name) - fi, statErr := os.Lstat(subpath) + fi, statErr := fs.Lstat(subpath) if !selectFunc(subpath, fi) { debug.Log("pipe.walk", "file %v excluded by filter", subpath) continue diff --git a/src/restic/repository/packer_manager.go b/src/restic/repository/packer_manager.go index de1f97c74..cbf27e626 100644 --- a/src/restic/repository/packer_manager.go +++ b/src/restic/repository/packer_manager.go @@ -10,6 +10,7 @@ import ( "restic/backend" "restic/crypto" "restic/debug" + "restic/fs" "restic/pack" ) @@ -93,7 +94,7 @@ func (r *Repository) savePacker(p *pack.Packer) error { } tmpfile := p.Writer().(*os.File) - f, err := os.Open(tmpfile.Name()) + f, err := fs.Open(tmpfile.Name()) if err != nil { return err } @@ -120,7 +121,7 @@ func (r *Repository) savePacker(p *pack.Packer) error { debug.Log("Repo.savePacker", "saved as %v", h) - err = os.Remove(tmpfile.Name()) + err = fs.Remove(tmpfile.Name()) if err != nil { return err } diff --git a/src/restic/restorer.go b/src/restic/restorer.go index a093b5e40..cb2f888cc 100644 --- a/src/restic/restorer.go +++ b/src/restic/restorer.go @@ -7,6 +7,7 @@ import ( "restic/backend" "restic/debug" + "restic/fs" "restic/repository" "github.com/juju/errors" @@ -99,7 +100,7 @@ func (res *Restorer) restoreNodeTo(node *Node, dir string, dst string) error { debug.Log("Restorer.restoreNodeTo", "create intermediate paths") // Create parent directories and retry - err = os.MkdirAll(filepath.Dir(dstPath), 0700) + err = fs.MkdirAll(filepath.Dir(dstPath), 0700) if err == nil || err == os.ErrExist { err = node.CreateAt(dstPath, res.repo) }