summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-09-25 16:30:29 +0200
committerJakob Unterwurzacher2016-09-25 16:30:29 +0200
commitfca1b824172fee453667ce9951df7c35a9f7e6e0 (patch)
treefd0993b0d5507f6991f3d673d6f3d8606fa16505
parent8f1e51789dd29b9fae82a059e2890bf9873cdd4c (diff)
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
-rw-r--r--internal/fusefrontend/file.go50
-rw-r--r--internal/fusefrontend/fs.go7
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 {