Commit 77177c5d authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Change go-fuse to use fuse.Attr rather than os.FileInfo in preparation

of the fileinfo API update.
parent 5dac7ee0
......@@ -20,7 +20,7 @@ var CheckSuccess = fuse.CheckSuccess
type StatFs struct {
fuse.DefaultFileSystem
entries map[string]*os.FileInfo
entries map[string]*fuse.Attr
dirs map[string][]fuse.DirEntry
}
......@@ -31,7 +31,9 @@ func (me *StatFs) add(name string, fi os.FileInfo) {
return
}
me.entries[name] = &fi
a := &fuse.Attr{}
a.FromFileInfo(&fi)
me.entries[name] = a
if name == "/" || name == "" {
return
}
......@@ -42,7 +44,7 @@ func (me *StatFs) add(name string, fi os.FileInfo) {
me.add(dir, os.FileInfo{Mode: fuse.S_IFDIR | 0755})
}
func (me *StatFs) GetAttr(name string, context *fuse.Context) (*os.FileInfo, fuse.Status) {
func (me *StatFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
e := me.entries[name]
if e == nil {
return nil, fuse.ENOENT
......@@ -65,7 +67,7 @@ func (me *StatFs) OpenDir(name string, context *fuse.Context) (stream chan fuse.
func NewStatFs() *StatFs {
return &StatFs{
entries: make(map[string]*os.FileInfo),
entries: make(map[string]*fuse.Attr),
dirs: make(map[string][]fuse.DirEntry),
}
}
......
......@@ -6,21 +6,20 @@ import (
"flag"
"github.com/hanwen/go-fuse/fuse"
"log"
"os"
)
type HelloFs struct {
fuse.DefaultFileSystem
}
func (me *HelloFs) GetAttr(name string, context *fuse.Context) (*os.FileInfo, fuse.Status) {
func (me *HelloFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
switch name {
case "file.txt":
return &os.FileInfo{
Mode: fuse.S_IFREG | 0644, Size: int64(len(name)),
return &fuse.Attr{
Mode: fuse.S_IFREG | 0644, Size: uint64(len(name)),
}, fuse.OK
case "":
return &os.FileInfo{
return &fuse.Attr{
Mode: fuse.S_IFDIR | 0755,
}, fuse.OK
}
......
......@@ -4,6 +4,7 @@ include $(GOROOT)/src/Make.inc
TARG=github.com/hanwen/go-fuse/fuse
MANUAL_GOFILES=api.go \
attr.go \
bufferpool.go \
copy.go \
default.go \
......
......@@ -5,7 +5,6 @@
package fuse
import (
"os"
)
// Types for users to implement.
......@@ -29,7 +28,7 @@ type FsNode interface {
Inode() *Inode
SetInode(node *Inode)
Lookup(name string, context *Context) (fi *os.FileInfo, node FsNode, code Status)
Lookup(name string, context *Context) (fi *Attr, node FsNode, code Status)
// Deletable() should return true if this inode may be
// discarded from the children list. This will be called from
......@@ -46,16 +45,16 @@ type FsNode interface {
Readlink(c *Context) ([]byte, Status)
// Namespace operations
Mknod(name string, mode uint32, dev uint32, context *Context) (fi *os.FileInfo, newNode FsNode, code Status)
Mkdir(name string, mode uint32, context *Context) (fi *os.FileInfo, newNode FsNode, code Status)
Mknod(name string, mode uint32, dev uint32, context *Context) (fi *Attr, newNode FsNode, code Status)
Mkdir(name string, mode uint32, context *Context) (fi *Attr, newNode FsNode, code Status)
Unlink(name string, context *Context) (code Status)
Rmdir(name string, context *Context) (code Status)
Symlink(name string, content string, context *Context) (fi *os.FileInfo, newNode FsNode, code Status)
Symlink(name string, content string, context *Context) (fi *Attr, newNode FsNode, code Status)
Rename(oldName string, newParent FsNode, newName string, context *Context) (code Status)
Link(name string, existing FsNode, context *Context) (fi *os.FileInfo, newNode FsNode, code Status)
Link(name string, existing FsNode, context *Context) (fi *Attr, newNode FsNode, code Status)
// Files
Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *os.FileInfo, newNode FsNode, code Status)
Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *Attr, newNode FsNode, code Status)
Open(flags uint32, context *Context) (file File, code Status)
OpenDir(context *Context) (chan DirEntry, Status)
......@@ -66,11 +65,11 @@ type FsNode interface {
ListXAttr(context *Context) (attrs []string, code Status)
// Attributes
GetAttr(file File, context *Context) (fi *os.FileInfo, code Status)
GetAttr(file File, context *Context) (fi *Attr, code Status)
Chmod(file File, perms uint32, context *Context) (code Status)
Chown(file File, uid uint32, gid uint32, context *Context) (code Status)
Truncate(file File, size uint64, context *Context) (code Status)
Utimens(file File, atime uint64, mtime uint64, context *Context) (code Status)
Utimens(file File, atime int64, mtime int64, context *Context) (code Status)
StatFs() *StatfsOut
}
......@@ -92,12 +91,12 @@ type FileSystem interface {
// If the filesystem wants to implement hard-links, it should
// return consistent non-zero FileInfo.Ino data. Using
// hardlinks incurs a performance hit.
GetAttr(name string, context *Context) (*os.FileInfo, Status)
GetAttr(name string, context *Context) (*Attr, Status)
// These should update the file's ctime too.
Chmod(name string, mode uint32, context *Context) (code Status)
Chown(name string, uid uint32, gid uint32, context *Context) (code Status)
Utimens(name string, AtimeNs uint64, MtimeNs uint64, context *Context) (code Status)
Utimens(name string, AtimeNs int64, MtimeNs int64, context *Context) (code Status)
Truncate(name string, size uint64, context *Context) (code Status)
......@@ -168,10 +167,10 @@ type File interface {
// The methods below may be called on closed files, due to
// concurrency. In that case, you should return EBADF.
Truncate(size uint64) Status
GetAttr() (*os.FileInfo, Status)
GetAttr() (*Attr, Status)
Chown(uid uint32, gid uint32) Status
Chmod(perms uint32) Status
Utimens(atimeNs uint64, mtimeNs uint64) Status
Utimens(atimeNs int64, mtimeNs int64) Status
}
// Wrap a File return in this to set FUSE flags. Also used internally
......
package fuse
import (
"log"
"os"
"syscall"
)
type FileMode uint32
func (me FileMode) String() string {
switch uint32(me) & syscall.S_IFMT {
case syscall.S_IFIFO:
return "p"
case syscall.S_IFCHR:
return "c"
case syscall.S_IFDIR:
return "d"
case syscall.S_IFBLK:
return "b"
case syscall.S_IFREG:
return "f"
case syscall.S_IFLNK:
return "l"
case syscall.S_IFSOCK:
return "s"
default:
log.Panic("Unknown mode: %o", me)
}
return "0"
}
func (me FileMode) IsFifo() bool { return (uint32(me) & syscall.S_IFMT) == syscall.S_IFIFO }
// IsChar reports whether the FileInfo describes a character special file.
func (me FileMode) IsChar() bool { return (uint32(me) & syscall.S_IFMT) == syscall.S_IFCHR }
// IsDirectory reports whether the FileInfo describes a directory.
func (me FileMode) IsDirectory() bool { return (uint32(me) & syscall.S_IFMT) == syscall.S_IFDIR }
// IsBlock reports whether the FileInfo describes a block special file.
func (me FileMode) IsBlock() bool { return (uint32(me) & syscall.S_IFMT) == syscall.S_IFBLK }
// IsRegular reports whether the FileInfo describes a regular file.
func (me FileMode) IsRegular() bool { return (uint32(me) & syscall.S_IFMT) == syscall.S_IFREG }
// IsSymlink reports whether the FileInfo describes a symbolic link.
func (me FileMode) IsSymlink() bool { return (uint32(me) & syscall.S_IFMT) == syscall.S_IFLNK }
// IsSocket reports whether the FileInfo describes a socket.
func (me FileMode) IsSocket() bool { return (uint32(me) & syscall.S_IFMT) == syscall.S_IFSOCK }
func (me *Attr) IsFifo() bool { return (uint32(me.Mode) & syscall.S_IFMT) == syscall.S_IFIFO }
// IsChar reports whether the FileInfo describes a character special file.
func (me *Attr) IsChar() bool { return (uint32(me.Mode) & syscall.S_IFMT) == syscall.S_IFCHR }
// IsDirectory reports whether the FileInfo describes a directory.
func (me *Attr) IsDirectory() bool { return (uint32(me.Mode) & syscall.S_IFMT) == syscall.S_IFDIR }
// IsBlock reports whether the FileInfo describes a block special file.
func (me *Attr) IsBlock() bool { return (uint32(me.Mode) & syscall.S_IFMT) == syscall.S_IFBLK }
// IsRegular reports whether the FileInfo describes a regular file.
func (me *Attr) IsRegular() bool { return (uint32(me.Mode) & syscall.S_IFMT) == syscall.S_IFREG }
// IsSymlink reports whether the FileInfo describes a symbolic link.
func (me *Attr) IsSymlink() bool { return (uint32(me.Mode) & syscall.S_IFMT) == syscall.S_IFLNK }
// IsSocket reports whether the FileInfo describes a socket.
func (me *Attr) IsSocket() bool { return (uint32(me.Mode) & syscall.S_IFMT) == syscall.S_IFSOCK }
func (a *Attr) Atimens() int64 {
return int64(1e9 * a.Atime) + int64(a.Atimensec)
}
func (a *Attr) Mtimens() int64 {
return int64(1e9 * a.Mtime) + int64(a.Mtimensec)
}
func (a *Attr) Ctimens() int64 {
return int64(1e9 * a.Ctime) + int64(a.Ctimensec)
}
func (a *Attr) SetTimes(atimens int64, mtimens int64, ctimens int64) {
if atimens >= 0 {
a.Atime = uint64(atimens/1e9)
a.Atimensec = uint32(atimens%1e9)
}
if mtimens >= 0 {
a.Mtime = uint64(mtimens/1e9)
a.Mtimensec = uint32(mtimens%1e9)
}
if atimens >= 0 {
a.Ctime = uint64(ctimens/1e9)
a.Ctimensec = uint32(ctimens%1e9)
}
}
func (attr *Attr) FromFileInfo(fi *os.FileInfo) {
attr.Ino = uint64(fi.Ino)
attr.Size = uint64(fi.Size)
attr.Blocks = uint64(fi.Blocks)
attr.SetTimes(fi.Atime_ns, fi.Mtime_ns, fi.Ctime_ns)
attr.Mode = fi.Mode
attr.Nlink = uint32(fi.Nlink)
attr.Uid = uint32(fi.Uid)
attr.Gid = uint32(fi.Gid)
attr.Rdev = uint32(fi.Rdev)
attr.Blksize = uint32(fi.Blksize)
}
func (a *Attr) ToFileInfo() (fi *os.FileInfo) {
return &os.FileInfo{
Ino: a.Ino,
Size: int64(a.Size),
Atime_ns: a.Atimens(),
Mtime_ns: a.Mtimens(),
Ctime_ns: a.Ctimens(),
Blocks: int64(a.Blocks),
Mode: a.Mode,
Nlink: uint64(a.Nlink),
Uid: int(a.Uid),
Gid: int(a.Gid),
Rdev: uint64(a.Rdev),
Blksize: int64(a.Blksize),
}
}
......@@ -74,6 +74,7 @@ func TestCacheFs(t *testing.T) {
c, err = ioutil.ReadFile(wd + "/mnt/file.txt")
CheckSuccess(err)
// x
if string(c) != "hello" {
t.Fatalf("Page cache skipped: expect 'hello' %q", string(c))
}
......@@ -95,9 +96,9 @@ type nonseekFs struct {
Length int
}
func (me *nonseekFs) GetAttr(name string, context *Context) (fi *os.FileInfo, status Status) {
func (me *nonseekFs) GetAttr(name string, context *Context) (fi *Attr, status Status) {
if name == "file" {
return &os.FileInfo{Mode: S_IFREG | 0644}, OK
return &Attr{Mode: S_IFREG | 0644}, OK
}
return nil, ENOENT
}
......
package fuse
import (
"os"
)
// DefaultFileSystem
func (me *DefaultFileSystem) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
func (me *DefaultFileSystem) GetAttr(name string, context *Context) (*Attr, Status) {
return nil, ENOSYS
}
......@@ -91,7 +90,7 @@ func (me *DefaultFileSystem) Create(name string, flags uint32, mode uint32, cont
return nil, ENOSYS
}
func (me *DefaultFileSystem) Utimens(name string, AtimeNs uint64, CtimeNs uint64, context *Context) (code Status) {
func (me *DefaultFileSystem) Utimens(name string, AtimeNs int64, CtimeNs int64, context *Context) (code Status) {
return ENOSYS
}
......
......@@ -2,7 +2,6 @@ package fuse
import (
"log"
"os"
)
var _ = log.Println
......@@ -34,7 +33,7 @@ func (me *DefaultFile) Release() {
}
func (me *DefaultFile) GetAttr() (*os.FileInfo, Status) {
func (me *DefaultFile) GetAttr() (*Attr, Status) {
return nil, ENOSYS
}
......@@ -42,7 +41,7 @@ func (me *DefaultFile) Fsync(*FsyncIn) (code Status) {
return ENOSYS
}
func (me *DefaultFile) Utimens(atimeNs uint64, mtimeNs uint64) Status {
func (me *DefaultFile) Utimens(atimeNs int64, mtimeNs int64) Status {
return ENOSYS
}
......
......@@ -2,7 +2,6 @@ package fuse
import (
"log"
"os"
)
var _ = log.Println
......@@ -55,7 +54,7 @@ func (me *DefaultFsNode) Inode() *Inode {
func (me *DefaultFsNode) OnForget() {
}
func (me *DefaultFsNode) Lookup(name string, context *Context) (fi *os.FileInfo, node FsNode, code Status) {
func (me *DefaultFsNode) Lookup(name string, context *Context) (fi *Attr, node FsNode, code Status) {
return nil, nil, ENOENT
}
......@@ -67,10 +66,10 @@ func (me *DefaultFsNode) Readlink(c *Context) ([]byte, Status) {
return nil, ENOSYS
}
func (me *DefaultFsNode) Mknod(name string, mode uint32, dev uint32, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *DefaultFsNode) Mknod(name string, mode uint32, dev uint32, context *Context) (fi *Attr, newNode FsNode, code Status) {
return nil, nil, ENOSYS
}
func (me *DefaultFsNode) Mkdir(name string, mode uint32, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *DefaultFsNode) Mkdir(name string, mode uint32, context *Context) (fi *Attr, newNode FsNode, code Status) {
return nil, nil, ENOSYS
}
func (me *DefaultFsNode) Unlink(name string, context *Context) (code Status) {
......@@ -79,7 +78,7 @@ func (me *DefaultFsNode) Unlink(name string, context *Context) (code Status) {
func (me *DefaultFsNode) Rmdir(name string, context *Context) (code Status) {
return ENOSYS
}
func (me *DefaultFsNode) Symlink(name string, content string, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *DefaultFsNode) Symlink(name string, content string, context *Context) (fi *Attr, newNode FsNode, code Status) {
return nil, nil, ENOSYS
}
......@@ -87,11 +86,11 @@ func (me *DefaultFsNode) Rename(oldName string, newParent FsNode, newName string
return ENOSYS
}
func (me *DefaultFsNode) Link(name string, existing FsNode, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *DefaultFsNode) Link(name string, existing FsNode, context *Context) (fi *Attr, newNode FsNode, code Status) {
return nil, nil, ENOSYS
}
func (me *DefaultFsNode) Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *os.FileInfo, newNode FsNode, code Status) {
func (me *DefaultFsNode) Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *Attr, newNode FsNode, code Status) {
return nil, nil, nil, ENOSYS
}
......@@ -132,11 +131,11 @@ func (me *DefaultFsNode) ListXAttr(context *Context) (attrs []string, code Statu
return nil, ENOSYS
}
func (me *DefaultFsNode) GetAttr(file File, context *Context) (fi *os.FileInfo, code Status) {
func (me *DefaultFsNode) GetAttr(file File, context *Context) (fi *Attr, code Status) {
if me.Inode().IsDir() {
return &os.FileInfo{Mode: S_IFDIR | 0755}, OK
return &Attr{Mode: S_IFDIR | 0755}, OK
}
return &os.FileInfo{Mode: S_IFREG | 0644}, OK
return &Attr{Mode: S_IFREG | 0644}, OK
}
func (me *DefaultFsNode) Chmod(file File, perms uint32, context *Context) (code Status) {
......@@ -151,6 +150,6 @@ func (me *DefaultFsNode) Truncate(file File, size uint64, context *Context) (cod
return ENOSYS
}
func (me *DefaultFsNode) Utimens(file File, atime uint64, mtime uint64, context *Context) (code Status) {
func (me *DefaultFsNode) Utimens(file File, atime int64, mtime int64, context *Context) (code Status) {
return ENOSYS
}
......@@ -26,8 +26,8 @@ func (me *DataFile) String() string {
return fmt.Sprintf("DataFile(%x)", me.data[:l])
}
func (me *DataFile) GetAttr() (*os.FileInfo, Status) {
return &os.FileInfo{Mode: S_IFREG | 0644, Size: int64(len(me.data))}, OK
func (me *DataFile) GetAttr() (*Attr, Status) {
return &Attr{Mode: S_IFREG | 0644, Size: uint64(len(me.data))}, OK
}
func NewDataFile(data []byte) *DataFile {
......@@ -130,12 +130,14 @@ func (me *LoopbackFile) Chown(uid uint32, gid uint32) Status {
return ToStatus(me.File.Chown(int(uid), int(gid)))
}
func (me *LoopbackFile) GetAttr() (*os.FileInfo, Status) {
func (me *LoopbackFile) GetAttr() (*Attr, Status) {
fi, err := me.File.Stat()
if err != nil {
return nil, ToStatus(err)
}
return fi, OK
a := &Attr{}
a.FromFileInfo(fi)
return a, OK
}
////////////////////////////////////////////////////////////////
......
......@@ -6,7 +6,6 @@ package fuse
import (
"log"
"os"
"path/filepath"
"strings"
"unsafe"
......@@ -77,7 +76,7 @@ func (me *FileSystemConnector) verify() {
}
// Generate EntryOut and increase the lookup count for an inode.
func (me *FileSystemConnector) childLookup(fi *os.FileInfo, fsi FsNode) (out *EntryOut) {
func (me *FileSystemConnector) childLookup(fi *Attr, fsi FsNode) (out *EntryOut) {
n := fsi.Inode()
out = n.mount.fileInfoToEntry(fi)
out.Ino = me.lookupUpdate(n)
......
......@@ -11,10 +11,14 @@ type MutableDataFile struct {
DefaultFile
data []byte
os.FileInfo
Attr
GetAttrCalled bool
}
func (me *MutableDataFile) String() string {
return "MutableDataFile"
}
func (me *MutableDataFile) Read(r *ReadIn, bp BufferPool) ([]byte, Status) {
return me.data[r.Offset : r.Offset+uint64(r.Size)], OK
}
......@@ -38,13 +42,13 @@ func (me *MutableDataFile) Release() {
}
func (me *MutableDataFile) getAttr() *os.FileInfo {
f := me.FileInfo
f.Size = int64(len(me.data))
func (me *MutableDataFile) getAttr() *Attr {
f := me.Attr
f.Size = uint64(len(me.data))
return &f
}
func (me *MutableDataFile) GetAttr() (*os.FileInfo, Status) {
func (me *MutableDataFile) GetAttr() (*Attr, Status) {
me.GetAttrCalled = true
return me.getAttr(), OK
}
......@@ -53,9 +57,8 @@ func (me *MutableDataFile) Fsync(*FsyncIn) (code Status) {
return OK
}
func (me *MutableDataFile) Utimens(atimeNs uint64, mtimeNs uint64) Status {
me.FileInfo.Atime_ns = int64(atimeNs)
me.FileInfo.Mtime_ns = int64(mtimeNs)
func (me *MutableDataFile) Utimens(atimeNs int64, mtimeNs int64) Status {
me.Attr.SetTimes(atimeNs, mtimeNs, -1)
return OK
}
......@@ -65,13 +68,13 @@ func (me *MutableDataFile) Truncate(size uint64) Status {
}
func (me *MutableDataFile) Chown(uid uint32, gid uint32) Status {
me.FileInfo.Uid = int(uid)
me.FileInfo.Gid = int(uid)
me.Attr.Uid = uid
me.Attr.Gid = gid
return OK
}
func (me *MutableDataFile) Chmod(perms uint32) Status {
me.FileInfo.Mode = (me.FileInfo.Mode &^ 07777) | perms
me.Attr.Mode = (me.Attr.Mode &^ 07777) | perms
return OK
}
......@@ -86,9 +89,9 @@ func (me *FSetAttrFs) GetXAttr(name string, attr string, context *Context) ([]by
return nil, ENODATA
}
func (me *FSetAttrFs) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
func (me *FSetAttrFs) GetAttr(name string, context *Context) (*Attr, Status) {
if name == "" {
return &os.FileInfo{Mode: S_IFDIR | 0700}, OK
return &Attr{Mode: S_IFDIR | 0700}, OK
}
if name == "file" && me.file != nil {
a := me.file.getAttr()
......@@ -109,7 +112,7 @@ func (me *FSetAttrFs) Create(name string, flags uint32, mode uint32, context *Co
if name == "file" {
f := NewFile()
me.file = f
me.file.FileInfo.Mode = mode
me.file.Attr.Mode = mode
return f, OK
}
return nil, ENOENT
......@@ -168,15 +171,15 @@ func TestFSetAttr(t *testing.T) {
err = f.Chmod(024)
CheckSuccess(err)
if fs.file.FileInfo.Mode&07777 != 024 {
if fs.file.Attr.Mode&07777 != 024 {
t.Error("chmod")
}
err = os.Chtimes(fn, 100e3, 101e3)
CheckSuccess(err)
if fs.file.FileInfo.Atime_ns != 100e3 || fs.file.FileInfo.Mtime_ns != 101e3 {
if fs.file.Attr.Atimensec != 100e3 || fs.file.Attr.Mtimensec != 101e3 {
t.Errorf("Utimens: atime %d != 100e3 mtime %d != 101e3",
fs.file.FileInfo.Atime_ns, fs.file.FileInfo.Mtime_ns)
fs.file.Attr.Atimensec, fs.file.Attr.Mtimensec)
}
newFi, err := f.Stat()
......
......@@ -2,7 +2,6 @@ package fuse
import (
"log"
"os"
"sync"
"unsafe"
)
......@@ -60,21 +59,22 @@ func (me *fileSystemMount) setOwner(attr *Attr) {
}
}
func (me *fileSystemMount) fileInfoToEntry(fi *os.FileInfo) (out *EntryOut) {
func (me *fileSystemMount) fileInfoToEntry(attr *Attr) (out *EntryOut) {
out = &EntryOut{}
out.Attr = *attr
splitNs(me.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec)
splitNs(me.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
out.Attr.FromFileInfo(fi)
me.setOwner(&out.Attr)
if !fi.IsDirectory() && fi.Nlink == 0 {
if !attr.IsDirectory() && attr.Nlink == 0 {
out.Nlink = 1
}
return out
}
func (me *fileSystemMount) fileInfoToAttr(fi *os.FileInfo, nodeId uint64) (out *AttrOut) {
func (me *fileSystemMount) fillAttr(a *Attr, nodeId uint64) (out *AttrOut) {
out = &AttrOut{}
out.Attr.FromFileInfo(fi)
out.Attr = *a
splitNs(me.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
me.setOwner(&out.Attr)
out.Ino = nodeId
......
......@@ -5,7 +5,6 @@ package fuse
import (
"bytes"
"log"
"os"
"time"
)
......@@ -15,17 +14,17 @@ func (me *FileSystemConnector) Init(fsInit *RawFsInit) {
me.fsInit = *fsInit
}
func (me *FileSystemConnector) lookupMountUpdate(mount *fileSystemMount) (fi *os.FileInfo, node *Inode, code Status) {
func (me *FileSystemConnector) lookupMountUpdate(mount *fileSystemMount) (fi *Attr, node *Inode, code Status) {
fi, code = mount.fs.Root().GetAttr(nil, nil)
if !code.Ok() {
log.Println("Root getattr should not return error", code)
return &os.FileInfo{Mode: S_IFDIR | 0755}, mount.mountInode, OK
return &Attr{Mode: S_IFDIR | 0755}, mount.mountInode, OK
}
return fi, mount.mountInode, OK
}
func (me *FileSystemConnector) internalLookup(parent *Inode, name string, context *Context) (fi *os.FileInfo, node *Inode, code Status) {
func (me *FileSystemConnector) internalLookup(parent *Inode, name string, context *Context) (fi *Attr, node *Inode, code Status) {
if subMount := me.findMount(parent, name); subMount != nil {
return me.lookupMountUpdate(subMount)
}
......@@ -89,7 +88,7 @@ func (me *FileSystemConnector) GetAttr(header *InHeader, input *GetAttrIn) (out
if !code.Ok() {
return nil, code
}
out = node.mount.fileInfoToAttr(fi, header.NodeId)
out = node.mount.fillAttr(fi, header.NodeId)
return out, OK
}
......@@ -151,17 +150,17 @@ func (me *FileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn) (out
code = node.fsInode.Truncate(f, input.Size, &header.Context)
}
if code.Ok() && (input.Valid&(FATTR_ATIME|FATTR_MTIME|FATTR_ATIME_NOW|FATTR_MTIME_NOW) != 0) {
now := uint64(0)
now := int64(0)
if input.Valid&FATTR_ATIME_NOW != 0 || input.Valid&FATTR_MTIME_NOW != 0 {
now = uint64(time.Nanoseconds())
now = time.Nanoseconds()
}
atime := uint64(input.Atime*1e9) + uint64(input.Atimensec)
atime := int64(input.Atime*1e9) + int64(input.Atimensec)
if input.Valid&FATTR_ATIME_NOW != 0 {
atime = now
}
mtime := uint64(input.Mtime*1e9) + uint64(input.Mtimensec)
mtime := int64(input.Mtime*1e9) + int64(input.Mtimensec)
if input.Valid&FATTR_MTIME_NOW != 0 {
mtime = now
}
......@@ -178,7 +177,7 @@ func (me *FileSystemConnector) SetAttr(header *InHeader, input *SetAttrIn) (out
fi, code := node.fsInode.GetAttr(f, &header.Context)
if code.Ok() {
out = node.mount.fileInfoToAttr(fi, header.NodeId)
out = node.mount.fillAttr(fi, header.NodeId)
}
return out, code
}
......
package fuse
import (
"os"
"sync"
)
......@@ -26,7 +25,7 @@ func (me *LockingFileSystem) locked() func() {
return func() { me.lock.Unlock() }
}
func (me *LockingFileSystem) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
func (me *LockingFileSystem) GetAttr(name string, context *Context) (*Attr, Status) {
defer me.locked()()
return me.FileSystem.GetAttr(name, context)
}
......@@ -115,7 +114,7 @@ func (me *LockingFileSystem) Create(name string, flags uint32, mode uint32, cont
return me.FileSystem.Create(name, flags, mode, context)
}
func (me *LockingFileSystem) Utimens(name string, AtimeNs uint64, CtimeNs uint64, context *Context) (code Status) {
func (me *LockingFileSystem) Utimens(name string, AtimeNs int64, CtimeNs int64, context *Context) (code Status) {
defer me.locked()()
return me.FileSystem.Utimens(name, AtimeNs, CtimeNs, context)
}
......
......@@ -33,9 +33,10 @@ func (me *LoopbackFileSystem) GetPath(relPath string) string {
return filepath.Join(me.Root, relPath)
}
func (me *LoopbackFileSystem) GetAttr(name string, context *Context) (fi *os.FileInfo, code Status) {
func (me *LoopbackFileSystem) GetAttr(name string, context *Context) (a *Attr, code Status) {
fullPath := me.GetPath(name)
var err error = nil
var fi *os.FileInfo
if name == "" {
// When GetAttr is called for the toplevel directory, we always want
// to look through symlinks.
......@@ -46,7 +47,9 @@ func (me *LoopbackFileSystem) GetAttr(name string, context *Context) (fi *os.Fil
if err != nil {
return nil, ToStatus(err)
}
return fi, OK
a = &Attr{}
a.FromFileInfo(fi)
return a, OK
}
func (me *LoopbackFileSystem) OpenDir(name string, context *Context) (stream chan DirEntry, status Status) {
......@@ -103,7 +106,7 @@ func (me *LoopbackFileSystem) Truncate(path string, offset uint64, context *Cont
return ToStatus(os.Truncate(me.GetPath(path), int64(offset)))
}
func (me *LoopbackFileSystem) Utimens(path string, AtimeNs uint64, MtimeNs uint64, context *Context) (code Status) {
func (me *LoopbackFileSystem) Utimens(path string, AtimeNs int64, MtimeNs int64, context *Context) (code Status) {
return ToStatus(os.Chtimes(me.GetPath(path), int64(AtimeNs), int64(MtimeNs)))
}
......
......@@ -35,9 +35,7 @@ func (me *MemNodeFs) newNode() *memNode {
id: me.nextFree,
}
now := time.Nanoseconds()
n.info.Mtime_ns = now
n.info.Atime_ns = now
n.info.Ctime_ns = now
n.info.SetTimes(now, now, now)
n.info.Mode = S_IFDIR | 0777
me.nextFree++
return n
......@@ -61,7 +59,7 @@ type memNode struct {
id int
link string
info os.FileInfo
info Attr
}
func (me *memNode) newNode(isdir bool) *memNode {
......@@ -82,7 +80,7 @@ func (me *memNode) Readlink(c *Context) ([]byte, Status) {
return []byte(me.link), OK
}
func (me *memNode) Mkdir(name string, mode uint32, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *memNode) Mkdir(name string, mode uint32, context *Context) (fi *Attr, newNode FsNode, code Status) {
n := me.newNode(true)
n.info.Mode = mode | S_IFDIR
me.Inode().AddChild(name, n.Inode())
......@@ -101,7 +99,7 @@ func (me *memNode) Rmdir(name string, context *Context) (code Status) {
return me.Unlink(name, context)
}
func (me *memNode) Symlink(name string, content string, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *memNode) Symlink(name string, content string, context *Context) (fi *Attr, newNode FsNode, code Status) {
n := me.newNode(false)
n.info.Mode = S_IFLNK | 0777
n.link = content
......@@ -117,13 +115,13 @@ func (me *memNode) Rename(oldName string, newParent FsNode, newName string, cont
return OK
}
func (me *memNode) Link(name string, existing FsNode, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *memNode) Link(name string, existing FsNode, context *Context) (fi *Attr, newNode FsNode, code Status) {
me.Inode().AddChild(name, existing.Inode())
fi, code = existing.GetAttr(nil, context)
return fi, existing, code
}
func (me *memNode) Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *os.FileInfo, newNode FsNode, code Status) {
func (me *memNode) Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *Attr, newNode FsNode, code Status) {
n := me.newNode(false)
n.info.Mode = mode | S_IFREG
......@@ -172,7 +170,7 @@ func (me *memNode) Open(flags uint32, context *Context) (file File, code Status)
return me.newFile(f), OK
}
func (me *memNode) GetAttr(file File, context *Context) (fi *os.FileInfo, code Status) {
func (me *memNode) GetAttr(file File, context *Context) (fi *Attr, code Status) {
return &me.info, OK
}
......@@ -184,29 +182,27 @@ func (me *memNode) Truncate(file File, size uint64, context *Context) (code Stat
code = ToStatus(err)
}
if code.Ok() {
me.info.Ctime_ns = time.Nanoseconds()
me.info.SetTimes(-1, -1, time.Nanoseconds())
// TODO - should update mtime too?
me.info.Size = int64(size)
me.info.Size = size
}
return code
}
func (me *memNode) Utimens(file File, atime uint64, mtime uint64, context *Context) (code Status) {
me.info.Atime_ns = int64(atime)
me.info.Mtime_ns = int64(mtime)
me.info.Ctime_ns = time.Nanoseconds()
func (me *memNode) Utimens(file File, atime int64, mtime int64, context *Context) (code Status) {
me.info.SetTimes(int64(atime), int64(mtime), time.Nanoseconds())
return OK
}
func (me *memNode) Chmod(file File, perms uint32, context *Context) (code Status) {
me.info.Mode = (me.info.Mode ^ 07777) | perms
me.info.Ctime_ns = time.Nanoseconds()
me.info.SetTimes(-1, -1, time.Nanoseconds())
return OK
}
func (me *memNode) Chown(file File, uid uint32, gid uint32, context *Context) (code Status) {
me.info.Uid = int(uid)
me.info.Gid = int(gid)
me.info.Ctime_ns = time.Nanoseconds()
me.info.Uid = uid
me.info.Gid = gid
me.info.SetTimes(-1, -1, time.Nanoseconds())
return OK
}
......@@ -55,28 +55,6 @@ func splitNs(time float64, secs *uint64, nsecs *uint32) {
*secs = uint64(math.Trunc(time))
}
func (attr *Attr) FromFileInfo(fi *os.FileInfo) {
attr.Ino = uint64(fi.Ino)
attr.Size = uint64(fi.Size)
attr.Blocks = uint64(fi.Blocks)
attr.Atime = uint64(fi.Atime_ns / 1e9)
attr.Atimensec = uint32(fi.Atime_ns % 1e9)
attr.Mtime = uint64(fi.Mtime_ns / 1e9)
attr.Mtimensec = uint32(fi.Mtime_ns % 1e9)
attr.Ctime = uint64(fi.Ctime_ns / 1e9)
attr.Ctimensec = uint32(fi.Ctime_ns % 1e9)
attr.Mode = fi.Mode
attr.Nlink = uint32(fi.Nlink)
attr.Uid = uint32(fi.Uid)
attr.Gid = uint32(fi.Gid)
attr.Rdev = uint32(fi.Rdev)
attr.Blksize = uint32(fi.Blksize)
}
// TODO - expose in Go's syscall package.
func writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
n1, _, e1 := syscall.Syscall(
......
......@@ -11,19 +11,19 @@ var _ = log.Println
type NotifyFs struct {
DefaultFileSystem
size int64
size uint64
exist bool
}
func (me *NotifyFs) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
func (me *NotifyFs) GetAttr(name string, context *Context) (*Attr, Status) {
if name == "" {
return &os.FileInfo{Mode: S_IFDIR | 0755}, OK
return &Attr{Mode: S_IFDIR | 0755}, OK
}
if name == "file" || (name == "dir/file" && me.exist) {
return &os.FileInfo{Mode: S_IFREG | 0644, Size: me.size}, OK
return &Attr{Mode: S_IFREG | 0644, Size: me.size}, OK
}
if name == "dir" {
return &os.FileInfo{Mode: S_IFDIR | 0755}, OK
return &Attr{Mode: S_IFDIR | 0755}, OK
}
return nil, ENOENT
}
......
......@@ -12,17 +12,18 @@ type ownerFs struct {
const _RANDOM_OWNER = 31415265
func (me *ownerFs) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
func (me *ownerFs) GetAttr(name string, context *Context) (*Attr, Status) {
if name == "" {
return &os.FileInfo{
return &Attr{
Mode: S_IFDIR | 0755,
}, OK
}
return &os.FileInfo{
a := &Attr{
Mode: S_IFREG | 0644,
Uid: _RANDOM_OWNER,
Gid: _RANDOM_OWNER,
}, OK
}
a.Uid = _RANDOM_OWNER
a.Gid = _RANDOM_OWNER
return a, OK
}
func setupOwnerTest(opts *FileSystemOptions) (workdir string, cleanup func()) {
......
......@@ -3,7 +3,6 @@ package fuse
import (
"fmt"
"log"
"os"
"path/filepath"
"sync"
)
......@@ -218,7 +217,7 @@ func (me *pathInode) RLockTree() func() {
return func() { me.pathFs.pathLock.RUnlock() }
}
func (me *pathInode) fillNewChildAttr(path string, child *pathInode, c *Context) (fi *os.FileInfo, code Status) {
func (me *pathInode) fillNewChildAttr(path string, child *pathInode, c *Context) (fi *Attr, code Status) {
fi, _ = me.fs.GetAttr(path, c)
if fi != nil && fi.Ino > 0 {
child.clientInode = fi.Ino
......@@ -378,7 +377,7 @@ func (me *pathInode) OpenDir(context *Context) (chan DirEntry, Status) {
return me.fs.OpenDir(me.GetPath(), context)
}
func (me *pathInode) Mknod(name string, mode uint32, dev uint32, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *pathInode) Mknod(name string, mode uint32, dev uint32, context *Context) (fi *Attr, newNode FsNode, code Status) {
fullPath := filepath.Join(me.GetPath(), name)
code = me.fs.Mknod(fullPath, mode, dev, context)
if code.Ok() {
......@@ -390,7 +389,7 @@ func (me *pathInode) Mknod(name string, mode uint32, dev uint32, context *Contex
return
}
func (me *pathInode) Mkdir(name string, mode uint32, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *pathInode) Mkdir(name string, mode uint32, context *Context) (fi *Attr, newNode FsNode, code Status) {
fullPath := filepath.Join(me.GetPath(), name)
code = me.fs.Mkdir(fullPath, mode, context)
if code.Ok() {
......@@ -418,7 +417,7 @@ func (me *pathInode) Rmdir(name string, context *Context) (code Status) {
return code
}
func (me *pathInode) Symlink(name string, content string, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *pathInode) Symlink(name string, content string, context *Context) (fi *Attr, newNode FsNode, code Status) {
fullPath := filepath.Join(me.GetPath(), name)
code = me.fs.Symlink(content, fullPath, context)
if code.Ok() {
......@@ -443,7 +442,7 @@ func (me *pathInode) Rename(oldName string, newParent FsNode, newName string, co
return code
}
func (me *pathInode) Link(name string, existingFsnode FsNode, context *Context) (fi *os.FileInfo, newNode FsNode, code Status) {
func (me *pathInode) Link(name string, existingFsnode FsNode, context *Context) (fi *Attr, newNode FsNode, code Status) {
if !me.pathFs.options.ClientInodes {
return nil, nil, ENOSYS
}
......@@ -470,7 +469,7 @@ func (me *pathInode) Link(name string, existingFsnode FsNode, context *Context)
return
}
func (me *pathInode) Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *os.FileInfo, newNode FsNode, code Status) {
func (me *pathInode) Create(name string, flags uint32, mode uint32, context *Context) (file File, fi *Attr, newNode FsNode, code Status) {
fullPath := filepath.Join(me.GetPath(), name)
file, code = me.fs.Create(fullPath, flags, mode, context)
if code.Ok() {
......@@ -502,7 +501,7 @@ func (me *pathInode) Open(flags uint32, context *Context) (file File, code Statu
return
}
func (me *pathInode) Lookup(name string, context *Context) (fi *os.FileInfo, node FsNode, code Status) {
func (me *pathInode) Lookup(name string, context *Context) (fi *Attr, node FsNode, code Status) {
fullPath := filepath.Join(me.GetPath(), name)
fi, code = me.fs.GetAttr(fullPath, context)
if code.Ok() {
......@@ -512,7 +511,7 @@ func (me *pathInode) Lookup(name string, context *Context) (fi *os.FileInfo, nod
return
}
func (me *pathInode) findChild(fi *os.FileInfo, name string, fullPath string) (out *pathInode) {
func (me *pathInode) findChild(fi *Attr, name string, fullPath string) (out *pathInode) {
if fi.Ino > 0 {
unlock := me.RLockTree()
v := me.pathFs.clientInodeMap[fi.Ino]
......@@ -535,7 +534,7 @@ func (me *pathInode) findChild(fi *os.FileInfo, name string, fullPath string) (o
return out
}
func (me *pathInode) GetAttr(file File, context *Context) (fi *os.FileInfo, code Status) {
func (me *pathInode) GetAttr(file File, context *Context) (fi *Attr, code Status) {
if file == nil {
// called on a deleted files.
file = me.inode.AnyFile()
......@@ -606,7 +605,7 @@ func (me *pathInode) Truncate(file File, size uint64, context *Context) (code St
return code
}
func (me *pathInode) Utimens(file File, atime uint64, mtime uint64, context *Context) (code Status) {
func (me *pathInode) Utimens(file File, atime int64, mtime int64, context *Context) (code Status) {
files := me.inode.Files(O_ANYWRITE)
for _, f := range files {
// TODO - pass context
......
......@@ -2,7 +2,6 @@ package fuse
import (
"fmt"
"os"
"path/filepath"
)
......@@ -16,7 +15,7 @@ func (me *PrefixFileSystem) prefixed(n string) string {
return filepath.Join(me.Prefix, n)
}
func (me *PrefixFileSystem) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
func (me *PrefixFileSystem) GetAttr(name string, context *Context) (*Attr, Status) {
return me.FileSystem.GetAttr(me.prefixed(name), context)
}
......@@ -88,7 +87,7 @@ func (me *PrefixFileSystem) Create(name string, flags uint32, mode uint32, conte
return me.FileSystem.Create(me.prefixed(name), flags, mode, context)
}
func (me *PrefixFileSystem) Utimens(name string, AtimeNs uint64, CtimeNs uint64, context *Context) (code Status) {
func (me *PrefixFileSystem) Utimens(name string, AtimeNs int64, CtimeNs int64, context *Context) (code Status) {
return me.FileSystem.Utimens(me.prefixed(name), AtimeNs, CtimeNs, context)
}
......
......@@ -2,7 +2,6 @@ package fuse
import (
"fmt"
"os"
)
// This is a wrapper that only exposes read-only operations.
......@@ -10,7 +9,7 @@ type ReadonlyFileSystem struct {
FileSystem
}
func (me *ReadonlyFileSystem) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
func (me *ReadonlyFileSystem) GetAttr(name string, context *Context) (*Attr, Status) {
return me.FileSystem.GetAttr(name, context)
}
......@@ -90,7 +89,7 @@ func (me *ReadonlyFileSystem) Create(name string, flags uint32, mode uint32, con
return nil, EPERM
}
func (me *ReadonlyFileSystem) Utimens(name string, AtimeNs uint64, CtimeNs uint64, context *Context) (code Status) {
func (me *ReadonlyFileSystem) Utimens(name string, AtimeNs int64, CtimeNs int64, context *Context) (code Status) {
return EPERM
}
......
......@@ -26,8 +26,8 @@ func NewXAttrFs(nm string, m map[string][]byte) *XAttrTestFs {
return x
}
func (me *XAttrTestFs) GetAttr(name string, context *Context) (*os.FileInfo, Status) {
a := &os.FileInfo{}
func (me *XAttrTestFs) GetAttr(name string, context *Context) (*Attr, Status) {
a := &Attr{}
if name == "" || name == "/" {
a.Mode = S_IFDIR | 0700
return a, OK
......
......@@ -257,31 +257,31 @@ func (me *AutoUnionFs) GetXAttr(name string, attr string, context *fuse.Context)
return nil, fuse.ENODATA
}
func (me *AutoUnionFs) GetAttr(path string, context *fuse.Context) (*os.FileInfo, fuse.Status) {
func (me *AutoUnionFs) GetAttr(path string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if path == "" || path == _CONFIG || path == _STATUS {
a := &os.FileInfo{
a := &fuse.Attr{
Mode: fuse.S_IFDIR | 0755,
}
return a, fuse.OK
}
if path == filepath.Join(_STATUS, _VERSION) {
a := &os.FileInfo{
a := &fuse.Attr{
Mode: fuse.S_IFREG | 0644,
Size: int64(len(fuse.Version())),
Size: uint64(len(fuse.Version())),
}
return a, fuse.OK
}
if path == filepath.Join(_STATUS, _ROOT) {
a := &os.FileInfo{
a := &fuse.Attr{
Mode: syscall.S_IFLNK | 0644,
}
return a, fuse.OK
}
if path == filepath.Join(_CONFIG, _SCAN_CONFIG) {
a := &os.FileInfo{
a := &fuse.Attr{
Mode: fuse.S_IFREG | 0644,
}
return a, fuse.OK
......@@ -295,7 +295,7 @@ func (me *AutoUnionFs) GetAttr(path string, context *fuse.Context) (*os.FileInfo
return nil, fuse.ENOENT
}
a := &os.FileInfo{
a := &fuse.Attr{
Mode: syscall.S_IFLNK | 0644,
}
return a, fuse.OK
......
......@@ -4,7 +4,6 @@ import (
"fmt"
"github.com/hanwen/go-fuse/fuse"
"log"
"os"
"strings"
)
......@@ -13,7 +12,7 @@ var _ = fmt.Println
const _XATTRSEP = "@XATTR@"
type attrResponse struct {
*os.FileInfo
*fuse.Attr
fuse.Status
}
......@@ -63,7 +62,7 @@ func readDir(fs fuse.FileSystem, name string) *dirResponse {
func getAttr(fs fuse.FileSystem, name string) *attrResponse {
a, code := fs.GetAttr(name, nil)
return &attrResponse{
FileInfo: a,
Attr: a,
Status: code,
}
}
......@@ -113,15 +112,15 @@ func (me *CachingFileSystem) DropCache() {
}
}
func (me *CachingFileSystem) GetAttr(name string, context *fuse.Context) (*os.FileInfo, fuse.Status) {
func (me *CachingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if name == _DROP_CACHE {
return &os.FileInfo{
return &fuse.Attr{
Mode: fuse.S_IFREG | 0777,
}, fuse.OK
}
r := me.attributes.Get(name).(*attrResponse)
return r.FileInfo, r.Status
return r.Attr, r.Status
}
func (me *CachingFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
......
......@@ -152,21 +152,13 @@ func (me *UnionFs) getBranch(name string) branchResult {
}
type branchResult struct {
attr *os.FileInfo
attr *fuse.Attr
code fuse.Status
branch int
}
func printFileInfo(me *os.FileInfo) string {
return fmt.Sprintf(
"{0%o S=%d L=%d %d:%d %d*%d %d:%d "+
"A %.09f M %.09f C %.09f}",
me.Mode, me.Size, me.Nlink, me.Uid, me.Gid, me.Blocks, me.Blksize, me.Rdev, me.Ino,
float64(me.Atime_ns)*1e-9, float64(me.Mtime_ns)*1e-9, float64(me.Ctime_ns)*1e-9)
}
func (me branchResult) String() string {
return fmt.Sprintf("{%s %v branch %d}", printFileInfo(me.attr), me.code, me.branch)
return fmt.Sprintf("{%v %v branch %d}", me.attr, me.code, me.branch)
}
func (me *UnionFs) getBranchAttrNoCache(name string) branchResult {
......@@ -237,7 +229,7 @@ func (me *UnionFs) putDeletion(name string) (code fuse.Status) {
// Is there a WriteStringToFileOrDie ?
writable := me.fileSystems[0]
fi, code := writable.GetAttr(marker, nil)
if code.Ok() && fi.Size == int64(len(name)) {
if code.Ok() && fi.Size == uint64(len(name)) {
return fuse.OK
}
......@@ -279,8 +271,8 @@ func (me *UnionFs) Promote(name string, srcResult branchResult, context *fuse.Co
code = writable.Chmod(name, srcResult.attr.Mode&07777|0200, context)
}
if code.Ok() {
code = writable.Utimens(name, uint64(srcResult.attr.Atime_ns),
uint64(srcResult.attr.Mtime_ns), context)
code = writable.Utimens(name, srcResult.attr.Atimens(),
srcResult.attr.Mtimens(), context)
}
files := me.nodeFs.AllFiles(name, 0)
......@@ -422,7 +414,7 @@ func (me *UnionFs) Mkdir(path string, mode uint32, context *fuse.Context) (code
}
if code.Ok() {
me.removeDeletion(path)
attr := &os.FileInfo{
attr := &fuse.Attr{
Mode: fuse.S_IFDIR | mode,
}
me.branchCache.Set(path, branchResult{attr, fuse.OK, 0})
......@@ -467,16 +459,15 @@ func (me *UnionFs) Truncate(path string, size uint64, context *fuse.Context) (co
code = me.fileSystems[0].Truncate(path, size, context)
}
if code.Ok() {
r.attr.Size = int64(size)
r.attr.Size = size
now := time.Nanoseconds()
r.attr.Mtime_ns = now
r.attr.Ctime_ns = now
r.attr.SetTimes(-1, now, now)
me.branchCache.Set(path, r)
}
return code
}
func (me *UnionFs) Utimens(name string, atime uint64, mtime uint64, context *fuse.Context) (code fuse.Status) {
func (me *UnionFs) Utimens(name string, atime int64, mtime int64, context *fuse.Context) (code fuse.Status) {
name = stripSlash(name)
r := me.getBranch(name)
......@@ -489,9 +480,7 @@ func (me *UnionFs) Utimens(name string, atime uint64, mtime uint64, context *fus
code = me.fileSystems[0].Utimens(name, atime, mtime, context)
}
if code.Ok() {
r.attr.Atime_ns = int64(atime)
r.attr.Mtime_ns = int64(mtime)
r.attr.Ctime_ns = time.Nanoseconds()
r.attr.SetTimes(atime, mtime, time.Nanoseconds())
me.branchCache.Set(name, r)
}
return code
......@@ -508,7 +497,7 @@ func (me *UnionFs) Chown(name string, uid uint32, gid uint32, context *fuse.Cont
return fuse.EPERM
}
if r.attr.Uid != int(uid) || r.attr.Gid != int(gid) {
if r.attr.Uid != uid || r.attr.Gid != gid {
if r.branch > 0 {
code := me.Promote(name, r, context)
if code != fuse.OK {
......@@ -518,9 +507,9 @@ func (me *UnionFs) Chown(name string, uid uint32, gid uint32, context *fuse.Cont
}
me.fileSystems[0].Chown(name, uid, gid, context)
}
r.attr.Uid = int(uid)
r.attr.Gid = int(gid)
r.attr.Ctime_ns = time.Nanoseconds()
r.attr.Uid = uid
r.attr.Gid = gid
r.attr.SetTimes(-1, -1, time.Nanoseconds())
me.branchCache.Set(name, r)
return fuse.OK
}
......@@ -551,7 +540,7 @@ func (me *UnionFs) Chmod(name string, mode uint32, context *fuse.Context) (code
me.fileSystems[0].Chmod(name, mode, context)
}
r.attr.Mode = (r.attr.Mode &^ permMask) | mode
r.attr.Ctime_ns = time.Nanoseconds()
r.attr.SetTimes(-1, -1, time.Nanoseconds())
me.branchCache.Set(name, r)
return fuse.OK
}
......@@ -638,7 +627,7 @@ func (me *UnionFs) promoteDirsTo(filename string) fuse.Status {
return fuse.EPERM
}
me.fileSystems[0].Utimens(d, uint64(r.attr.Atime_ns), uint64(r.attr.Mtime_ns), nil)
me.fileSystems[0].Utimens(d, r.attr.Atimens(), r.attr.Mtimens(), nil)
r.branch = 0
me.branchCache.Set(d, r)
}
......@@ -658,22 +647,21 @@ func (me *UnionFs) Create(name string, flags uint32, mode uint32, context *fuse.
me.removeDeletion(name)
now := time.Nanoseconds()
a := os.FileInfo{
a := fuse.Attr{
Mode: fuse.S_IFREG | mode,
Ctime_ns: now,
Mtime_ns: now,
}
a.SetTimes(-1, now, now)
me.branchCache.Set(name, branchResult{&a, fuse.OK, 0})
}
return fuseFile, code
}
func (me *UnionFs) GetAttr(name string, context *fuse.Context) (a *os.FileInfo, s fuse.Status) {
func (me *UnionFs) GetAttr(name string, context *fuse.Context) (a *fuse.Attr, s fuse.Status) {
if name == _READONLY {
return nil, fuse.ENOENT
}
if name == _DROP_CACHE {
return &os.FileInfo{
return &fuse.Attr{
Mode: fuse.S_IFREG | 0777,
}, fuse.OK
}
......@@ -949,7 +937,7 @@ func (me *UnionFs) Open(name string, flags uint32, context *fuse.Context) (fuseF
return nil, code
}
r.branch = 0
r.attr.Mtime_ns = time.Nanoseconds()
r.attr.SetTimes(-1, time.Nanoseconds(), -1)
me.branchCache.Set(name, r)
}
fuseFile, status = me.fileSystems[r.branch].Open(name, uint32(flags), context)
......@@ -1007,7 +995,7 @@ func (me *unionFsFile) SetInode(node *fuse.Inode) {
me.node = node
}
func (me *unionFsFile) GetAttr() (*os.FileInfo, fuse.Status) {
func (me *unionFsFile) GetAttr() (*fuse.Attr, fuse.Status) {
fi, code := me.File.GetAttr()
if fi != nil {
f := *fi
......
......@@ -3,12 +3,11 @@ package zipfs
import (
"fmt"
"github.com/hanwen/go-fuse/fuse"
"os"
"strings"
)
type MemFile interface {
Stat() *os.FileInfo
Stat() *fuse.Attr
Data() []byte
}
......@@ -63,7 +62,7 @@ func (me *memNode) Print(indent int) {
}
// We construct the tree at mount, so we never need to look anything up.
func (me *memNode) Lookup(name string, c *fuse.Context) (fi *os.FileInfo, node fuse.FsNode, code fuse.Status) {
func (me *memNode) Lookup(name string, c *fuse.Context) (fi *fuse.Attr, node fuse.FsNode, code fuse.Status) {
return nil, nil, fuse.ENOENT
}
......@@ -96,9 +95,9 @@ func (me *memNode) Deletable() bool {
return false
}
func (me *memNode) GetAttr(file fuse.File, context *fuse.Context) (*os.FileInfo, fuse.Status) {
func (me *memNode) GetAttr(file fuse.File, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if me.Inode().IsDir() {
return &os.FileInfo{
return &fuse.Attr{
Mode: fuse.S_IFDIR | 0777,
}, fuse.OK
}
......
......@@ -13,7 +13,6 @@ symlinking path/to/zipfile to /config/zipmount
import (
"github.com/hanwen/go-fuse/fuse"
"log"
"os"
"path/filepath"
"sync"
)
......@@ -76,8 +75,8 @@ func (me *MultiZipFs) OpenDir(name string, context *fuse.Context) (stream chan f
return stream, fuse.OK
}
func (me *MultiZipFs) GetAttr(name string, context *fuse.Context) (*os.FileInfo, fuse.Status) {
a := &os.FileInfo{}
func (me *MultiZipFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
a := &fuse.Attr{}
if name == "" {
// Should not write in top dir.
a.Mode = fuse.S_IFDIR | 0500
......
......@@ -16,7 +16,7 @@ const testTtl = 0.1
func setupMzfs() (mountPoint string, cleanup func()) {
fs := NewMultiZipFs()
mountPoint, _ = ioutil.TempDir("", "")
nfs := fuse.NewPathNodeFs(fs)
nfs := fuse.NewPathNodeFs(fs, nil)
state, _, err := fuse.MountNodeFileSystem(mountPoint, nfs, &fuse.FileSystemOptions{
EntryTimeout: testTtl,
AttrTimeout: testTtl,
......
......@@ -6,6 +6,7 @@ import (
"compress/bzip2"
"compress/gzip"
"fmt"
"github.com/hanwen/go-fuse/fuse"
"io"
"os"
"strings"
......@@ -16,17 +17,15 @@ var _ = fmt.Println
// TODO - handle symlinks.
func HeaderToFileInfo(h *tar.Header) *os.FileInfo {
return &os.FileInfo{
Name: h.Name,
func HeaderToFileInfo(h *tar.Header) (*fuse.Attr, string) {
a := &fuse.Attr{
Mode: uint32(h.Mode),
Uid: h.Uid,
Gid: h.Gid,
Size: h.Size,
Mtime_ns: h.Mtime,
Atime_ns: h.Atime,
Ctime_ns: h.Ctime,
Size: uint64(h.Size),
}
a.Uid = uint32(h.Uid)
a.Gid = uint32(h.Gid)
a.SetTimes(h.Atime, h.Mtime,h.Ctime)
return a, h.Name
}
type TarFile struct {
......@@ -34,8 +33,8 @@ type TarFile struct {
tar.Header
}
func (me *TarFile) Stat() *os.FileInfo {
fi := HeaderToFileInfo(&me.Header)
func (me *TarFile) Stat() *fuse.Attr {
fi, _ := HeaderToFileInfo(&me.Header)
fi.Mode |= syscall.S_IFREG
return fi
}
......
......@@ -19,11 +19,11 @@ type ZipFile struct {
*zip.File
}
func (me *ZipFile) Stat() *os.FileInfo {
func (me *ZipFile) Stat() *fuse.Attr {
// TODO - do something intelligent with timestamps.
return &os.FileInfo{
return &fuse.Attr{
Mode: fuse.S_IFREG | 0444,
Size: int64(me.File.UncompressedSize),
Size: uint64(me.File.UncompressedSize),
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment