94 lines
2.7 KiB
Go
94 lines
2.7 KiB
Go
// Copyright 2015 Google Inc. All Rights Reserved.
|
|
//
|
|
// 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 fuseutil
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"github.com/jacobsa/fuse/fuseops"
|
|
)
|
|
|
|
type DirentType uint32
|
|
|
|
const (
|
|
DT_Unknown DirentType = 0
|
|
DT_Socket DirentType = syscall.DT_SOCK
|
|
DT_Link DirentType = syscall.DT_LNK
|
|
DT_File DirentType = syscall.DT_REG
|
|
DT_Block DirentType = syscall.DT_BLK
|
|
DT_Directory DirentType = syscall.DT_DIR
|
|
DT_Char DirentType = syscall.DT_CHR
|
|
DT_FIFO DirentType = syscall.DT_FIFO
|
|
)
|
|
|
|
// A struct representing an entry within a directory file, describing a child.
|
|
// See notes on fuseops.ReadDirOp and on AppendDirent for details.
|
|
type Dirent struct {
|
|
// The (opaque) offset within the directory file of the entry following this
|
|
// one. See notes on fuseops.ReadDirOp.Offset for details.
|
|
Offset fuseops.DirOffset
|
|
|
|
// The inode of the child file or directory, and its name within the parent.
|
|
Inode fuseops.InodeID
|
|
Name string
|
|
|
|
// The type of the child. The zero value (DT_Unknown) is legal, but means
|
|
// that the kernel will need to call GetAttr when the type is needed.
|
|
Type DirentType
|
|
}
|
|
|
|
// Append the supplied directory entry to the given buffer in the format
|
|
// expected in fuseops.ReadFileOp.Data, returning the resulting buffer.
|
|
func AppendDirent(input []byte, d Dirent) (output []byte) {
|
|
// We want to append bytes with the layout of fuse_dirent
|
|
// (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
|
|
// alignment.
|
|
type fuse_dirent struct {
|
|
ino uint64
|
|
off uint64
|
|
namelen uint32
|
|
type_ uint32
|
|
name [0]byte
|
|
}
|
|
|
|
const alignment = 8
|
|
const nameOffset = 8 + 8 + 4 + 4
|
|
|
|
// Write the header into the buffer.
|
|
de := fuse_dirent{
|
|
ino: uint64(d.Inode),
|
|
off: uint64(d.Offset),
|
|
namelen: uint32(len(d.Name)),
|
|
type_: uint32(d.Type),
|
|
}
|
|
|
|
output = append(input, (*[nameOffset]byte)(unsafe.Pointer(&de))[:]...)
|
|
|
|
// Write the name afterward.
|
|
output = append(output, d.Name...)
|
|
|
|
// Add any necessary padding.
|
|
if len(d.Name)%alignment != 0 {
|
|
padLen := alignment - (len(d.Name) % alignment)
|
|
|
|
var padding [alignment]byte
|
|
output = append(output, padding[:padLen]...)
|
|
}
|
|
|
|
return
|
|
}
|