Skip to content

Commit

Permalink
loopback: Utimens: enable Nsec precision for dates after 1970
Browse files Browse the repository at this point in the history
syscall.NsecToTimespec is broken for dates before 1970 but works
fine otherwise.

Fix hanwen#100 as well and add a testcase.
  • Loading branch information
rfjakob committed Sep 25, 2016
1 parent 41c29e1 commit 16972fd
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 5 deletions.
11 changes: 8 additions & 3 deletions fuse/nodefs/files_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,19 @@ func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
ts[0].Nsec = _UTIME_OMIT
} else {
ts[0] = syscall.NsecToTimespec(a.UnixNano())
ts[0].Nsec = 0
if ts[0].Nsec < 0 {
// Go bug https://github.com/golang/go/issues/12777/
ts[0].Nsec = 0
}
}

if m == nil {
ts[1].Nsec = _UTIME_OMIT
} else {
ts[1] = syscall.NsecToTimespec(a.UnixNano())
ts[1].Nsec = 0
ts[1] = syscall.NsecToTimespec(m.UnixNano())
if ts[1].Nsec < 0 {
ts[1].Nsec = 0
}
}

f.lock.Lock()
Expand Down
9 changes: 7 additions & 2 deletions fuse/pathfs/loopback_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,19 @@ func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, c
ts[0].Nsec = _UTIME_OMIT
} else {
ts[0] = syscall.NsecToTimespec(a.UnixNano())
ts[0].Nsec = 0
if ts[0].Nsec < 0 {
// Go bug https://github.com/golang/go/issues/12777/
ts[0].Nsec = 0
}
}

if m == nil {
ts[1].Nsec = _UTIME_OMIT
} else {
ts[1] = syscall.NsecToTimespec(m.UnixNano())
ts[1].Nsec = 0
if ts[1].Nsec < 0 {
ts[1].Nsec = 0
}
}

err := sysUtimensat(0, fs.GetPath(path), &ts, _AT_SYMLINK_NOFOLLOW)
Expand Down
35 changes: 35 additions & 0 deletions fuse/test/loopback_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,41 @@ func TestNegativeTime(t *testing.T) {
}
}

// Setting nanoseconds should work for dates after 1970
func TestUtimesNano(t *testing.T) {
tc := NewTestCase(t)
defer tc.Cleanup()

path := tc.mountFile
err := ioutil.WriteFile(path, []byte("xyz"), 0600)
if err != nil {
t.Fatal(err)
}
ts := make([]syscall.Timespec, 2)
// atime
ts[0].Sec = 1
ts[0].Nsec = 2
// mtime
ts[1].Sec = 3
ts[1].Nsec = 4
err = syscall.UtimesNano(path, ts)
if err != nil {
t.Fatal(err)
}

var st syscall.Stat_t
err = syscall.Stat(path, &st)
if err != nil {
t.Fatal(err)
}
if st.Atim != ts[0] {
t.Errorf("Wrong atime: %v, want: %v", st.Atim, ts[0])
}
if st.Mtim != ts[1] {
t.Errorf("Wrong mtime: %v, want: %v", st.Mtim, ts[1])
}
}

func clearStatfs(s *syscall.Statfs_t) {
empty := syscall.Statfs_t{}
s.Type = 0
Expand Down

0 comments on commit 16972fd

Please sign in to comment.