Ported more methods.
parent
f4c58fac66
commit
680eaa899d
357
fuseops/ops.go
357
fuseops/ops.go
|
@ -239,6 +239,92 @@ type OpenDirOp struct {
|
|||
|
||||
// Read entries from a directory previously opened with OpenDir.
|
||||
type ReadDirOp struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The directory inode that we are reading, and the handle previously
|
||||
// returned by OpenDir when opening that inode.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
|
||||
// The offset within the directory at which to read.
|
||||
//
|
||||
// Warning: this field is not necessarily a count of bytes. Its legal values
|
||||
// are defined by the results returned in ReadDirResponse. See the notes
|
||||
// below and the notes on that struct.
|
||||
//
|
||||
// In the Linux kernel this ultimately comes from file::f_pos, which starts
|
||||
// at zero and is set by llseek and by the final consumed result returned by
|
||||
// each call to ReadDir:
|
||||
//
|
||||
// * (http://goo.gl/2nWJPL) iterate_dir, which is called by getdents(2) and
|
||||
// readdir(2), sets dir_context::pos to file::f_pos before calling
|
||||
// f_op->iterate, and then does the opposite assignment afterward.
|
||||
//
|
||||
// * (http://goo.gl/rTQVSL) fuse_readdir, which implements iterate for fuse
|
||||
// directories, passes dir_context::pos as the offset to fuse_read_fill,
|
||||
// which passes it on to user-space. fuse_readdir later calls
|
||||
// parse_dirfile with the same context.
|
||||
//
|
||||
// * (http://goo.gl/vU5ukv) For each returned result (except perhaps the
|
||||
// last, which may be truncated by the page boundary), parse_dirfile
|
||||
// updates dir_context::pos with fuse_dirent::off.
|
||||
//
|
||||
// It is affected by the Posix directory stream interfaces in the following
|
||||
// manner:
|
||||
//
|
||||
// * (http://goo.gl/fQhbyn, http://goo.gl/ns1kDF) opendir initially causes
|
||||
// filepos to be set to zero.
|
||||
//
|
||||
// * (http://goo.gl/ezNKyR, http://goo.gl/xOmDv0) readdir allows the user
|
||||
// to iterate through the directory one entry at a time. As each entry is
|
||||
// consumed, its d_off field is stored in __dirstream::filepos.
|
||||
//
|
||||
// * (http://goo.gl/WEOXG8, http://goo.gl/rjSXl3) telldir allows the user
|
||||
// to obtain the d_off field from the most recently returned entry.
|
||||
//
|
||||
// * (http://goo.gl/WG3nDZ, http://goo.gl/Lp0U6W) seekdir allows the user
|
||||
// to seek backward to an offset previously returned by telldir. It
|
||||
// stores the new offset in filepos, and calls llseek to update the
|
||||
// kernel's struct file.
|
||||
//
|
||||
// * (http://goo.gl/gONQhz, http://goo.gl/VlrQkc) rewinddir allows the user
|
||||
// to go back to the beginning of the directory, obtaining a fresh view.
|
||||
// It updates filepos and calls llseek to update the kernel's struct
|
||||
// file.
|
||||
//
|
||||
// Unfortunately, FUSE offers no way to intercept seeks
|
||||
// (http://goo.gl/H6gEXa), so there is no way to cause seekdir or rewinddir
|
||||
// to fail. Additionally, there is no way to distinguish an explicit
|
||||
// rewinddir followed by readdir from the initial readdir, or a rewinddir
|
||||
// from a seekdir to the value returned by telldir just after opendir.
|
||||
//
|
||||
// Luckily, Posix is vague about what the user will see if they seek
|
||||
// backwards, and requires the user not to seek to an old offset after a
|
||||
// rewind. The only requirement on freshness is that rewinddir results in
|
||||
// something that looks like a newly-opened directory. So FUSE file systems
|
||||
// may e.g. cache an entire fresh listing for each ReadDir with a zero
|
||||
// offset, and return array offsets into that cached listing.
|
||||
Offset DirOffset
|
||||
|
||||
// The maximum number of bytes to return in ReadDirResponse.Data. A smaller
|
||||
// number is acceptable.
|
||||
Size int
|
||||
|
||||
// Set by the file system: a buffer consisting of a sequence of FUSE
|
||||
// directory entries in the format generated by fuse_add_direntry
|
||||
// (http://goo.gl/qCcHCV), which is consumed by parse_dirfile
|
||||
// (http://goo.gl/2WUmD2). Use fuseutil.AppendDirent to generate this data.
|
||||
//
|
||||
// The buffer must not exceed the length specified in ReadDirRequest.Size. It
|
||||
// is okay for the final entry to be truncated; parse_dirfile copes with this
|
||||
// by ignoring the partial record.
|
||||
//
|
||||
// Each entry returned exposes a directory offset to the user that may later
|
||||
// show up in ReadDirRequest.Offset. See notes on that field for more
|
||||
// information.
|
||||
//
|
||||
// An empty buffer indicates the end of the directory has been reached.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Release a previously-minted directory handle. The kernel sends this when
|
||||
|
@ -248,6 +334,12 @@ type ReadDirOp struct {
|
|||
// The kernel guarantees that the handle ID will not be used in further ops
|
||||
// sent to the file system (unless it is reissued by the file system).
|
||||
type ReleaseDirHandleOp struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The handle ID to be released. The kernel guarantees that this ID will not
|
||||
// be used in further calls to the file system (unless it is reissued by the
|
||||
// file system).
|
||||
Handle HandleID
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -261,6 +353,22 @@ type ReleaseDirHandleOp struct {
|
|||
// process. On OS X it may not be sent for every open(2)
|
||||
// (cf.https://github.com/osxfuse/osxfuse/issues/199).
|
||||
type OpenFileOp struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The ID of the inode to be opened.
|
||||
Inode InodeID
|
||||
|
||||
// Mode and options flags.
|
||||
Flags bazilfuse.OpenFlags
|
||||
|
||||
// An opaque ID that will be echoed in follow-up calls for this file using
|
||||
// the same struct file in the kernel. In practice this usually means
|
||||
// follow-up calls using the file descriptor returned by open(2).
|
||||
//
|
||||
// The handle may be supplied in future ops like ReadFileOp that contain a
|
||||
// file handle. The file system must ensure this ID remains valid until a
|
||||
// later call to ReleaseFileHandle.
|
||||
Handle HandleID
|
||||
}
|
||||
|
||||
// Read data from a file previously opened with CreateFile or OpenFile.
|
||||
|
@ -269,6 +377,27 @@ type OpenFileOp struct {
|
|||
// some reads may be served by the page cache. See notes on WriteFileOp for
|
||||
// more.
|
||||
type ReadFileOp struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The file inode that we are reading, and the handle previously returned by
|
||||
// CreateFile or OpenFile when opening that inode.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
|
||||
// The range of the file to read.
|
||||
//
|
||||
// The FUSE documentation requires that exactly the number of bytes be
|
||||
// returned, except in the case of EOF or error (http://goo.gl/ZgfBkF). This
|
||||
// appears to be because it uses file mmapping machinery
|
||||
// (http://goo.gl/SGxnaN) to read a page at a time. It appears to understand
|
||||
// where EOF is by checking the inode size (http://goo.gl/0BkqKD), returned
|
||||
// by a previous call to LookUpInode, GetInodeAttributes, etc.
|
||||
Offset int64
|
||||
Size int
|
||||
|
||||
// Set by the file system: the data read. If this is less than the requested
|
||||
// size, it indicates EOF. An error should not be returned in this case.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Write data to a file previously opened with CreateFile or OpenFile.
|
||||
|
@ -300,6 +429,42 @@ type ReadFileOp struct {
|
|||
// flush request.
|
||||
//
|
||||
type WriteFileOp struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The file inode that we are modifying, and the handle previously returned
|
||||
// by CreateFile or OpenFile when opening that inode.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
|
||||
// The offset at which to write the data below.
|
||||
//
|
||||
// The man page for pwrite(2) implies that aside from changing the file
|
||||
// handle's offset, using pwrite is equivalent to using lseek(2) and then
|
||||
// write(2). The man page for lseek(2) says the following:
|
||||
//
|
||||
// "The lseek() function allows the file offset to be set beyond the end of
|
||||
// the file (but this does not change the size of the file). If data is later
|
||||
// written at this point, subsequent reads of the data in the gap (a "hole")
|
||||
// return null bytes (aq\0aq) until data is actually written into the gap."
|
||||
//
|
||||
// It is therefore reasonable to assume that the kernel is looking for
|
||||
// the following semantics:
|
||||
//
|
||||
// * If the offset is less than or equal to the current size, extend the
|
||||
// file as necessary to fit any data that goes past the end of the file.
|
||||
//
|
||||
// * If the offset is greater than the current size, extend the file
|
||||
// with null bytes until it is not, then do the above.
|
||||
//
|
||||
Offset int64
|
||||
|
||||
// The data to write.
|
||||
//
|
||||
// The FUSE documentation requires that exactly the number of bytes supplied
|
||||
// be written, except on error (http://goo.gl/KUpwwn). This appears to be
|
||||
// because it uses file mmapping machinery (http://goo.gl/SGxnaN) to write a
|
||||
// page at a time.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Synchronize the current contents of an open file to storage.
|
||||
|
@ -384,198 +549,6 @@ type ReleaseFileHandleOp struct {
|
|||
// Requests and responses
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
type ReadDirRequest struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The directory inode that we are reading, and the handle previously
|
||||
// returned by OpenDir when opening that inode.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
|
||||
// The offset within the directory at which to read.
|
||||
//
|
||||
// Warning: this field is not necessarily a count of bytes. Its legal values
|
||||
// are defined by the results returned in ReadDirResponse. See the notes
|
||||
// below and the notes on that struct.
|
||||
//
|
||||
// In the Linux kernel this ultimately comes from file::f_pos, which starts
|
||||
// at zero and is set by llseek and by the final consumed result returned by
|
||||
// each call to ReadDir:
|
||||
//
|
||||
// * (http://goo.gl/2nWJPL) iterate_dir, which is called by getdents(2) and
|
||||
// readdir(2), sets dir_context::pos to file::f_pos before calling
|
||||
// f_op->iterate, and then does the opposite assignment afterward.
|
||||
//
|
||||
// * (http://goo.gl/rTQVSL) fuse_readdir, which implements iterate for fuse
|
||||
// directories, passes dir_context::pos as the offset to fuse_read_fill,
|
||||
// which passes it on to user-space. fuse_readdir later calls
|
||||
// parse_dirfile with the same context.
|
||||
//
|
||||
// * (http://goo.gl/vU5ukv) For each returned result (except perhaps the
|
||||
// last, which may be truncated by the page boundary), parse_dirfile
|
||||
// updates dir_context::pos with fuse_dirent::off.
|
||||
//
|
||||
// It is affected by the Posix directory stream interfaces in the following
|
||||
// manner:
|
||||
//
|
||||
// * (http://goo.gl/fQhbyn, http://goo.gl/ns1kDF) opendir initially causes
|
||||
// filepos to be set to zero.
|
||||
//
|
||||
// * (http://goo.gl/ezNKyR, http://goo.gl/xOmDv0) readdir allows the user
|
||||
// to iterate through the directory one entry at a time. As each entry is
|
||||
// consumed, its d_off field is stored in __dirstream::filepos.
|
||||
//
|
||||
// * (http://goo.gl/WEOXG8, http://goo.gl/rjSXl3) telldir allows the user
|
||||
// to obtain the d_off field from the most recently returned entry.
|
||||
//
|
||||
// * (http://goo.gl/WG3nDZ, http://goo.gl/Lp0U6W) seekdir allows the user
|
||||
// to seek backward to an offset previously returned by telldir. It
|
||||
// stores the new offset in filepos, and calls llseek to update the
|
||||
// kernel's struct file.
|
||||
//
|
||||
// * (http://goo.gl/gONQhz, http://goo.gl/VlrQkc) rewinddir allows the user
|
||||
// to go back to the beginning of the directory, obtaining a fresh view.
|
||||
// It updates filepos and calls llseek to update the kernel's struct
|
||||
// file.
|
||||
//
|
||||
// Unfortunately, FUSE offers no way to intercept seeks
|
||||
// (http://goo.gl/H6gEXa), so there is no way to cause seekdir or rewinddir
|
||||
// to fail. Additionally, there is no way to distinguish an explicit
|
||||
// rewinddir followed by readdir from the initial readdir, or a rewinddir
|
||||
// from a seekdir to the value returned by telldir just after opendir.
|
||||
//
|
||||
// Luckily, Posix is vague about what the user will see if they seek
|
||||
// backwards, and requires the user not to seek to an old offset after a
|
||||
// rewind. The only requirement on freshness is that rewinddir results in
|
||||
// something that looks like a newly-opened directory. So FUSE file systems
|
||||
// may e.g. cache an entire fresh listing for each ReadDir with a zero
|
||||
// offset, and return array offsets into that cached listing.
|
||||
Offset DirOffset
|
||||
|
||||
// The maximum number of bytes to return in ReadDirResponse.Data. A smaller
|
||||
// number is acceptable.
|
||||
Size int
|
||||
}
|
||||
|
||||
type ReadDirResponse struct {
|
||||
// A buffer consisting of a sequence of FUSE directory entries in the format
|
||||
// generated by fuse_add_direntry (http://goo.gl/qCcHCV), which is consumed
|
||||
// by parse_dirfile (http://goo.gl/2WUmD2). Use fuseutil.AppendDirent to
|
||||
// generate this data.
|
||||
//
|
||||
// The buffer must not exceed the length specified in ReadDirRequest.Size. It
|
||||
// is okay for the final entry to be truncated; parse_dirfile copes with this
|
||||
// by ignoring the partial record.
|
||||
//
|
||||
// Each entry returned exposes a directory offset to the user that may later
|
||||
// show up in ReadDirRequest.Offset. See notes on that field for more
|
||||
// information.
|
||||
//
|
||||
// An empty buffer indicates the end of the directory has been reached.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type ReleaseDirHandleRequest struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The handle ID to be released. The kernel guarantees that this ID will not
|
||||
// be used in further calls to the file system (unless it is reissued by the
|
||||
// file system).
|
||||
Handle HandleID
|
||||
}
|
||||
|
||||
type ReleaseDirHandleResponse struct {
|
||||
}
|
||||
|
||||
type OpenFileRequest struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The ID of the inode to be opened.
|
||||
Inode InodeID
|
||||
|
||||
// Mode and options flags.
|
||||
Flags bazilfuse.OpenFlags
|
||||
}
|
||||
|
||||
type OpenFileResponse struct {
|
||||
// An opaque ID that will be echoed in follow-up calls for this file using
|
||||
// the same struct file in the kernel. In practice this usually means
|
||||
// follow-up calls using the file descriptor returned by open(2).
|
||||
//
|
||||
// The handle may be supplied in future ops like ReadFileOp that contain a
|
||||
// file handle. The file system must ensure this ID remains valid until a
|
||||
// later call to ReleaseFileHandle.
|
||||
Handle HandleID
|
||||
}
|
||||
|
||||
type ReadFileRequest struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The file inode that we are reading, and the handle previously returned by
|
||||
// CreateFile or OpenFile when opening that inode.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
|
||||
// The range of the file to read.
|
||||
//
|
||||
// The FUSE documentation requires that exactly the number of bytes be
|
||||
// returned, except in the case of EOF or error (http://goo.gl/ZgfBkF). This
|
||||
// appears to be because it uses file mmapping machinery
|
||||
// (http://goo.gl/SGxnaN) to read a page at a time. It appears to understand
|
||||
// where EOF is by checking the inode size (http://goo.gl/0BkqKD), returned
|
||||
// by a previous call to LookUpInode, GetInodeAttributes, etc.
|
||||
Offset int64
|
||||
Size int
|
||||
}
|
||||
|
||||
type ReadFileResponse struct {
|
||||
// The data read. If this is less than the requested size, it indicates EOF.
|
||||
// An error should not be returned in this case.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type WriteFileRequest struct {
|
||||
Header RequestHeader
|
||||
|
||||
// The file inode that we are modifying, and the handle previously returned
|
||||
// by CreateFile or OpenFile when opening that inode.
|
||||
Inode InodeID
|
||||
Handle HandleID
|
||||
|
||||
// The offset at which to write the data below.
|
||||
//
|
||||
// The man page for pwrite(2) implies that aside from changing the file
|
||||
// handle's offset, using pwrite is equivalent to using lseek(2) and then
|
||||
// write(2). The man page for lseek(2) says the following:
|
||||
//
|
||||
// "The lseek() function allows the file offset to be set beyond the end of
|
||||
// the file (but this does not change the size of the file). If data is later
|
||||
// written at this point, subsequent reads of the data in the gap (a "hole")
|
||||
// return null bytes (aq\0aq) until data is actually written into the gap."
|
||||
//
|
||||
// It is therefore reasonable to assume that the kernel is looking for
|
||||
// the following semantics:
|
||||
//
|
||||
// * If the offset is less than or equal to the current size, extend the
|
||||
// file as necessary to fit any data that goes past the end of the file.
|
||||
//
|
||||
// * If the offset is greater than the current size, extend the file
|
||||
// with null bytes until it is not, then do the above.
|
||||
//
|
||||
Offset int64
|
||||
|
||||
// The data to write.
|
||||
//
|
||||
// The FUSE documentation requires that exactly the number of bytes supplied
|
||||
// be written, except on error (http://goo.gl/KUpwwn). This appears to be
|
||||
// because it uses file mmapping machinery (http://goo.gl/SGxnaN) to write a
|
||||
// page at a time.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type WriteFileResponse struct {
|
||||
}
|
||||
|
||||
type SyncFileRequest struct {
|
||||
Header RequestHeader
|
||||
|
||||
|
|
Loading…
Reference in New Issue