From fca1b824172fee453667ce9951df7c35a9f7e6e0 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sun, 25 Sep 2016 16:30:29 +0200 Subject: fusefrontend: relay Utimens to go-fuse Commit af5441dcd9033e81da43ab77887a7b5aac693ab6 has caused a regression ( https://github.com/rfjakob/gocryptfs/issues/35 ) that is fixed by this commit. The go-fuse library by now has all the syscall wrappers in place to correctly handle Utimens, also for symlinks. Instead of duplicating the effort here just call into go-fuse. Closes #35 --- internal/fusefrontend/file.go | 50 +++++++------------------------------------ internal/fusefrontend/fs.go | 7 ++---- 2 files changed, 10 insertions(+), 47 deletions(-) diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index 61b1e55..a04b6af 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -33,18 +33,16 @@ type file struct { // Every FUSE entrypoint should RLock(). The only user of Lock() is // Release(), which closes the fd and sets "released" to true. fdLock sync.RWMutex - // Was the file opened O_WRONLY? writeOnly bool - // Content encryption helper contentEnc *contentenc.ContentEnc - // Inode number ino uint64 - // File header header *contentenc.FileHeader + // go-fuse nodefs.loopbackFile + loopbackFile nodefs.File } func NewFile(fd *os.File, writeOnly bool, contentEnc *contentenc.ContentEnc) (nodefs.File, fuse.Status) { @@ -57,10 +55,11 @@ func NewFile(fd *os.File, writeOnly bool, contentEnc *contentenc.ContentEnc) (no wlock.register(st.Ino) return &file{ - fd: fd, - writeOnly: writeOnly, - contentEnc: contentEnc, - ino: st.Ino, + fd: fd, + writeOnly: writeOnly, + contentEnc: contentEnc, + ino: st.Ino, + loopbackFile: nodefs.NewLoopbackFile(fd), }, fuse.OK } @@ -386,41 +385,8 @@ func (f *file) GetAttr(a *fuse.Attr) fuse.Status { return fuse.OK } -const _UTIME_OMIT = ((1 << 30) - 2) - -// utimeToTimespec converts a "time.Time" pointer as passed to Utimens to a -// Timespec that can be passed to the utimensat syscall. -func utimeToTimespec(t *time.Time) (ts syscall.Timespec) { - if t == nil { - ts.Nsec = _UTIME_OMIT - } else { - ts = syscall.NsecToTimespec(t.UnixNano()) - // For dates before 1970, NsecToTimespec incorrectly returns negative - // nanoseconds. Ticket: https://github.com/golang/go/issues/12777 - if ts.Nsec < 0 { - ts.Nsec = 0 - } - } - return ts -} - func (f *file) Utimens(a *time.Time, m *time.Time) fuse.Status { f.fdLock.RLock() defer f.fdLock.RUnlock() - - ts := make([]syscall.Timespec, 2) - ts[0] = utimeToTimespec(a) - ts[1] = utimeToTimespec(m) - - fn := fmt.Sprintf("/proc/self/fd/%d", f.fd.Fd()) - err := syscall.UtimesNano(fn, ts) - if err != nil { - tlog.Debug.Printf("UtimesNano on %q failed: %v", fn, err) - } - if err == syscall.ENOENT { - // If /proc/self/fd/X did not exist, the actual error is that the file - // descriptor was invalid. - return fuse.EBADF - } - return fuse.ToStatus(err) + return f.loopbackFile.Utimens(a, m) } diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index 1219479..bc81c37 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -234,14 +234,11 @@ func (fs *FS) Utimens(path string, a *time.Time, m *time.Time, context *fuse.Con if fs.isFiltered(path) { return fuse.EPERM } - cPath, err := fs.getBackingPath(path) + cPath, err := fs.encryptPath(path) if err != nil { return fuse.ToStatus(err) } - ts := make([]syscall.Timespec, 2) - ts[0] = utimeToTimespec(a) - ts[1] = utimeToTimespec(m) - return fuse.ToStatus(syscall.UtimesNano(cPath, ts)) + return fs.FileSystem.Utimens(cPath, a, m, context) } func (fs *FS) StatFs(path string) *fuse.StatfsOut { -- cgit v1.2.3