diff --git a/cmd/cmount/fs.go b/cmd/cmount/fs.go index d3f992514..ae91e91ab 100644 --- a/cmd/cmount/fs.go +++ b/cmd/cmount/fs.go @@ -289,41 +289,65 @@ func (fsys *FS) Statfs(path string, stat *fuse.Statfs_t) (errc int) { return 0 } -// Open opens a file -func (fsys *FS) Open(path string, flags int) (errc int, fh uint64) { - defer log.Trace(path, "flags=0x%X", flags)("errc=%d, fh=0x%X", &errc, &fh) +// OpenEx opens a file +func (fsys *FS) OpenEx(path string, fi *fuse.FileInfo_t) (errc int) { + defer log.Trace(path, "flags=0x%X", fi.Flags)("errc=%d, fh=0x%X", &errc, &fi.Fh) + fi.Fh = fhUnset // translate the fuse flags to os flags - flags = translateOpenFlags(flags) + flags := translateOpenFlags(fi.Flags) handle, err := fsys.VFS.OpenFile(path, flags, 0777) if err != nil { - return translateError(err), fhUnset + return translateError(err) } - // FIXME add support for unknown length files setting direct_io - // See: https://github.com/billziss-gh/cgofuse/issues/38 + // If size unknown then use direct io to read + if entry := handle.Node().DirEntry(); entry != nil && entry.Size() < 0 { + fi.DirectIo = true + } - return 0, fsys.openHandle(handle) + fi.Fh = fsys.openHandle(handle) + return 0 +} + +// Open opens a file +func (fsys *FS) Open(path string, flags int) (errc int, fh uint64) { + var fi = fuse.FileInfo_t{ + Flags: flags, + } + errc = fsys.OpenEx(path, &fi) + return errc, fi.Fh +} + +// CreateEx creates and opens a file. +func (fsys *FS) CreateEx(filePath string, mode uint32, fi *fuse.FileInfo_t) (errc int) { + defer log.Trace(filePath, "flags=0x%X, mode=0%o", fi.Flags, mode)("errc=%d, fh=0x%X", &errc, &fi.Fh) + fi.Fh = fhUnset + leaf, parentDir, errc := fsys.lookupParentDir(filePath) + if errc != 0 { + return errc + } + file, err := parentDir.Create(leaf, fi.Flags) + if err != nil { + return translateError(err) + } + // translate the fuse flags to os flags + flags := translateOpenFlags(fi.Flags) | os.O_CREATE + handle, err := file.Open(flags) + if err != nil { + return translateError(err) + } + fi.Fh = fsys.openHandle(handle) + return 0 } // Create creates and opens a file. func (fsys *FS) Create(filePath string, flags int, mode uint32) (errc int, fh uint64) { - defer log.Trace(filePath, "flags=0x%X, mode=0%o", flags, mode)("errc=%d, fh=0x%X", &errc, &fh) - leaf, parentDir, errc := fsys.lookupParentDir(filePath) - if errc != 0 { - return errc, fhUnset + var fi = fuse.FileInfo_t{ + Flags: flags, } - file, err := parentDir.Create(leaf, flags) - if err != nil { - return translateError(err), fhUnset - } - // translate the fuse flags to os flags - flags = translateOpenFlags(flags) | os.O_CREATE - handle, err := file.Open(flags) - if err != nil { - return translateError(err), fhUnset - } - return 0, fsys.openHandle(handle) + errc = fsys.CreateEx(filePath, mode, &fi) + return errc, fi.Fh } // Truncate truncates a file to size @@ -594,3 +618,12 @@ func translateOpenFlags(inFlags int) (outFlags int) { // NB O_SYNC isn't defined by fuse return outFlags } + +// Make sure interfaces are satisfied +var ( + _ fuse.FileSystemInterface = (*FS)(nil) + _ fuse.FileSystemOpenEx = (*FS)(nil) + //_ fuse.FileSystemChflags = (*FS)(nil) + //_ fuse.FileSystemSetcrtime = (*FS)(nil) + //_ fuse.FileSystemSetchgtime = (*FS)(nil) +)