func (res *Restorer) restoreNodeTo(node *Node, dir string, dst string) error { debug.Log("node %v, dir %v, dst %v", node.Name, dir, dst) dstPath := filepath.Join(dst, dir, node.Name) err := node.CreateAt(dstPath, res.repo) if err != nil { debug.Log("node.CreateAt(%s) error %v", dstPath, err) } // Did it fail because of ENOENT? if err != nil && os.IsNotExist(errors.Cause(err)) { debug.Log("create intermediate paths") // Create parent directories and retry err = fs.MkdirAll(filepath.Dir(dstPath), 0700) if err == nil || os.IsExist(errors.Cause(err)) { err = node.CreateAt(dstPath, res.repo) } } if err != nil { debug.Log("error %v", err) err = res.Error(dstPath, node, err) if err != nil { return err } } debug.Log("successfully restored %v", node.Name) return nil }
// 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(dir string) (*Local, error) { // test if config file already exists _, 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 := fs.MkdirAll(d, backend.Modes.Dir) if err != nil { return nil, errors.Wrap(err, "MkdirAll") } } // open backend return Open(dir) }
// Save stores data in the backend at the handle. func (b *Local) Save(h restic.Handle, p []byte) (err error) { debug.Log("Save %v, length %v", h, len(p)) if err := h.Valid(); err != nil { return err } tmpfile, err := writeToTempfile(filepath.Join(b.p, backend.Paths.Temp), p) debug.Log("saved %v (%d bytes) to %v", h, len(p), tmpfile) if err != nil { return err } filename := filename(b.p, h.Type, h.Name) // test if new path already exists if _, err := fs.Stat(filename); err == nil { return errors.Errorf("Rename(): file %v already exists", filename) } // create directories if necessary, ignore errors if h.Type == restic.DataFile { err = fs.MkdirAll(filepath.Dir(filename), backend.Modes.Dir) if err != nil { return errors.Wrap(err, "MkdirAll") } } err = fs.Rename(tmpfile, filename) debug.Log("save %v: rename %v -> %v: %v", h, filepath.Base(tmpfile), filepath.Base(filename), err) if err != nil { return errors.Wrap(err, "Rename") } // set mode to read-only fi, err := fs.Stat(filename) if err != nil { return errors.Wrap(err, "Stat") } return setNewFileMode(filename, fi) }