From 4bb724fac20e73ef5d30e2e05d85cc09ad02ad56 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Tue, 28 Apr 2015 21:24:43 -0400 Subject: [PATCH 1/4] Refactor node.go --- node.go | 222 +++++++++++++++++++++---------------------------- node_darwin.go | 35 +++----- node_linux.go | 27 ++---- restorer.go | 4 +- 4 files changed, 113 insertions(+), 175 deletions(-) diff --git a/node.go b/node.go index d6252f572..fe62bd273 100644 --- a/node.go +++ b/node.go @@ -66,7 +66,7 @@ func NodeFromFileInfo(path string, fi os.FileInfo) (*Node, error) { ModTime: fi.ModTime(), } - node.Type = nodeTypeFromFileInfo(path, fi) + node.Type = nodeTypeFromFileInfo(fi) if node.Type == "file" { node.Size = uint64(fi.Size()) } @@ -75,7 +75,7 @@ func NodeFromFileInfo(path string, fi os.FileInfo) (*Node, error) { return node, err } -func nodeTypeFromFileInfo(path string, fi os.FileInfo) string { +func nodeTypeFromFileInfo(fi os.FileInfo) string { switch fi.Mode() & (os.ModeType | os.ModeCharDevice) { case 0: return "file" @@ -96,155 +96,114 @@ func nodeTypeFromFileInfo(path string, fi os.FileInfo) string { return "" } -func CreateNodeAt(node *Node, m *Map, s *server.Server, path string) error { +func (node *Node) CreateAt(path string, m *Map, s *server.Server) error { switch node.Type { case "dir": - err := os.Mkdir(path, node.Mode) - if err != nil { - return arrar.Annotate(err, "Mkdir") - } - - err = os.Lchown(path, int(node.UID), int(node.GID)) - if err != nil { - return arrar.Annotate(err, "Lchown") - } - - var utimes = []syscall.Timespec{ - syscall.NsecToTimespec(node.AccessTime.UnixNano()), - syscall.NsecToTimespec(node.ModTime.UnixNano()), - } - err = syscall.UtimesNano(path, utimes) - if err != nil { - return arrar.Annotate(err, "Utimesnano") + if err := node.createDirAt(path); err != nil { + return err } case "file": - // TODO: handle hard links - f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600) - defer f.Close() - if err != nil { - return arrar.Annotate(err, "OpenFile") - } - - for _, blobid := range node.Content { - blob, err := m.FindID(blobid) - if err != nil { - return arrar.Annotate(err, "Find Blob") - } - - buf, err := s.Load(backend.Data, blob) - if err != nil { - return arrar.Annotate(err, "Load") - } - - _, err = f.Write(buf) - if err != nil { - return arrar.Annotate(err, "Write") - } - } - - f.Close() - - err = os.Lchown(path, int(node.UID), int(node.GID)) - if err != nil { - return arrar.Annotate(err, "Lchown") - } - - var utimes = []syscall.Timespec{ - syscall.NsecToTimespec(node.AccessTime.UnixNano()), - syscall.NsecToTimespec(node.ModTime.UnixNano()), - } - err = syscall.UtimesNano(path, utimes) - if err != nil { - return arrar.Annotate(err, "Utimesnano") + if err := node.createFileAt(path, m, s); err != nil { + return err } case "symlink": - err := os.Symlink(node.LinkTarget, path) - if err != nil { - return arrar.Annotate(err, "Symlink") + if err := node.createSymlinkAt(path); err != nil { + return err } - - err = os.Lchown(path, int(node.UID), int(node.GID)) - if err != nil { - return arrar.Annotate(err, "Lchown") - } - - // f, err := os.OpenFile(path, O_PATH|syscall.O_NOFOLLOW, 0600) - // defer f.Close() - // if err != nil { - // return arrar.Annotate(err, "OpenFile") - // } - - // TODO: Get Futimes() working on older Linux kernels (fails with 3.2.0) - // var utimes = []syscall.Timeval{ - // syscall.NsecToTimeval(node.AccessTime.UnixNano()), - // syscall.NsecToTimeval(node.ModTime.UnixNano()), - // } - // err = syscall.Futimes(int(f.Fd()), utimes) - // if err != nil { - // return arrar.Annotate(err, "Futimes") - // } - - return nil case "dev": - err := node.createDevAt(path) - if err != nil { + if err := node.createDevAt(path); err != nil { return arrar.Annotate(err, "Mknod") } case "chardev": - err := node.createCharDevAt(path) - if err != nil { + if err := node.createCharDevAt(path); err != nil { return arrar.Annotate(err, "Mknod") } case "fifo": - err := node.createFifoAt(path) - if err != nil { + if err := node.createFifoAt(path); err != nil { return arrar.Annotate(err, "Mkfifo") } case "socket": - // nothing to do, we do not restore sockets return nil default: return fmt.Errorf("filetype %q not implemented!\n", node.Type) } - err := os.Chmod(path, node.Mode) + return node.restoreMetadata(path) +} + +func (node Node) restoreMetadata(path string) error { + var err error + + err = os.Lchown(path, int(node.UID), int(node.GID)) + if err != nil { + return arrar.Annotate(err, "Lchown") + } + + if node.Type == "symlink" { + return nil + } + + err = os.Chmod(path, node.Mode) if err != nil { return arrar.Annotate(err, "Chmod") } - err = os.Chown(path, int(node.UID), int(node.GID)) - if err != nil { - return arrar.Annotate(err, "Chown") + var utimes = []syscall.Timespec{ + syscall.NsecToTimespec(node.AccessTime.UnixNano()), + syscall.NsecToTimespec(node.ModTime.UnixNano()), } - - err = os.Chtimes(path, node.AccessTime, node.ModTime) + err = syscall.UtimesNano(path, utimes) if err != nil { - return arrar.Annotate(err, "Chtimes") + return arrar.Annotate(err, "Utimesnano") } return nil } -func (node Node) SameContent(olderNode *Node) bool { - // if this node has a type other than "file", treat as if content has changed - if node.Type != "file" { - return false +func (node Node) createDirAt(path string) error { + err := os.Mkdir(path, node.Mode) + if err != nil { + return arrar.Annotate(err, "Mkdir") } - // if the name or type has changed, this is surely something different - if node.Name != olderNode.Name || node.Type != olderNode.Type { - return false + return nil +} + +func (node Node) createFileAt(path string, m *Map, s *server.Server) error { + f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600) + defer f.Close() + + if err != nil { + return arrar.Annotate(err, "OpenFile") } - // if timestamps or inodes differ, content has changed - if node.ModTime != olderNode.ModTime || - node.ChangeTime != olderNode.ChangeTime || - node.Inode != olderNode.Inode { - return false + for _, blobid := range node.Content { + blob, err := m.FindID(blobid) + if err != nil { + return arrar.Annotate(err, "Find Blob") + } + + buf, err := s.Load(backend.Data, blob) + if err != nil { + return arrar.Annotate(err, "Load") + } + + _, err = f.Write(buf) + if err != nil { + return arrar.Annotate(err, "Write") + } } - // otherwise the node is assumed to have the same content - return true + return nil +} + +func (node Node) createSymlinkAt(path string) error { + err := os.Symlink(node.LinkTarget, path) + if err != nil { + return arrar.Annotate(err, "Symlink") + } + + return nil } func (node Node) MarshalJSON() ([]byte, error) { @@ -270,7 +229,6 @@ func (node *Node) UnmarshalJSON(data []byte) error { } func (node Node) Equals(other Node) bool { - // TODO: add generatored code for this if node.Name != other.Name { return false } @@ -316,29 +274,37 @@ func (node Node) Equals(other Node) bool { if node.Device != other.Device { return false } - if node.Content != nil && other.Content == nil { + if !node.sameContent(other) { return false - } else if node.Content == nil && other.Content != nil { - return false - } else if node.Content != nil && other.Content != nil { - if len(node.Content) != len(other.Content) { - return false - } - - for i := 0; i < len(node.Content); i++ { - if !node.Content[i].Equal(other.Content[i]) { - return false - } - } } - if !node.Subtree.Equal(other.Subtree) { return false } - if node.Error != other.Error { return false } return true } + +func (node Node) sameContent(other Node) bool { + if node.Content == nil { + return other.Content == nil + } + + if other.Content == nil { + return false + } + + if len(node.Content) != len(other.Content) { + return false + } + + for i := 0; i < len(node.Content); i++ { + if !node.Content[i].Equal(other.Content[i]) { + return false + } + } + + return true +} diff --git a/node_darwin.go b/node_darwin.go index 4d3297e2a..ae4b0060a 100644 --- a/node_darwin.go +++ b/node_darwin.go @@ -15,10 +15,10 @@ func (node *Node) OpenForReading() (*os.File, error) { return os.Open(node.path) } -func (node *Node) fillExtra(path string, fi os.FileInfo) (err error) { +func (node *Node) fillExtra(path string, fi os.FileInfo) error { stat, ok := fi.Sys().(*syscall.Stat_t) if !ok { - return + return nil } node.ChangeTime = time.Unix(stat.Ctimespec.Unix()) @@ -26,24 +26,19 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) (err error) { node.UID = stat.Uid node.GID = stat.Gid - // TODO: cache uid lookup - if u, nil := user.LookupId(strconv.Itoa(int(stat.Uid))); err == nil { + if u, err := user.LookupId(strconv.Itoa(int(stat.Uid))); err == nil { node.User = u.Username } - // TODO: implement getgrnam() or use https://github.com/kless/osutil - // if g, nil := user.LookupId(strconv.Itoa(int(stat.Uid))); err == nil { - // node.User = u.Username - // } - node.Inode = stat.Ino + var err error + switch node.Type { case "file": node.Size = uint64(stat.Size) node.Links = uint64(stat.Nlink) case "dir": - // nothing to do case "symlink": node.LinkTarget, err = os.Readlink(path) case "dev": @@ -51,11 +46,9 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) (err error) { case "chardev": node.Device = uint64(stat.Rdev) case "fifo": - // nothing to do case "socket": - // nothing to do default: - panic(fmt.Sprintf("invalid node type %q", node.Type)) + err = fmt.Errorf("invalid node type %q", node.Type) } return err @@ -74,27 +67,22 @@ func (node *Node) createFifoAt(path string) error { } 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) + tpe := nodeTypeFromFileInfo(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) + extendedStat := fi.Sys().(*syscall.Stat_t) + changeTime := time.Unix(extendedStat.Ctimespec.Unix()) + inode := extendedStat.Ino + size := uint64(extendedStat.Size) - 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 || @@ -103,7 +91,6 @@ func (node *Node) isNewer(path string, fi os.FileInfo) bool { return false } - // otherwise the node is assumed to have the same content debug.Log("node.isNewer", "node %v is not newer", path) return false } diff --git a/node_linux.go b/node_linux.go index aef5c1e3a..812621d5c 100644 --- a/node_linux.go +++ b/node_linux.go @@ -30,16 +30,10 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) error { node.UID = stat.Uid node.GID = stat.Gid - // TODO: cache uid lookup if u, err := user.LookupId(strconv.Itoa(int(stat.Uid))); err == nil { node.User = u.Username } - // TODO: implement getgrnam() or use https://github.com/kless/osutil - // if g, nil := user.LookupId(strconv.Itoa(int(stat.Uid))); err == nil { - // node.User = u.Username - // } - node.Inode = stat.Ino var err error @@ -49,7 +43,6 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) error { node.Size = uint64(stat.Size) node.Links = uint64(stat.Nlink) case "dir": - // nothing to do case "symlink": node.LinkTarget, err = os.Readlink(path) case "dev": @@ -57,11 +50,9 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) error { case "chardev": node.Device = stat.Rdev case "fifo": - // nothing to do case "socket": - // nothing to do default: - panic(fmt.Sprintf("invalid node type %q", node.Type)) + err = fmt.Errorf("invalid node type %q", node.Type) } return err @@ -80,27 +71,22 @@ func (node *Node) createFifoAt(path string) error { } 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) + tpe := nodeTypeFromFileInfo(fi) if node.Name != fi.Name() || node.Type != tpe { debug.Log("node.isNewer", "node %v is newer: name or type changed", path) return true } - // collect extended stat - stat := fi.Sys().(*syscall.Stat_t) + extendedStat := fi.Sys().(*syscall.Stat_t) + changeTime := time.Unix(extendedStat.Ctim.Unix()) + inode := extendedStat.Ino + size := uint64(extendedStat.Size) - changeTime := time.Unix(stat.Ctim.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 || @@ -109,7 +95,6 @@ func (node *Node) isNewer(path string, fi os.FileInfo) bool { return true } - // otherwise the node is assumed to have the same content debug.Log("node.isNewer", "node %v is not newer", path) return false } diff --git a/restorer.go b/restorer.go index 39ac01379..e7a8d18ca 100644 --- a/restorer.go +++ b/restorer.go @@ -47,7 +47,7 @@ func (res *Restorer) to(dst string, dir string, treeBlob server.Blob) error { if res.Filter == nil || res.Filter(filepath.Join(dir, node.Name), dstpath, node) { - err := CreateNodeAt(node, tree.Map, res.s, dstpath) + err := node.CreateAt(dstpath, tree.Map, res.s) // Did it fail because of ENOENT? if arrar.Check(err, func(err error) bool { @@ -60,7 +60,7 @@ func (res *Restorer) to(dst string, dir string, treeBlob server.Blob) error { // Create parent directories and retry err = os.MkdirAll(filepath.Dir(dstpath), 0700) if err == nil || err == os.ErrExist { - err = CreateNodeAt(node, tree.Map, res.s, dstpath) + err = node.CreateAt(dstpath, tree.Map, res.s) } } From 91a2a5f90a941aa3b2c00d64d5e79f7a6eca718d Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 29 Apr 2015 03:31:07 +0000 Subject: [PATCH 2/4] Move isNewer() into node.go --- node.go | 29 +++++++++++++++++++++++++++++ node_darwin.go | 29 ++--------------------------- node_linux.go | 31 ++----------------------------- 3 files changed, 33 insertions(+), 56 deletions(-) diff --git a/node.go b/node.go index fe62bd273..aab2aa8a8 100644 --- a/node.go +++ b/node.go @@ -10,6 +10,7 @@ import ( "github.com/juju/arrar" "github.com/restic/restic/backend" + "github.com/restic/restic/debug" "github.com/restic/restic/server" ) @@ -308,3 +309,31 @@ func (node Node) sameContent(other Node) bool { return true } + +func (node *Node) isNewer(path string, fi os.FileInfo) bool { + if node.Type != "file" { + debug.Log("node.isNewer", "node %v is newer: not file", path) + return true + } + + tpe := nodeTypeFromFileInfo(fi) + if node.Name != fi.Name() || node.Type != tpe { + debug.Log("node.isNewer", "node %v is newer: name or type changed", path) + return true + } + + extendedStat := fi.Sys().(*syscall.Stat_t) + inode := extendedStat.Ino + size := uint64(extendedStat.Size) + + if node.ModTime != fi.ModTime() || + node.ChangeTime != changeTime(extendedStat) || + node.Inode != inode || + node.Size != size { + debug.Log("node.isNewer", "node %v is newer: timestamp, size or inode changed", path) + return true + } + + debug.Log("node.isNewer", "node %v is not newer", path) + return false +} diff --git a/node_darwin.go b/node_darwin.go index ae4b0060a..666a576ff 100644 --- a/node_darwin.go +++ b/node_darwin.go @@ -66,31 +66,6 @@ func (node *Node) createFifoAt(path string) error { return syscall.Mkfifo(path, 0600) } -func (node *Node) isNewer(path string, fi os.FileInfo) bool { - if node.Type != "file" { - debug.Log("node.isNewer", "node %v is newer: not file", path) - return true - } - - tpe := nodeTypeFromFileInfo(fi) - if node.Name != fi.Name() || node.Type != tpe { - debug.Log("node.isNewer", "node %v is newer: name or type changed", path) - return false - } - - extendedStat := fi.Sys().(*syscall.Stat_t) - changeTime := time.Unix(extendedStat.Ctimespec.Unix()) - inode := extendedStat.Ino - size := uint64(extendedStat.Size) - - 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 - } - - debug.Log("node.isNewer", "node %v is not newer", path) - return false +func changeTime(stat *syscall.Stat_t) time.Unix { + return time.Unix(stat.Ctimespec.Unix()) } diff --git a/node_linux.go b/node_linux.go index 812621d5c..7ba11e943 100644 --- a/node_linux.go +++ b/node_linux.go @@ -7,8 +7,6 @@ import ( "strconv" "syscall" "time" - - "github.com/restic/restic/debug" ) func (node *Node) OpenForReading() (*os.File, error) { @@ -70,31 +68,6 @@ func (node *Node) createFifoAt(path string) error { return syscall.Mkfifo(path, 0600) } -func (node *Node) isNewer(path string, fi os.FileInfo) bool { - if node.Type != "file" { - debug.Log("node.isNewer", "node %v is newer: not file", path) - return true - } - - tpe := nodeTypeFromFileInfo(fi) - if node.Name != fi.Name() || node.Type != tpe { - debug.Log("node.isNewer", "node %v is newer: name or type changed", path) - return true - } - - extendedStat := fi.Sys().(*syscall.Stat_t) - changeTime := time.Unix(extendedStat.Ctim.Unix()) - inode := extendedStat.Ino - size := uint64(extendedStat.Size) - - if node.ModTime != fi.ModTime() || - node.ChangeTime != changeTime || - node.Inode != inode || - node.Size != size { - debug.Log("node.isNewer", "node %v is newer: timestamp, size or inode changed", path) - return true - } - - debug.Log("node.isNewer", "node %v is not newer", path) - return false +func changeTime(stat *syscall.Stat_t) time.Time { + return time.Unix(stat.Ctim.Unix()) } From 6ba11d8fb7ac6d82a846c7d8128f71691b06d927 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 29 Apr 2015 03:45:24 +0000 Subject: [PATCH 3/4] move fillExtra to node.go --- node.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ node_darwin.go | 38 ++++---------------------------------- node_linux.go | 41 ++++------------------------------------- 3 files changed, 55 insertions(+), 71 deletions(-) diff --git a/node.go b/node.go index aab2aa8a8..249edbb4a 100644 --- a/node.go +++ b/node.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "os/user" "strconv" "syscall" "time" @@ -337,3 +338,49 @@ func (node *Node) isNewer(path string, fi os.FileInfo) bool { debug.Log("node.isNewer", "node %v is not newer", path) return false } + +func (node *Node) fillUser(stat *syscall.Stat_t) error { + node.UID = stat.Uid + node.GID = stat.Gid + + u, err := user.LookupId(strconv.Itoa(int(stat.Uid))) + if err != nil { + return err + } + + node.User = u.Username + return nil +} + +func (node *Node) fillExtra(path string, fi os.FileInfo) error { + stat, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return nil + } + + node.Inode = stat.Ino + + node.fillUser(stat) + node.fillTimes(stat) + + var err error + + switch node.Type { + case "file": + node.Size = uint64(stat.Size) + node.Links = uint64(stat.Nlink) + case "dir": + case "symlink": + node.LinkTarget, err = os.Readlink(path) + case "dev": + node.fillDevice(stat) + case "chardev": + node.fillDevice(stat) + case "fifo": + case "socket": + default: + err = fmt.Errorf("invalid node type %q", node.Type) + } + + return err +} diff --git a/node_darwin.go b/node_darwin.go index 666a576ff..183f6201d 100644 --- a/node_darwin.go +++ b/node_darwin.go @@ -15,43 +15,13 @@ func (node *Node) OpenForReading() (*os.File, error) { return os.Open(node.path) } -func (node *Node) fillExtra(path string, fi os.FileInfo) error { - stat, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return nil - } - +func (node *Node) fillTimes(stat *syscall.Stat_t) { node.ChangeTime = time.Unix(stat.Ctimespec.Unix()) node.AccessTime = time.Unix(stat.Atimespec.Unix()) - node.UID = stat.Uid - node.GID = stat.Gid +} - if u, err := user.LookupId(strconv.Itoa(int(stat.Uid))); err == nil { - node.User = u.Username - } - - node.Inode = stat.Ino - - var err error - - switch node.Type { - case "file": - node.Size = uint64(stat.Size) - node.Links = uint64(stat.Nlink) - case "dir": - case "symlink": - node.LinkTarget, err = os.Readlink(path) - case "dev": - node.Device = uint64(stat.Rdev) - case "chardev": - node.Device = uint64(stat.Rdev) - case "fifo": - case "socket": - default: - err = fmt.Errorf("invalid node type %q", node.Type) - } - - return err +func (node *Node) fillDevice(stat *syscall.Stat_t) { + node.Device = uint64(stat.Rdev) } func (node *Node) createDevAt(path string) error { diff --git a/node_linux.go b/node_linux.go index 7ba11e943..c2b776be1 100644 --- a/node_linux.go +++ b/node_linux.go @@ -1,10 +1,7 @@ package restic import ( - "fmt" "os" - "os/user" - "strconv" "syscall" "time" ) @@ -17,43 +14,13 @@ func (node *Node) OpenForReading() (*os.File, error) { return file, err } -func (node *Node) fillExtra(path string, fi os.FileInfo) error { - stat, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return nil - } - +func (node *Node) fillTimes(stat *syscall.Stat_t) { node.ChangeTime = time.Unix(stat.Ctim.Unix()) node.AccessTime = time.Unix(stat.Atim.Unix()) - node.UID = stat.Uid - node.GID = stat.Gid +} - if u, err := user.LookupId(strconv.Itoa(int(stat.Uid))); err == nil { - node.User = u.Username - } - - node.Inode = stat.Ino - - var err error - - switch node.Type { - case "file": - node.Size = uint64(stat.Size) - node.Links = uint64(stat.Nlink) - case "dir": - case "symlink": - node.LinkTarget, err = os.Readlink(path) - case "dev": - node.Device = stat.Rdev - case "chardev": - node.Device = stat.Rdev - case "fifo": - case "socket": - default: - err = fmt.Errorf("invalid node type %q", node.Type) - } - - return err +func (node *Node) fillDevice(stat *syscall.Stat_t) { + node.Device = stat.Rdev } func (node *Node) createDevAt(path string) error { From adcde1988e48e17ec03e031031d5d1dd3f498852 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 29 Apr 2015 03:53:49 +0000 Subject: [PATCH 4/4] uint64(stat.Rdev) works on both platforms --- node.go | 4 ++-- node_darwin.go | 21 ++++++--------------- node_linux.go | 14 +++++--------- 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/node.go b/node.go index 249edbb4a..45a6a9be0 100644 --- a/node.go +++ b/node.go @@ -373,9 +373,9 @@ func (node *Node) fillExtra(path string, fi os.FileInfo) error { case "symlink": node.LinkTarget, err = os.Readlink(path) case "dev": - node.fillDevice(stat) + node.Device = uint64(stat.Rdev) case "chardev": - node.fillDevice(stat) + node.Device = uint64(stat.Rdev) case "fifo": case "socket": default: diff --git a/node_darwin.go b/node_darwin.go index 183f6201d..1d4a22927 100644 --- a/node_darwin.go +++ b/node_darwin.go @@ -1,29 +1,15 @@ package restic import ( - "fmt" "os" - "os/user" - "strconv" "syscall" "time" - - "github.com/restic/restic/debug" ) func (node *Node) OpenForReading() (*os.File, error) { return os.Open(node.path) } -func (node *Node) fillTimes(stat *syscall.Stat_t) { - node.ChangeTime = time.Unix(stat.Ctimespec.Unix()) - node.AccessTime = time.Unix(stat.Atimespec.Unix()) -} - -func (node *Node) fillDevice(stat *syscall.Stat_t) { - node.Device = uint64(stat.Rdev) -} - func (node *Node) createDevAt(path string) error { return syscall.Mknod(path, syscall.S_IFBLK|0600, int(node.Device)) } @@ -36,6 +22,11 @@ func (node *Node) createFifoAt(path string) error { return syscall.Mkfifo(path, 0600) } -func changeTime(stat *syscall.Stat_t) time.Unix { +func changeTime(stat *syscall.Stat_t) time.Time { return time.Unix(stat.Ctimespec.Unix()) } + +func (node *Node) fillTimes(stat *syscall.Stat_t) { + node.ChangeTime = time.Unix(stat.Ctimespec.Unix()) + node.AccessTime = time.Unix(stat.Atimespec.Unix()) +} diff --git a/node_linux.go b/node_linux.go index c2b776be1..0be72c24b 100644 --- a/node_linux.go +++ b/node_linux.go @@ -14,15 +14,6 @@ func (node *Node) OpenForReading() (*os.File, error) { return file, err } -func (node *Node) fillTimes(stat *syscall.Stat_t) { - node.ChangeTime = time.Unix(stat.Ctim.Unix()) - node.AccessTime = time.Unix(stat.Atim.Unix()) -} - -func (node *Node) fillDevice(stat *syscall.Stat_t) { - node.Device = stat.Rdev -} - func (node *Node) createDevAt(path string) error { return syscall.Mknod(path, syscall.S_IFBLK|0600, int(node.Device)) } @@ -35,6 +26,11 @@ func (node *Node) createFifoAt(path string) error { return syscall.Mkfifo(path, 0600) } +func (node *Node) fillTimes(stat *syscall.Stat_t) { + node.ChangeTime = time.Unix(stat.Ctim.Unix()) + node.AccessTime = time.Unix(stat.Atim.Unix()) +} + func changeTime(stat *syscall.Stat_t) time.Time { return time.Unix(stat.Ctim.Unix()) }