Commit 6d01ffa4 authored by Aaron Jacobs's avatar Aaron Jacobs

Replaced AppendDirent with WriteDirent.

parent c0804378
...@@ -388,20 +388,24 @@ type ReadDirOp struct { ...@@ -388,20 +388,24 @@ type ReadDirOp struct {
// //
// The output data should consist of a sequence of FUSE directory entries in // The output data should consist of a sequence of FUSE directory entries in
// the format generated by fuse_add_direntry (http://goo.gl/qCcHCV), which is // the format generated by fuse_add_direntry (http://goo.gl/qCcHCV), which is
// consumed by parse_dirfile (http://goo.gl/2WUmD2). Use // consumed by parse_dirfile (http://goo.gl/2WUmD2). Use fuseutil.WriteDirent
// fuseutil.AppendDirent to generate this data. // to generate this data.
//
// It is okay for the final entry to be truncated if it doesn't fit;
// parse_dirfile copes with this by ignoring the partial record.
// //
// Each entry returned exposes a directory offset to the user that may later // 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 // show up in ReadDirRequest.Offset. See notes on that field for more
// information. // information.
Dst []byte Dst []byte
// Set by the file system: the number of bytes read into Dst. It is okay for // Set by the file system: the number of bytes read into Dst.
// this to be less than len(Dst) if there is less data available. A value of //
// zero means that the end of the directory has been reached. // It is okay for this to be less than len(Dst) if there are not enough
// entries available or the final entry would not fit.
//
// Zero means that the end of the directory has been reached. This is
// unambiguous because NAME_MAX (https://goo.gl/ZxzKaE) plus the size of
// fuse_dirent (https://goo.gl/WO8s3F) plus the 8-byte alignment of
// FUSE_DIRENT_ALIGN (http://goo.gl/UziWvH) is less than the read size of
// PAGE_SIZE used by fuse_readdir (cf. https://goo.gl/VajtS2).
BytesRead int BytesRead int
} }
......
...@@ -35,7 +35,7 @@ const ( ...@@ -35,7 +35,7 @@ const (
) )
// A struct representing an entry within a directory file, describing a child. // A struct representing an entry within a directory file, describing a child.
// See notes on fuseops.ReadDirOp and on AppendDirent for details. // See notes on fuseops.ReadDirOp and on WriteDirent for details.
type Dirent struct { type Dirent struct {
// The (opaque) offset within the directory file of the entry following this // The (opaque) offset within the directory file of the entry following this
// one. See notes on fuseops.ReadDirOp.Offset for details. // one. See notes on fuseops.ReadDirOp.Offset for details.
...@@ -50,10 +50,11 @@ type Dirent struct { ...@@ -50,10 +50,11 @@ type Dirent struct {
Type DirentType Type DirentType
} }
// Append the supplied directory entry to the given buffer in the format // Write the supplied directory entry intto the given buffer in the format
// expected in fuseops.ReadFileOp.Data, returning the resulting buffer. // expected in fuseops.ReadFileOp.Data, returning the number of bytes written.
func AppendDirent(input []byte, d Dirent) (output []byte) { // Return zero if the entry would not fit.
// We want to append bytes with the layout of fuse_dirent func WriteDirent(buf []byte, d Dirent) (n int) {
// We want to write bytes with the layout of fuse_dirent
// (http://goo.gl/BmFxob) in host order. The struct must be aligned according // (http://goo.gl/BmFxob) in host order. The struct must be aligned according
// to FUSE_DIRENT_ALIGN (http://goo.gl/UziWvH), which dictates 8-byte // to FUSE_DIRENT_ALIGN (http://goo.gl/UziWvH), which dictates 8-byte
// alignment. // alignment.
...@@ -65,10 +66,23 @@ func AppendDirent(input []byte, d Dirent) (output []byte) { ...@@ -65,10 +66,23 @@ func AppendDirent(input []byte, d Dirent) (output []byte) {
name [0]byte name [0]byte
} }
const alignment = 8 const direntAlignment = 8
const nameOffset = 8 + 8 + 4 + 4 const direntSize = 8 + 8 + 4 + 4
// Write the header into the buffer. // Compute the number of bytes of padding we'll need to maintain alignment
// for the next entry.
var padLen int
if len(d.Name)%direntAlignment != 0 {
padLen = direntAlignment - (len(d.Name) % direntAlignment)
}
// Do we have enough room?
totalLen := direntSize + len(d.Name) + padLen
if totalLen > len(buf) {
return
}
// Write the header.
de := fuse_dirent{ de := fuse_dirent{
ino: uint64(d.Inode), ino: uint64(d.Inode),
off: uint64(d.Offset), off: uint64(d.Offset),
...@@ -76,17 +90,15 @@ func AppendDirent(input []byte, d Dirent) (output []byte) { ...@@ -76,17 +90,15 @@ func AppendDirent(input []byte, d Dirent) (output []byte) {
type_: uint32(d.Type), type_: uint32(d.Type),
} }
output = append(input, (*[nameOffset]byte)(unsafe.Pointer(&de))[:]...) n += copy(buf[n:], (*[direntSize]byte)(unsafe.Pointer(&de))[:])
// Write the name afterward. // Write the name afterward.
output = append(output, d.Name...) n += copy(buf[n:], d.Name)
// Add any necessary padding. // Add any necessary padding.
if len(d.Name)%alignment != 0 { if padLen != 0 {
padLen := alignment - (len(d.Name) % alignment) var padding [direntAlignment]byte
n += copy(buf, padding[:padLen])
var padding [alignment]byte
output = append(output, padding[:padLen]...)
} }
return return
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment