diff --git a/file_system.go b/file_system.go index d67fcee..56ccac2 100644 --- a/file_system.go +++ b/file_system.go @@ -433,7 +433,10 @@ type SetInodeAttributesRequest struct { Inode InodeID // The attributes to modify, or nil for attributes that don't need a change. - Size *uint64 + Size *uint64 + Mode *os.FileMode + Atime *time.Time + Mtime *time.Time } type SetInodeAttributesResponse struct { diff --git a/samples/memfs/fs.go b/samples/memfs/fs.go index 730636f..4a752a6 100644 --- a/samples/memfs/fs.go +++ b/samples/memfs/fs.go @@ -281,7 +281,7 @@ func (fs *memFS) SetInodeAttributes( defer inode.mu.Unlock() // Handle the request. - inode.SetAttributes(req.Size) + inode.SetAttributes(req.Size, req.Mode, req.Mtime) // Fill in the response. resp.Attributes = inode.attributes diff --git a/samples/memfs/inode.go b/samples/memfs/inode.go index a878fcc..e906545 100644 --- a/samples/memfs/inode.go +++ b/samples/memfs/inode.go @@ -18,6 +18,7 @@ import ( "fmt" "io" "os" + "time" "github.com/jacobsa/fuse" "github.com/jacobsa/fuse/fuseutil" @@ -373,7 +374,10 @@ func (inode *inode) WriteAt(p []byte, off int64) (n int, err error) { // Update attributes from non-nil parameters. // // EXCLUSIVE_LOCKS_REQUIRED(inode.mu) -func (inode *inode) SetAttributes(size *uint64) { +func (inode *inode) SetAttributes( + size *uint64, + mode *os.FileMode, + mtime *time.Time) { // Update the modification time. inode.attributes.Mtime = inode.clock.Now() @@ -392,4 +396,14 @@ func (inode *inode) SetAttributes(size *uint64) { // Update attributes. inode.attributes.Size = *size } + + // Change mode? + if mode != nil { + inode.attributes.Mode = *mode + } + + // Change mtime? + if mtime != nil { + inode.attributes.Mtime = *mtime + } } diff --git a/samples/memfs/memfs_test.go b/samples/memfs/memfs_test.go index 6bd4252..9c3d5ba 100644 --- a/samples/memfs/memfs_test.go +++ b/samples/memfs/memfs_test.go @@ -859,7 +859,6 @@ func (t *MemFSTest) ReadsPastEndOfFile() { func (t *MemFSTest) Truncate_Smaller() { var err error - fileName := path.Join(t.mfs.Dir(), "foo") // Create a file. @@ -888,7 +887,6 @@ func (t *MemFSTest) Truncate_Smaller() { func (t *MemFSTest) Truncate_SameSize() { var err error - fileName := path.Join(t.mfs.Dir(), "foo") // Create a file. @@ -917,7 +915,6 @@ func (t *MemFSTest) Truncate_SameSize() { func (t *MemFSTest) Truncate_Larger() { var err error - fileName := path.Join(t.mfs.Dir(), "foo") // Create a file. @@ -945,9 +942,38 @@ func (t *MemFSTest) Truncate_Larger() { } func (t *MemFSTest) Chmod() { - AssertTrue(false, "TODO") + var err error + fileName := path.Join(t.mfs.Dir(), "foo") + + // Create a file. + err = ioutil.WriteFile(fileName, []byte(""), 0600) + AssertEq(nil, err) + + // Chmod it. + err = os.Chmod(fileName, 0754) + AssertEq(nil, err) + + // Stat it. + fi, err := os.Stat(fileName) + AssertEq(nil, err) + ExpectEq(os.FileMode(0754), fi.Mode()) } func (t *MemFSTest) Chtimes() { - AssertTrue(false, "TODO") + var err error + fileName := path.Join(t.mfs.Dir(), "foo") + + // Create a file. + err = ioutil.WriteFile(fileName, []byte(""), 0600) + AssertEq(nil, err) + + // Chtimes it. + expectedMtime := time.Now().Add(123 * time.Second).Round(time.Second) + err = os.Chtimes(fileName, time.Time{}, expectedMtime) + AssertEq(nil, err) + + // Stat it. + fi, err := os.Stat(fileName) + AssertEq(nil, err) + ExpectEq(0, fi.ModTime().Sub(expectedMtime)) } diff --git a/server.go b/server.go index 811c34b..28ebf3e 100644 --- a/server.go +++ b/server.go @@ -182,6 +182,18 @@ func (s *server) handleFuseRequest(fuseReq bazilfuse.Request) { req.Size = &typed.Size } + if typed.Valid&bazilfuse.SetattrMode != 0 { + req.Mode = &typed.Mode + } + + if typed.Valid&bazilfuse.SetattrAtime != 0 { + req.Atime = &typed.Atime + } + + if typed.Valid&bazilfuse.SetattrMtime != 0 { + req.Mtime = &typed.Mtime + } + // Call the file system. resp, err := s.fs.SetInodeAttributes(ctx, req) if err != nil {