diff --git a/cache_darwin.go b/cache_darwin.go new file mode 100644 index 000000000..816fa2416 --- /dev/null +++ b/cache_darwin.go @@ -0,0 +1,49 @@ +package restic + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/restic/restic/debug" +) + +// GetCacheDir returns the cache directory according to XDG basedir spec, see +// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html +func GetCacheDir() (string, error) { + xdgcache := os.Getenv("XDG_CACHE_HOME") + home := os.Getenv("HOME") + + if xdgcache == "" && home == "" { + return "", errors.New("unable to locate cache directory (XDG_CACHE_HOME and HOME unset)") + } + + cachedir := "" + if xdgcache != "" { + cachedir = filepath.Join(xdgcache, "restic") + } else if home != "" { + cachedir = filepath.Join(home, ".cache", "restic") + } + + fi, err := os.Stat(cachedir) + if os.IsNotExist(err) { + err = os.MkdirAll(cachedir, 0700) + if err != nil { + return "", err + } + + fi, err = os.Stat(cachedir) + debug.Log("getCacheDir", "create cache dir %v", cachedir) + } + + if err != nil { + return "", err + } + + if !fi.IsDir() { + return "", fmt.Errorf("cache dir %v is not a directory", cachedir) + } + + return cachedir, nil +} diff --git a/node_darwin.go b/node_darwin.go index 38b3d1261..ff1c2d2c1 100644 --- a/node_darwin.go +++ b/node_darwin.go @@ -7,6 +7,8 @@ import ( "strconv" "syscall" "time" + + "github.com/restic/restic/debug" ) func (node *Node) fill_extra(path string, fi os.FileInfo) (err error) { @@ -66,3 +68,38 @@ func (node *Node) createCharDevAt(path string) error { func (node *Node) createFifoAt(path string) error { return syscall.Mkfifo(path, 0600) } + +func (node *Node) isNewer(path string, fi os.FileInfo) bool { + // if this node has a type other than "file", treat as if content has changed + if node.Type != "file" { + debug.Log("node.isNewer", "node %v is newer: not file", path) + return true + } + + // if the name or type has changed, this is surely something different + tpe := nodeTypeFromFileInfo(path, fi) + if node.Name != fi.Name() || node.Type != tpe { + debug.Log("node.isNewer", "node %v is newer: name or type changed", path) + return false + } + + // collect extended stat + stat := fi.Sys().(*syscall.Stat_t) + + changeTime := time.Unix(stat.Ctimespec.Unix()) + inode := stat.Ino + size := uint64(stat.Size) + + // if timestamps or inodes differ, content has changed + if node.ModTime != fi.ModTime() || + node.ChangeTime != changeTime || + node.Inode != inode || + node.Size != size { + debug.Log("node.isNewer", "node %v is newer: timestamp or inode changed", path) + return false + } + + // otherwise the node is assumed to have the same content + debug.Log("node.isNewer", "node %v is not newer", path) + return false +}