Some work on getting cross-version file operations working
This commit is contained in:
parent
00d1c81a6c
commit
aeb0822714
28
dir.go
28
dir.go
@ -81,29 +81,29 @@ func (vd *verDir) createDir(name string) (*verDir, error) {
|
||||
node := newVerNode(childPath, vd.node.ver, nil, NodeFlagDir|NodeFlagVer)
|
||||
dir := newVerDir(node, vd)
|
||||
vd.dirs[name] = dir
|
||||
|
||||
node.ver.meta.createNode(node.path)
|
||||
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
func (vd *verDir) createFile(name string, flags int) (*verFile, error) {
|
||||
func (vd *verDir) createFile(name string, flags fuse.OpenFlags) (*verFile, *verFileHandle, error) {
|
||||
if err := vd.version(); err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
childPath := path.Join(vd.node.path, name)
|
||||
handle, err := os.OpenFile(vd.node.ver.rebasePath(childPath), flags, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
node := newVerNode(childPath, vd.node.ver, nil, NodeFlagVer)
|
||||
file := newVerFile(node, vd)
|
||||
file.handle = handle
|
||||
vd.files[name] = file
|
||||
|
||||
handle, err := file.open(flags)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
vd.files[name] = file
|
||||
node.ver.meta.createNode(node.path)
|
||||
return file, nil
|
||||
|
||||
return file, handle, nil
|
||||
}
|
||||
|
||||
// Node
|
||||
@ -137,9 +137,11 @@ func (vd *verDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fus
|
||||
}
|
||||
} else if req.Mode.IsRegular() {
|
||||
var file *verFile
|
||||
if file, err = vd.createFile(req.Name, int(req.Flags)); err == nil {
|
||||
var vfh *verFileHandle
|
||||
if file, vfh, err = vd.createFile(req.Name, req.Flags); err == nil {
|
||||
node = file
|
||||
handle = file
|
||||
handle = handle
|
||||
resp.Handle = vfh.id
|
||||
}
|
||||
} else {
|
||||
err = errors.New("unsupported filetype")
|
||||
|
117
file.go
117
file.go
@ -23,7 +23,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"bazil.org/fuse"
|
||||
@ -36,14 +35,14 @@ import (
|
||||
//
|
||||
|
||||
type verFile struct {
|
||||
node *verNode
|
||||
inode uint64
|
||||
parent *verDir
|
||||
handle *os.File
|
||||
node *verNode
|
||||
inode uint64
|
||||
parent *verDir
|
||||
handles map[fuse.HandleID]*verFileHandle
|
||||
}
|
||||
|
||||
func newVerFile(node *verNode, parent *verDir) *verFile {
|
||||
return &verFile{node, allocInode(), parent, nil}
|
||||
return &verFile{node, allocInode(), parent, make(map[fuse.HandleID]*verFileHandle)}
|
||||
}
|
||||
|
||||
func (vf *verFile) version() error {
|
||||
@ -63,6 +62,30 @@ func (vf *verFile) version() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vf *verFile) open(flags fuse.OpenFlags) (*verFileHandle, error) {
|
||||
if !flags.IsReadOnly() {
|
||||
if err := vf.version(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
path := vf.node.rebasedPath()
|
||||
handle, err := os.OpenFile(path, int(flags), 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id := fuse.HandleID(allocHandleId())
|
||||
verHandle := &verFileHandle{vf, path, handle, id}
|
||||
vf.handles[id] = verHandle
|
||||
|
||||
return verHandle, nil
|
||||
}
|
||||
|
||||
func (vf *verFile) release(handle fuse.HandleID) {
|
||||
delete(vf.handles, handle)
|
||||
}
|
||||
|
||||
// Node
|
||||
func (vf *verFile) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||
vf.node.attr(attr)
|
||||
@ -82,54 +105,41 @@ func (vf *verFile) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *
|
||||
|
||||
// NodeOpener
|
||||
func (vf *verFile) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
||||
if vf.handle != nil {
|
||||
return nil, errors.New("attempted to open already opened file")
|
||||
}
|
||||
|
||||
if !req.Flags.IsReadOnly() {
|
||||
if err := vf.version(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
handle, err := os.OpenFile(vf.node.rebasedPath(), int(req.Flags), 0644)
|
||||
handle, err := vf.open(req.Flags)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vf.handle = handle
|
||||
return vf, nil
|
||||
}
|
||||
|
||||
// HandleReleaser
|
||||
func (vf *verFile) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
|
||||
if vf.handle == nil {
|
||||
return errors.New("attempted to release unopened file")
|
||||
}
|
||||
|
||||
vf.handle.Close()
|
||||
vf.handle = nil
|
||||
|
||||
return nil
|
||||
resp.Handle = handle.id
|
||||
return handle, nil
|
||||
}
|
||||
|
||||
// NodeFsyncer
|
||||
func (vf *verFile) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
||||
if vf.handle == nil {
|
||||
return errors.New("attempted to sync unopened file")
|
||||
for _, vfh := range vf.handles {
|
||||
if err := vfh.handle.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return vf.handle.Sync()
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// verFileHandle
|
||||
//
|
||||
|
||||
type verFileHandle struct {
|
||||
node *verFile
|
||||
path string
|
||||
handle *os.File
|
||||
id fuse.HandleID
|
||||
}
|
||||
|
||||
// HandleReader
|
||||
func (vf *verFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
||||
if vf.handle == nil {
|
||||
return errors.New("attempted to read from unopened file")
|
||||
}
|
||||
|
||||
func (vfh *verFileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
||||
resp.Data = make([]byte, req.Size)
|
||||
if _, err := vf.handle.ReadAt(resp.Data, req.Offset); err != nil {
|
||||
if _, err := vfh.handle.ReadAt(resp.Data, req.Offset); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -137,18 +147,14 @@ func (vf *verFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.R
|
||||
}
|
||||
|
||||
// HandleReadAller
|
||||
func (vf *verFile) ReadAll(ctx context.Context) ([]byte, error) {
|
||||
if vf.handle == nil {
|
||||
return nil, errors.New("attempted to read from unopened file")
|
||||
}
|
||||
|
||||
info, err := os.Stat(vf.node.rebasedPath())
|
||||
func (vfh *verFileHandle) ReadAll(ctx context.Context) ([]byte, error) {
|
||||
info, err := os.Stat(vfh.path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make([]byte, info.Size())
|
||||
if _, err := vf.handle.Read(data); err != nil {
|
||||
if _, err := vfh.handle.Read(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -156,12 +162,8 @@ func (vf *verFile) ReadAll(ctx context.Context) ([]byte, error) {
|
||||
}
|
||||
|
||||
// HandleWriter
|
||||
func (vf *verFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
|
||||
if vf.handle == nil {
|
||||
return errors.New("attempted to write to unopened file")
|
||||
}
|
||||
|
||||
size, err := vf.handle.WriteAt(req.Data, req.Offset)
|
||||
func (vfh *verFileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
|
||||
size, err := vfh.handle.WriteAt(req.Data, req.Offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -169,3 +171,12 @@ func (vf *verFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse
|
||||
resp.Size = size
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleReleaser
|
||||
func (vfh *verFileHandle) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
|
||||
vfh.handle.Close()
|
||||
vfh.handle = nil
|
||||
|
||||
vfh.node.release(req.Handle)
|
||||
return nil
|
||||
}
|
||||
|
8
util.go
8
util.go
@ -32,14 +32,20 @@ import (
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
)
|
||||
|
||||
var inodeCnt uint64
|
||||
var inodeCnt, handleCnt uint64
|
||||
|
||||
func allocInode() uint64 {
|
||||
return atomic.AddUint64(&inodeCnt, 1)
|
||||
}
|
||||
|
||||
func allocHandleId() fuse.HandleID {
|
||||
return fuse.HandleID(atomic.AddUint64(&handleCnt, 1))
|
||||
}
|
||||
|
||||
func copyFile(src, dst string) (int64, error) {
|
||||
srcFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user