v2api: implement Mknod
This commit is contained in:
parent
855b4a95b7
commit
b971c75e67
@ -102,6 +102,23 @@ func (n *Node) Getattr(ctx context.Context, f fs.FileHandle, out *fuse.AttrOut)
|
||||
return 0
|
||||
}
|
||||
|
||||
// newChild attaches a new child inode to n.
|
||||
// The passed-in `st` will be modified to get a unique inode number.
|
||||
func (n *Node) newChild(ctx context.Context, st *syscall.Stat_t, out *fuse.EntryOut) *fs.Inode {
|
||||
// Get unique inode number
|
||||
rn := n.rootNode()
|
||||
rn.inoMap.TranslateStat(st)
|
||||
out.Attr.FromStat(st)
|
||||
// Create child node
|
||||
id := fs.StableAttr{
|
||||
Mode: uint32(st.Mode),
|
||||
Gen: 1,
|
||||
Ino: st.Ino,
|
||||
}
|
||||
node := &Node{}
|
||||
return n.NewInode(ctx, node, id)
|
||||
}
|
||||
|
||||
// Create - FUSE call. Creates a new file.
|
||||
//
|
||||
// Symlink-safe through the use of Openat().
|
||||
@ -153,17 +170,7 @@ func (n *Node) Create(ctx context.Context, name string, flags uint32, mode uint3
|
||||
errno = fs.ToErrno(err)
|
||||
return
|
||||
}
|
||||
// Get unique inode number
|
||||
rn.inoMap.TranslateStat(&st)
|
||||
out.Attr.FromStat(&st)
|
||||
// Create child node
|
||||
id := fs.StableAttr{
|
||||
Mode: uint32(st.Mode),
|
||||
Gen: 1,
|
||||
Ino: st.Ino,
|
||||
}
|
||||
node := &Node{}
|
||||
ch := n.NewInode(ctx, node, id)
|
||||
ch := n.newChild(ctx, &st, out)
|
||||
|
||||
f := os.NewFile(uintptr(fd), cName)
|
||||
return ch, NewFile2(f, rn, &st), 0, 0
|
||||
@ -296,3 +303,50 @@ func (n *Node) Statfs(ctx context.Context, out *fuse.StatfsOut) syscall.Errno {
|
||||
out.FromStatfsT(&st)
|
||||
return 0
|
||||
}
|
||||
|
||||
// Mknod - FUSE call. Create a device file.
|
||||
//
|
||||
// Symlink-safe through use of Mknodat().
|
||||
func (n *Node) Mknod(ctx context.Context, name string, mode, rdev uint32, out *fuse.EntryOut) (inode *fs.Inode, errno syscall.Errno) {
|
||||
dirfd, cName, errno := n.prepareAtSyscall("")
|
||||
if errno != 0 {
|
||||
return
|
||||
}
|
||||
defer syscall.Close(dirfd)
|
||||
|
||||
// Make sure context is nil if we don't want to preserve the owner
|
||||
rn := n.rootNode()
|
||||
if !rn.args.PreserveOwner {
|
||||
ctx = nil
|
||||
}
|
||||
|
||||
// Create ".name" file to store long file name (except in PlaintextNames mode)
|
||||
var err error
|
||||
if !rn.args.PlaintextNames && nametransform.IsLongContent(cName) {
|
||||
err := rn.nameTransform.WriteLongNameAt(dirfd, cName, name)
|
||||
if err != nil {
|
||||
errno = fs.ToErrno(err)
|
||||
return
|
||||
}
|
||||
// Create "gocryptfs.longfile." device node
|
||||
err = syscallcompat.MknodatUserCtx(dirfd, cName, mode, int(rdev), ctx)
|
||||
if err != nil {
|
||||
nametransform.DeleteLongNameAt(dirfd, cName)
|
||||
}
|
||||
} else {
|
||||
// Create regular device node
|
||||
err = syscallcompat.MknodatUserCtx(dirfd, cName, mode, int(rdev), ctx)
|
||||
}
|
||||
if err != nil {
|
||||
errno = fs.ToErrno(err)
|
||||
return
|
||||
}
|
||||
|
||||
st, err := syscallcompat.Fstatat2(dirfd, cName, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
errno = fs.ToErrno(err)
|
||||
return
|
||||
}
|
||||
inode = n.newChild(ctx, st, out)
|
||||
return inode, 0
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ var _ = (fs.NodeOpener)((*Node)(nil))
|
||||
var _ = (fs.NodeOpendirer)((*Node)(nil))
|
||||
var _ = (fs.NodeSetattrer)((*Node)(nil))
|
||||
var _ = (fs.NodeStatfser)((*Node)(nil))
|
||||
var _ = (fs.NodeMknoder)((*Node)(nil))
|
||||
|
||||
/* TODO
|
||||
var _ = (fs.NodeGetxattrer)((*Node)(nil))
|
||||
@ -24,7 +25,6 @@ var _ = (fs.NodeSetxattrer)((*Node)(nil))
|
||||
var _ = (fs.NodeRemovexattrer)((*Node)(nil))
|
||||
var _ = (fs.NodeListxattrer)((*Node)(nil))
|
||||
var _ = (fs.NodeCopyFileRanger)((*Node)(nil))
|
||||
var _ = (fs.NodeMknoder)((*Node)(nil))
|
||||
var _ = (fs.NodeLinker)((*Node)(nil))
|
||||
var _ = (fs.NodeSymlinker)((*Node)(nil))
|
||||
var _ = (fs.NodeRenamer)((*Node)(nil))
|
||||
|
@ -115,16 +115,8 @@ func (n *Node) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.En
|
||||
tlog.Warn.Printf("Mkdir %q: Fstat failed: %v", cName, err)
|
||||
return nil, fs.ToErrno(err)
|
||||
}
|
||||
rn.inoMap.TranslateStat(&st)
|
||||
out.Attr.FromStat(&st)
|
||||
// Create child node
|
||||
id := fs.StableAttr{
|
||||
Mode: uint32(st.Mode),
|
||||
Gen: 1,
|
||||
Ino: st.Ino,
|
||||
}
|
||||
node := &Node{}
|
||||
ch := n.NewInode(ctx, node, id)
|
||||
ch := n.newChild(ctx, &st, out)
|
||||
|
||||
// Set mode
|
||||
if origMode != mode {
|
||||
|
@ -136,6 +136,20 @@ func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
|
||||
return syscall.Mknodat(dirfd, path, mode, dev)
|
||||
}
|
||||
|
||||
// MknodatUserCtx is a tries to extract a fuse.Context from the generic ctx and
|
||||
// calls OpenatUser.
|
||||
func MknodatUserCtx(dirfd int, path string, mode uint32, dev int, ctx context.Context) (err error) {
|
||||
var ctx2 *fuse.Context
|
||||
if ctx != nil {
|
||||
if caller, ok := fuse.FromContext(ctx); ok {
|
||||
ctx2 = &fuse.Context{
|
||||
Caller: *caller,
|
||||
}
|
||||
}
|
||||
}
|
||||
return MknodatUser(dirfd, path, mode, dev, ctx2)
|
||||
}
|
||||
|
||||
// MknodatUser runs the Mknodat syscall in the context of a different user.
|
||||
func MknodatUser(dirfd int, path string, mode uint32, dev int, context *fuse.Context) (err error) {
|
||||
if context != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user