123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- // 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 WriteDirent 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
- }
- // Write the supplied directory entry intto the given buffer in the format
- // expected in fuseops.ReadFileOp.Data, returning the number of bytes written.
- // Return zero if the entry would not fit.
- 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
- // 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 direntAlignment = 8
- const direntSize = 8 + 8 + 4 + 4
- // 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{
- ino: uint64(d.Inode),
- off: uint64(d.Offset),
- namelen: uint32(len(d.Name)),
- type_: uint32(d.Type),
- }
- n += copy(buf[n:], (*[direntSize]byte)(unsafe.Pointer(&de))[:])
- // Write the name afterward.
- n += copy(buf[n:], d.Name)
- // Add any necessary padding.
- if padLen != 0 {
- var padding [direntAlignment]byte
- n += copy(buf[n:], padding[:padLen])
- }
- return
- }
|