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)
|
node := newVerNode(childPath, vd.node.ver, nil, NodeFlagDir|NodeFlagVer)
|
||||||
dir := newVerDir(node, vd)
|
dir := newVerDir(node, vd)
|
||||||
vd.dirs[name] = dir
|
vd.dirs[name] = dir
|
||||||
|
|
||||||
node.ver.meta.createNode(node.path)
|
node.ver.meta.createNode(node.path)
|
||||||
|
|
||||||
return dir, nil
|
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 {
|
if err := vd.version(); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
childPath := path.Join(vd.node.path, name)
|
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)
|
node := newVerNode(childPath, vd.node.ver, nil, NodeFlagVer)
|
||||||
file := newVerFile(node, vd)
|
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)
|
node.ver.meta.createNode(node.path)
|
||||||
return file, nil
|
|
||||||
|
return file, handle, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node
|
// Node
|
||||||
@ -137,9 +137,11 @@ func (vd *verDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fus
|
|||||||
}
|
}
|
||||||
} else if req.Mode.IsRegular() {
|
} else if req.Mode.IsRegular() {
|
||||||
var file *verFile
|
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
|
node = file
|
||||||
handle = file
|
handle = handle
|
||||||
|
resp.Handle = vfh.id
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = errors.New("unsupported filetype")
|
err = errors.New("unsupported filetype")
|
||||||
|
117
file.go
117
file.go
@ -23,7 +23,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"bazil.org/fuse"
|
"bazil.org/fuse"
|
||||||
@ -36,14 +35,14 @@ import (
|
|||||||
//
|
//
|
||||||
|
|
||||||
type verFile struct {
|
type verFile struct {
|
||||||
node *verNode
|
node *verNode
|
||||||
inode uint64
|
inode uint64
|
||||||
parent *verDir
|
parent *verDir
|
||||||
handle *os.File
|
handles map[fuse.HandleID]*verFileHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVerFile(node *verNode, parent *verDir) *verFile {
|
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 {
|
func (vf *verFile) version() error {
|
||||||
@ -63,6 +62,30 @@ func (vf *verFile) version() error {
|
|||||||
return nil
|
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
|
// Node
|
||||||
func (vf *verFile) Attr(ctx context.Context, attr *fuse.Attr) error {
|
func (vf *verFile) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||||
vf.node.attr(attr)
|
vf.node.attr(attr)
|
||||||
@ -82,54 +105,41 @@ func (vf *verFile) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *
|
|||||||
|
|
||||||
// NodeOpener
|
// NodeOpener
|
||||||
func (vf *verFile) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
func (vf *verFile) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
||||||
if vf.handle != nil {
|
handle, err := vf.open(req.Flags)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vf.handle = handle
|
resp.Handle = handle.id
|
||||||
return vf, nil
|
return handle, 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeFsyncer
|
// NodeFsyncer
|
||||||
func (vf *verFile) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
func (vf *verFile) Fsync(ctx context.Context, req *fuse.FsyncRequest) error {
|
||||||
if vf.handle == nil {
|
for _, vfh := range vf.handles {
|
||||||
return errors.New("attempted to sync unopened file")
|
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
|
// HandleReader
|
||||||
func (vf *verFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
func (vfh *verFileHandle) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
||||||
if vf.handle == nil {
|
|
||||||
return errors.New("attempted to read from unopened file")
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Data = make([]byte, req.Size)
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,18 +147,14 @@ func (vf *verFile) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleReadAller
|
// HandleReadAller
|
||||||
func (vf *verFile) ReadAll(ctx context.Context) ([]byte, error) {
|
func (vfh *verFileHandle) ReadAll(ctx context.Context) ([]byte, error) {
|
||||||
if vf.handle == nil {
|
info, err := os.Stat(vfh.path)
|
||||||
return nil, errors.New("attempted to read from unopened file")
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := os.Stat(vf.node.rebasedPath())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make([]byte, info.Size())
|
data := make([]byte, info.Size())
|
||||||
if _, err := vf.handle.Read(data); err != nil {
|
if _, err := vfh.handle.Read(data); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,12 +162,8 @@ func (vf *verFile) ReadAll(ctx context.Context) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleWriter
|
// HandleWriter
|
||||||
func (vf *verFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
|
func (vfh *verFileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {
|
||||||
if vf.handle == nil {
|
size, err := vfh.handle.WriteAt(req.Data, req.Offset)
|
||||||
return errors.New("attempted to write to unopened file")
|
|
||||||
}
|
|
||||||
|
|
||||||
size, err := vf.handle.WriteAt(req.Data, req.Offset)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -169,3 +171,12 @@ func (vf *verFile) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse
|
|||||||
resp.Size = size
|
resp.Size = size
|
||||||
return nil
|
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"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"bazil.org/fuse"
|
||||||
)
|
)
|
||||||
|
|
||||||
var inodeCnt uint64
|
var inodeCnt, handleCnt uint64
|
||||||
|
|
||||||
func allocInode() uint64 {
|
func allocInode() uint64 {
|
||||||
return atomic.AddUint64(&inodeCnt, 1)
|
return atomic.AddUint64(&inodeCnt, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func allocHandleId() fuse.HandleID {
|
||||||
|
return fuse.HandleID(atomic.AddUint64(&handleCnt, 1))
|
||||||
|
}
|
||||||
|
|
||||||
func copyFile(src, dst string) (int64, error) {
|
func copyFile(src, dst string) (int64, error) {
|
||||||
srcFile, err := os.Open(src)
|
srcFile, err := os.Open(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user