874 lines
22 KiB
Go
874 lines
22 KiB
Go
// Copyright 2020 The gVisor Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package linux
|
|
|
|
import (
|
|
"gvisor.dev/gvisor/pkg/marshal"
|
|
"gvisor.dev/gvisor/pkg/marshal/primitive"
|
|
)
|
|
|
|
// +marshal
|
|
type FUSEOpcode uint32
|
|
|
|
// +marshal
|
|
type FUSEOpID uint64
|
|
|
|
// FUSE_ROOT_ID is the id of root inode.
|
|
const FUSE_ROOT_ID = 1
|
|
|
|
// Opcodes for FUSE operations. Analogous to the opcodes in include/linux/fuse.h.
|
|
const (
|
|
FUSE_LOOKUP FUSEOpcode = 1
|
|
FUSE_FORGET = 2 /* no reply */
|
|
FUSE_GETATTR = 3
|
|
FUSE_SETATTR = 4
|
|
FUSE_READLINK = 5
|
|
FUSE_SYMLINK = 6
|
|
_
|
|
FUSE_MKNOD = 8
|
|
FUSE_MKDIR = 9
|
|
FUSE_UNLINK = 10
|
|
FUSE_RMDIR = 11
|
|
FUSE_RENAME = 12
|
|
FUSE_LINK = 13
|
|
FUSE_OPEN = 14
|
|
FUSE_READ = 15
|
|
FUSE_WRITE = 16
|
|
FUSE_STATFS = 17
|
|
FUSE_RELEASE = 18
|
|
_
|
|
FUSE_FSYNC = 20
|
|
FUSE_SETXATTR = 21
|
|
FUSE_GETXATTR = 22
|
|
FUSE_LISTXATTR = 23
|
|
FUSE_REMOVEXATTR = 24
|
|
FUSE_FLUSH = 25
|
|
FUSE_INIT = 26
|
|
FUSE_OPENDIR = 27
|
|
FUSE_READDIR = 28
|
|
FUSE_RELEASEDIR = 29
|
|
FUSE_FSYNCDIR = 30
|
|
FUSE_GETLK = 31
|
|
FUSE_SETLK = 32
|
|
FUSE_SETLKW = 33
|
|
FUSE_ACCESS = 34
|
|
FUSE_CREATE = 35
|
|
FUSE_INTERRUPT = 36
|
|
FUSE_BMAP = 37
|
|
FUSE_DESTROY = 38
|
|
FUSE_IOCTL = 39
|
|
FUSE_POLL = 40
|
|
FUSE_NOTIFY_REPLY = 41
|
|
FUSE_BATCH_FORGET = 42
|
|
)
|
|
|
|
const (
|
|
// FUSE_MIN_READ_BUFFER is the minimum size the read can be for any FUSE filesystem.
|
|
// This is the minimum size Linux supports. See linux.fuse.h.
|
|
FUSE_MIN_READ_BUFFER uint32 = 8192
|
|
)
|
|
|
|
// FUSEHeaderIn is the header read by the daemon with each request.
|
|
//
|
|
// +marshal
|
|
type FUSEHeaderIn struct {
|
|
// Len specifies the total length of the data, including this header.
|
|
Len uint32
|
|
|
|
// Opcode specifies the kind of operation of the request.
|
|
Opcode FUSEOpcode
|
|
|
|
// Unique specifies the unique identifier for this request.
|
|
Unique FUSEOpID
|
|
|
|
// NodeID is the ID of the filesystem object being operated on.
|
|
NodeID uint64
|
|
|
|
// UID is the UID of the requesting process.
|
|
UID uint32
|
|
|
|
// GID is the GID of the requesting process.
|
|
GID uint32
|
|
|
|
// PID is the PID of the requesting process.
|
|
PID uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEHeaderOut is the header written by the daemon when it processes
|
|
// a request and wants to send a reply (almost all operations require a
|
|
// reply; if they do not, this will be explicitly documented).
|
|
//
|
|
// +marshal
|
|
type FUSEHeaderOut struct {
|
|
// Len specifies the total length of the data, including this header.
|
|
Len uint32
|
|
|
|
// Error specifies the error that occurred (0 if none).
|
|
Error int32
|
|
|
|
// Unique specifies the unique identifier of the corresponding request.
|
|
Unique FUSEOpID
|
|
}
|
|
|
|
// FUSE_INIT flags, consistent with the ones in include/uapi/linux/fuse.h.
|
|
// Our taget version is 7.23 but we have few implemented in advance.
|
|
const (
|
|
FUSE_ASYNC_READ = 1 << 0
|
|
FUSE_POSIX_LOCKS = 1 << 1
|
|
FUSE_FILE_OPS = 1 << 2
|
|
FUSE_ATOMIC_O_TRUNC = 1 << 3
|
|
FUSE_EXPORT_SUPPORT = 1 << 4
|
|
FUSE_BIG_WRITES = 1 << 5
|
|
FUSE_DONT_MASK = 1 << 6
|
|
FUSE_SPLICE_WRITE = 1 << 7
|
|
FUSE_SPLICE_MOVE = 1 << 8
|
|
FUSE_SPLICE_READ = 1 << 9
|
|
FUSE_FLOCK_LOCKS = 1 << 10
|
|
FUSE_HAS_IOCTL_DIR = 1 << 11
|
|
FUSE_AUTO_INVAL_DATA = 1 << 12
|
|
FUSE_DO_READDIRPLUS = 1 << 13
|
|
FUSE_READDIRPLUS_AUTO = 1 << 14
|
|
FUSE_ASYNC_DIO = 1 << 15
|
|
FUSE_WRITEBACK_CACHE = 1 << 16
|
|
FUSE_NO_OPEN_SUPPORT = 1 << 17
|
|
FUSE_MAX_PAGES = 1 << 22 // From FUSE 7.28
|
|
)
|
|
|
|
// currently supported FUSE protocol version numbers.
|
|
const (
|
|
FUSE_KERNEL_VERSION = 7
|
|
FUSE_KERNEL_MINOR_VERSION = 31
|
|
)
|
|
|
|
// Constants relevant to FUSE operations.
|
|
const (
|
|
FUSE_NAME_MAX = 1024
|
|
FUSE_PAGE_SIZE = 4096
|
|
FUSE_DIRENT_ALIGN = 8
|
|
)
|
|
|
|
// FUSEInitIn is the request sent by the kernel to the daemon,
|
|
// to negotiate the version and flags.
|
|
//
|
|
// +marshal
|
|
type FUSEInitIn struct {
|
|
// Major version supported by kernel.
|
|
Major uint32
|
|
|
|
// Minor version supported by the kernel.
|
|
Minor uint32
|
|
|
|
// MaxReadahead is the maximum number of bytes to read-ahead
|
|
// decided by the kernel.
|
|
MaxReadahead uint32
|
|
|
|
// Flags of this init request.
|
|
Flags uint32
|
|
}
|
|
|
|
// FUSEInitOut is the reply sent by the daemon to the kernel
|
|
// for FUSEInitIn. We target FUSE 7.23; this struct supports 7.28.
|
|
//
|
|
// +marshal
|
|
type FUSEInitOut struct {
|
|
// Major version supported by daemon.
|
|
Major uint32
|
|
|
|
// Minor version supported by daemon.
|
|
Minor uint32
|
|
|
|
// MaxReadahead is the maximum number of bytes to read-ahead.
|
|
// Decided by the daemon, after receiving the value from kernel.
|
|
MaxReadahead uint32
|
|
|
|
// Flags of this init reply.
|
|
Flags uint32
|
|
|
|
// MaxBackground is the maximum number of pending background requests
|
|
// that the daemon wants.
|
|
MaxBackground uint16
|
|
|
|
// CongestionThreshold is the daemon-decided threshold for
|
|
// the number of the pending background requests.
|
|
CongestionThreshold uint16
|
|
|
|
// MaxWrite is the daemon's maximum size of a write buffer.
|
|
// Kernel adjusts it to the minimum (fuse/init.go:fuseMinMaxWrite).
|
|
// if the value from daemon is too small.
|
|
MaxWrite uint32
|
|
|
|
// TimeGran is the daemon's time granularity for mtime and ctime metadata.
|
|
// The unit is nanosecond.
|
|
// Value should be power of 10.
|
|
// 1 indicates full nanosecond granularity support.
|
|
TimeGran uint32
|
|
|
|
// MaxPages is the daemon's maximum number of pages for one write operation.
|
|
// Kernel adjusts it to the maximum (fuse/init.go:FUSE_MAX_MAX_PAGES).
|
|
// if the value from daemon is too large.
|
|
MaxPages uint16
|
|
|
|
_ uint16
|
|
|
|
_ [8]uint32
|
|
}
|
|
|
|
// FUSE_GETATTR_FH is currently the only flag of FUSEGetAttrIn.GetAttrFlags.
|
|
// If it is set, the file handle (FUSEGetAttrIn.Fh) is used to indicate the
|
|
// object instead of the node id attribute in the request header.
|
|
const FUSE_GETATTR_FH = (1 << 0)
|
|
|
|
// FUSEGetAttrIn is the request sent by the kernel to the daemon,
|
|
// to get the attribute of a inode.
|
|
//
|
|
// +marshal
|
|
type FUSEGetAttrIn struct {
|
|
// GetAttrFlags specifies whether getattr request is sent with a nodeid or
|
|
// with a file handle.
|
|
GetAttrFlags uint32
|
|
|
|
_ uint32
|
|
|
|
// Fh is the file handler when GetAttrFlags has FUSE_GETATTR_FH bit. If
|
|
// used, the operation is analogous to fstat(2).
|
|
Fh uint64
|
|
}
|
|
|
|
// FUSEAttr is the struct used in the reponse FUSEGetAttrOut.
|
|
//
|
|
// +marshal
|
|
type FUSEAttr struct {
|
|
// Ino is the inode number of this file.
|
|
Ino uint64
|
|
|
|
// Size is the size of this file.
|
|
Size uint64
|
|
|
|
// Blocks is the number of the 512B blocks allocated by this file.
|
|
Blocks uint64
|
|
|
|
// Atime is the time of last access.
|
|
Atime uint64
|
|
|
|
// Mtime is the time of last modification.
|
|
Mtime uint64
|
|
|
|
// Ctime is the time of last status change.
|
|
Ctime uint64
|
|
|
|
// AtimeNsec is the nano second part of Atime.
|
|
AtimeNsec uint32
|
|
|
|
// MtimeNsec is the nano second part of Mtime.
|
|
MtimeNsec uint32
|
|
|
|
// CtimeNsec is the nano second part of Ctime.
|
|
CtimeNsec uint32
|
|
|
|
// Mode contains the file type and mode.
|
|
Mode uint32
|
|
|
|
// Nlink is the number of the hard links.
|
|
Nlink uint32
|
|
|
|
// UID is user ID of the owner.
|
|
UID uint32
|
|
|
|
// GID is group ID of the owner.
|
|
GID uint32
|
|
|
|
// Rdev is the device ID if this is a special file.
|
|
Rdev uint32
|
|
|
|
// BlkSize is the block size for filesystem I/O.
|
|
BlkSize uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEGetAttrOut is the reply sent by the daemon to the kernel
|
|
// for FUSEGetAttrIn.
|
|
//
|
|
// +marshal
|
|
type FUSEGetAttrOut struct {
|
|
// AttrValid and AttrValidNsec describe the attribute cache duration
|
|
AttrValid uint64
|
|
|
|
// AttrValidNsec is the nanosecond part of the attribute cache duration
|
|
AttrValidNsec uint32
|
|
|
|
_ uint32
|
|
|
|
// Attr contains the metadata returned from the FUSE server
|
|
Attr FUSEAttr
|
|
}
|
|
|
|
// FUSEEntryOut is the reply sent by the daemon to the kernel
|
|
// for FUSE_MKNOD, FUSE_MKDIR, FUSE_SYMLINK, FUSE_LINK and
|
|
// FUSE_LOOKUP.
|
|
//
|
|
// +marshal
|
|
type FUSEEntryOut struct {
|
|
// NodeID is the ID for current inode.
|
|
NodeID uint64
|
|
|
|
// Generation is the generation number of inode.
|
|
// Used to identify an inode that have different ID at different time.
|
|
Generation uint64
|
|
|
|
// EntryValid indicates timeout for an entry.
|
|
EntryValid uint64
|
|
|
|
// AttrValid indicates timeout for an entry's attributes.
|
|
AttrValid uint64
|
|
|
|
// EntryValidNsec indicates timeout for an entry in nanosecond.
|
|
EntryValidNSec uint32
|
|
|
|
// AttrValidNsec indicates timeout for an entry's attributes in nanosecond.
|
|
AttrValidNSec uint32
|
|
|
|
// Attr contains the attributes of an entry.
|
|
Attr FUSEAttr
|
|
}
|
|
|
|
// FUSELookupIn is the request sent by the kernel to the daemon
|
|
// to look up a file name.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSELookupIn struct {
|
|
marshal.StubMarshallable
|
|
|
|
// Name is a file name to be looked up.
|
|
Name string
|
|
}
|
|
|
|
// MarshalBytes serializes r.name to the dst buffer.
|
|
func (r *FUSELookupIn) MarshalBytes(buf []byte) {
|
|
copy(buf, r.Name)
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSELookupIn.
|
|
// 1 extra byte for null-terminated string.
|
|
func (r *FUSELookupIn) SizeBytes() int {
|
|
return len(r.Name) + 1
|
|
}
|
|
|
|
// MAX_NON_LFS indicates the maximum offset without large file support.
|
|
const MAX_NON_LFS = ((1 << 31) - 1)
|
|
|
|
// flags returned by OPEN request.
|
|
const (
|
|
// FOPEN_DIRECT_IO indicates bypassing page cache for this opened file.
|
|
FOPEN_DIRECT_IO = 1 << 0
|
|
// FOPEN_KEEP_CACHE avoids invalidate of data cache on open.
|
|
FOPEN_KEEP_CACHE = 1 << 1
|
|
// FOPEN_NONSEEKABLE indicates the file cannot be seeked.
|
|
FOPEN_NONSEEKABLE = 1 << 2
|
|
)
|
|
|
|
// FUSEOpenIn is the request sent by the kernel to the daemon,
|
|
// to negotiate flags and get file handle.
|
|
//
|
|
// +marshal
|
|
type FUSEOpenIn struct {
|
|
// Flags of this open request.
|
|
Flags uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEOpenOut is the reply sent by the daemon to the kernel
|
|
// for FUSEOpenIn.
|
|
//
|
|
// +marshal
|
|
type FUSEOpenOut struct {
|
|
// Fh is the file handler for opened file.
|
|
Fh uint64
|
|
|
|
// OpenFlag for the opened file.
|
|
OpenFlag uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSE_READ flags, consistent with the ones in include/uapi/linux/fuse.h.
|
|
const (
|
|
FUSE_READ_LOCKOWNER = 1 << 1
|
|
)
|
|
|
|
// FUSEReadIn is the request sent by the kernel to the daemon
|
|
// for FUSE_READ.
|
|
//
|
|
// +marshal
|
|
type FUSEReadIn struct {
|
|
// Fh is the file handle in userspace.
|
|
Fh uint64
|
|
|
|
// Offset is the read offset.
|
|
Offset uint64
|
|
|
|
// Size is the number of bytes to read.
|
|
Size uint32
|
|
|
|
// ReadFlags for this FUSE_READ request.
|
|
// Currently only contains FUSE_READ_LOCKOWNER.
|
|
ReadFlags uint32
|
|
|
|
// LockOwner is the id of the lock owner if there is one.
|
|
LockOwner uint64
|
|
|
|
// Flags for the underlying file.
|
|
Flags uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEWriteIn is the first part of the payload of the
|
|
// request sent by the kernel to the daemon
|
|
// for FUSE_WRITE (struct for FUSE version >= 7.9).
|
|
//
|
|
// The second part of the payload is the
|
|
// binary bytes of the data to be written.
|
|
//
|
|
// +marshal
|
|
type FUSEWriteIn struct {
|
|
// Fh is the file handle in userspace.
|
|
Fh uint64
|
|
|
|
// Offset is the write offset.
|
|
Offset uint64
|
|
|
|
// Size is the number of bytes to write.
|
|
Size uint32
|
|
|
|
// ReadFlags for this FUSE_WRITE request.
|
|
WriteFlags uint32
|
|
|
|
// LockOwner is the id of the lock owner if there is one.
|
|
LockOwner uint64
|
|
|
|
// Flags for the underlying file.
|
|
Flags uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEWriteOut is the payload of the reply sent by the daemon to the kernel
|
|
// for a FUSE_WRITE request.
|
|
//
|
|
// +marshal
|
|
type FUSEWriteOut struct {
|
|
// Size is the number of bytes written.
|
|
Size uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEReleaseIn is the request sent by the kernel to the daemon
|
|
// when there is no more reference to a file.
|
|
//
|
|
// +marshal
|
|
type FUSEReleaseIn struct {
|
|
// Fh is the file handler for the file to be released.
|
|
Fh uint64
|
|
|
|
// Flags of the file.
|
|
Flags uint32
|
|
|
|
// ReleaseFlags of this release request.
|
|
ReleaseFlags uint32
|
|
|
|
// LockOwner is the id of the lock owner if there is one.
|
|
LockOwner uint64
|
|
}
|
|
|
|
// FUSECreateMeta contains all the static fields of FUSECreateIn,
|
|
// which is used for FUSE_CREATE.
|
|
//
|
|
// +marshal
|
|
type FUSECreateMeta struct {
|
|
// Flags of the creating file.
|
|
Flags uint32
|
|
|
|
// Mode is the mode of the creating file.
|
|
Mode uint32
|
|
|
|
// Umask is the current file mode creation mask.
|
|
Umask uint32
|
|
_ uint32
|
|
}
|
|
|
|
// FUSECreateIn contains all the arguments sent by the kernel to the daemon, to
|
|
// atomically create and open a new regular file.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSECreateIn struct {
|
|
marshal.StubMarshallable
|
|
|
|
// CreateMeta contains mode, rdev and umash field for FUSE_MKNODS.
|
|
CreateMeta FUSECreateMeta
|
|
|
|
// Name is the name of the node to create.
|
|
Name string
|
|
}
|
|
|
|
// MarshalBytes serializes r.CreateMeta and r.Name to the dst buffer.
|
|
func (r *FUSECreateIn) MarshalBytes(buf []byte) {
|
|
r.CreateMeta.MarshalBytes(buf[:r.CreateMeta.SizeBytes()])
|
|
copy(buf[r.CreateMeta.SizeBytes():], r.Name)
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSECreateIn.
|
|
// 1 extra byte for null-terminated string.
|
|
func (r *FUSECreateIn) SizeBytes() int {
|
|
return r.CreateMeta.SizeBytes() + len(r.Name) + 1
|
|
}
|
|
|
|
// FUSEMknodMeta contains all the static fields of FUSEMknodIn,
|
|
// which is used for FUSE_MKNOD.
|
|
//
|
|
// +marshal
|
|
type FUSEMknodMeta struct {
|
|
// Mode of the inode to create.
|
|
Mode uint32
|
|
|
|
// Rdev encodes device major and minor information.
|
|
Rdev uint32
|
|
|
|
// Umask is the current file mode creation mask.
|
|
Umask uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEMknodIn contains all the arguments sent by the kernel
|
|
// to the daemon, to create a new file node.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSEMknodIn struct {
|
|
marshal.StubMarshallable
|
|
|
|
// MknodMeta contains mode, rdev and umash field for FUSE_MKNODS.
|
|
MknodMeta FUSEMknodMeta
|
|
|
|
// Name is the name of the node to create.
|
|
Name string
|
|
}
|
|
|
|
// MarshalBytes serializes r.MknodMeta and r.Name to the dst buffer.
|
|
func (r *FUSEMknodIn) MarshalBytes(buf []byte) {
|
|
r.MknodMeta.MarshalBytes(buf[:r.MknodMeta.SizeBytes()])
|
|
copy(buf[r.MknodMeta.SizeBytes():], r.Name)
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSEMknodIn.
|
|
// 1 extra byte for null-terminated string.
|
|
func (r *FUSEMknodIn) SizeBytes() int {
|
|
return r.MknodMeta.SizeBytes() + len(r.Name) + 1
|
|
}
|
|
|
|
// FUSESymLinkIn is the request sent by the kernel to the daemon,
|
|
// to create a symbolic link.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSESymLinkIn struct {
|
|
marshal.StubMarshallable
|
|
|
|
// Name of symlink to create.
|
|
Name string
|
|
|
|
// Target of the symlink.
|
|
Target string
|
|
}
|
|
|
|
// MarshalBytes serializes r.Name and r.Target to the dst buffer.
|
|
// Left null-termination at end of r.Name and r.Target.
|
|
func (r *FUSESymLinkIn) MarshalBytes(buf []byte) {
|
|
copy(buf, r.Name)
|
|
copy(buf[len(r.Name)+1:], r.Target)
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSESymLinkIn.
|
|
// 2 extra bytes for null-terminated string.
|
|
func (r *FUSESymLinkIn) SizeBytes() int {
|
|
return len(r.Name) + len(r.Target) + 2
|
|
}
|
|
|
|
// FUSEEmptyIn is used by operations without request body.
|
|
type FUSEEmptyIn struct{ marshal.StubMarshallable }
|
|
|
|
// MarshalBytes do nothing for marshal.
|
|
func (r *FUSEEmptyIn) MarshalBytes(buf []byte) {}
|
|
|
|
// SizeBytes is 0 for empty request.
|
|
func (r *FUSEEmptyIn) SizeBytes() int {
|
|
return 0
|
|
}
|
|
|
|
// FUSEMkdirMeta contains all the static fields of FUSEMkdirIn,
|
|
// which is used for FUSE_MKDIR.
|
|
//
|
|
// +marshal
|
|
type FUSEMkdirMeta struct {
|
|
// Mode of the directory of create.
|
|
Mode uint32
|
|
|
|
// Umask is the user file creation mask.
|
|
Umask uint32
|
|
}
|
|
|
|
// FUSEMkdirIn contains all the arguments sent by the kernel
|
|
// to the daemon, to create a new directory.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSEMkdirIn struct {
|
|
marshal.StubMarshallable
|
|
|
|
// MkdirMeta contains Mode and Umask of the directory to create.
|
|
MkdirMeta FUSEMkdirMeta
|
|
|
|
// Name of the directory to create.
|
|
Name string
|
|
}
|
|
|
|
// MarshalBytes serializes r.MkdirMeta and r.Name to the dst buffer.
|
|
func (r *FUSEMkdirIn) MarshalBytes(buf []byte) {
|
|
r.MkdirMeta.MarshalBytes(buf[:r.MkdirMeta.SizeBytes()])
|
|
copy(buf[r.MkdirMeta.SizeBytes():], r.Name)
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSEMkdirIn.
|
|
// 1 extra byte for null-terminated Name string.
|
|
func (r *FUSEMkdirIn) SizeBytes() int {
|
|
return r.MkdirMeta.SizeBytes() + len(r.Name) + 1
|
|
}
|
|
|
|
// FUSERmDirIn is the request sent by the kernel to the daemon
|
|
// when trying to remove a directory.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSERmDirIn struct {
|
|
marshal.StubMarshallable
|
|
|
|
// Name is a directory name to be removed.
|
|
Name string
|
|
}
|
|
|
|
// MarshalBytes serializes r.name to the dst buffer.
|
|
func (r *FUSERmDirIn) MarshalBytes(buf []byte) {
|
|
copy(buf, r.Name)
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSERmDirIn.
|
|
func (r *FUSERmDirIn) SizeBytes() int {
|
|
return len(r.Name) + 1
|
|
}
|
|
|
|
// FUSEDirents is a list of Dirents received from the FUSE daemon server.
|
|
// It is used for FUSE_READDIR.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSEDirents struct {
|
|
marshal.StubMarshallable
|
|
|
|
Dirents []*FUSEDirent
|
|
}
|
|
|
|
// FUSEDirent is a Dirent received from the FUSE daemon server.
|
|
// It is used for FUSE_READDIR.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSEDirent struct {
|
|
marshal.StubMarshallable
|
|
|
|
// Meta contains all the static fields of FUSEDirent.
|
|
Meta FUSEDirentMeta
|
|
|
|
// Name is the filename of the dirent.
|
|
Name string
|
|
}
|
|
|
|
// FUSEDirentMeta contains all the static fields of FUSEDirent.
|
|
// It is used for FUSE_READDIR.
|
|
//
|
|
// +marshal
|
|
type FUSEDirentMeta struct {
|
|
// Inode of the dirent.
|
|
Ino uint64
|
|
|
|
// Offset of the dirent.
|
|
Off uint64
|
|
|
|
// NameLen is the length of the dirent name.
|
|
NameLen uint32
|
|
|
|
// Type of the dirent.
|
|
Type uint32
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSEDirents.
|
|
func (r *FUSEDirents) SizeBytes() int {
|
|
var sizeBytes int
|
|
for _, dirent := range r.Dirents {
|
|
sizeBytes += dirent.SizeBytes()
|
|
}
|
|
|
|
return sizeBytes
|
|
}
|
|
|
|
// UnmarshalBytes deserializes FUSEDirents from the src buffer.
|
|
func (r *FUSEDirents) UnmarshalBytes(src []byte) {
|
|
for {
|
|
if len(src) <= (*FUSEDirentMeta)(nil).SizeBytes() {
|
|
break
|
|
}
|
|
|
|
// Its unclear how many dirents there are in src. Each dirent is dynamically
|
|
// sized and so we can't make assumptions about how many dirents we can allocate.
|
|
if r.Dirents == nil {
|
|
r.Dirents = make([]*FUSEDirent, 0)
|
|
}
|
|
|
|
// We have to allocate a struct for each dirent - there must be a better way
|
|
// to do this. Linux allocates 1 page to store all the dirents and then
|
|
// simply reads them from the page.
|
|
var dirent FUSEDirent
|
|
dirent.UnmarshalBytes(src)
|
|
r.Dirents = append(r.Dirents, &dirent)
|
|
|
|
src = src[dirent.SizeBytes():]
|
|
}
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSEDirent.
|
|
func (r *FUSEDirent) SizeBytes() int {
|
|
dataSize := r.Meta.SizeBytes() + len(r.Name)
|
|
|
|
// Each Dirent must be padded such that its size is a multiple
|
|
// of FUSE_DIRENT_ALIGN. Similar to the fuse dirent alignment
|
|
// in linux/fuse.h.
|
|
return (dataSize + (FUSE_DIRENT_ALIGN - 1)) & ^(FUSE_DIRENT_ALIGN - 1)
|
|
}
|
|
|
|
// UnmarshalBytes deserializes FUSEDirent from the src buffer.
|
|
func (r *FUSEDirent) UnmarshalBytes(src []byte) {
|
|
r.Meta.UnmarshalBytes(src)
|
|
src = src[r.Meta.SizeBytes():]
|
|
|
|
if r.Meta.NameLen > FUSE_NAME_MAX {
|
|
// The name is too long and therefore invalid. We don't
|
|
// need to unmarshal the name since it'll be thrown away.
|
|
return
|
|
}
|
|
|
|
buf := make([]byte, r.Meta.NameLen)
|
|
name := primitive.ByteSlice(buf)
|
|
name.UnmarshalBytes(src[:r.Meta.NameLen])
|
|
r.Name = string(name)
|
|
}
|
|
|
|
// FATTR_* consts are the attribute flags defined in include/uapi/linux/fuse.h.
|
|
// These should be or-ed together for setattr to know what has been changed.
|
|
const (
|
|
FATTR_MODE = (1 << 0)
|
|
FATTR_UID = (1 << 1)
|
|
FATTR_GID = (1 << 2)
|
|
FATTR_SIZE = (1 << 3)
|
|
FATTR_ATIME = (1 << 4)
|
|
FATTR_MTIME = (1 << 5)
|
|
FATTR_FH = (1 << 6)
|
|
FATTR_ATIME_NOW = (1 << 7)
|
|
FATTR_MTIME_NOW = (1 << 8)
|
|
FATTR_LOCKOWNER = (1 << 9)
|
|
FATTR_CTIME = (1 << 10)
|
|
)
|
|
|
|
// FUSESetAttrIn is the request sent by the kernel to the daemon,
|
|
// to set the attribute(s) of a file.
|
|
//
|
|
// +marshal
|
|
type FUSESetAttrIn struct {
|
|
// Valid indicates which attributes are modified by this request.
|
|
Valid uint32
|
|
|
|
_ uint32
|
|
|
|
// Fh is used to identify the file if FATTR_FH is set in Valid.
|
|
Fh uint64
|
|
|
|
// Size is the size that the request wants to change to.
|
|
Size uint64
|
|
|
|
// LockOwner is the owner of the lock that the request wants to change to.
|
|
LockOwner uint64
|
|
|
|
// Atime is the access time that the request wants to change to.
|
|
Atime uint64
|
|
|
|
// Mtime is the modification time that the request wants to change to.
|
|
Mtime uint64
|
|
|
|
// Ctime is the status change time that the request wants to change to.
|
|
Ctime uint64
|
|
|
|
// AtimeNsec is the nano second part of Atime.
|
|
AtimeNsec uint32
|
|
|
|
// MtimeNsec is the nano second part of Mtime.
|
|
MtimeNsec uint32
|
|
|
|
// CtimeNsec is the nano second part of Ctime.
|
|
CtimeNsec uint32
|
|
|
|
// Mode is the file mode that the request wants to change to.
|
|
Mode uint32
|
|
|
|
_ uint32
|
|
|
|
// UID is the user ID of the owner that the request wants to change to.
|
|
UID uint32
|
|
|
|
// GID is the group ID of the owner that the request wants to change to.
|
|
GID uint32
|
|
|
|
_ uint32
|
|
}
|
|
|
|
// FUSEUnlinkIn is the request sent by the kernel to the daemon
|
|
// when trying to unlink a node.
|
|
//
|
|
// Dynamically-sized objects cannot be marshalled.
|
|
type FUSEUnlinkIn struct {
|
|
marshal.StubMarshallable
|
|
|
|
// Name of the node to unlink.
|
|
Name string
|
|
}
|
|
|
|
// MarshalBytes serializes r.name to the dst buffer, which should
|
|
// have size len(r.Name) + 1 and last byte set to 0.
|
|
func (r *FUSEUnlinkIn) MarshalBytes(buf []byte) {
|
|
copy(buf, r.Name)
|
|
}
|
|
|
|
// SizeBytes is the size of the memory representation of FUSEUnlinkIn.
|
|
// 1 extra byte for null-terminated Name string.
|
|
func (r *FUSEUnlinkIn) SizeBytes() int {
|
|
return len(r.Name) + 1
|
|
}
|