github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/fuseutil/dirent.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fuseutil 16 17 import ( 18 "syscall" 19 "unsafe" 20 21 "github.com/scaleoutsean/fusego/fuseops" 22 ) 23 24 type DirentType uint32 25 26 const ( 27 DT_Unknown DirentType = 0 28 DT_Socket DirentType = syscall.DT_SOCK 29 DT_Link DirentType = syscall.DT_LNK 30 DT_File DirentType = syscall.DT_REG 31 DT_Block DirentType = syscall.DT_BLK 32 DT_Directory DirentType = syscall.DT_DIR 33 DT_Char DirentType = syscall.DT_CHR 34 DT_FIFO DirentType = syscall.DT_FIFO 35 ) 36 37 // A struct representing an entry within a directory file, describing a child. 38 // See notes on fuseops.ReadDirOp and on WriteDirent for details. 39 type Dirent struct { 40 // The (opaque) offset within the directory file of the entry following this 41 // one. See notes on fuseops.ReadDirOp.Offset for details. 42 Offset fuseops.DirOffset 43 44 // The inode of the child file or directory, and its name within the parent. 45 Inode fuseops.InodeID 46 Name string 47 48 // The type of the child. The zero value (DT_Unknown) is legal, but means 49 // that the kernel will need to call GetAttr when the type is needed. 50 Type DirentType 51 } 52 53 // Write the supplied directory entry intto the given buffer in the format 54 // expected in fuseops.ReadFileOp.Data, returning the number of bytes written. 55 // Return zero if the entry would not fit. 56 func WriteDirent(buf []byte, d Dirent) (n int) { 57 // We want to write bytes with the layout of fuse_dirent 58 // (http://goo.gl/BmFxob) in host order. The struct must be aligned according 59 // to FUSE_DIRENT_ALIGN (http://goo.gl/UziWvH), which dictates 8-byte 60 // alignment. 61 type fuse_dirent struct { 62 ino uint64 63 off uint64 64 namelen uint32 65 type_ uint32 66 name [0]byte 67 } 68 69 const direntAlignment = 8 70 const direntSize = 8 + 8 + 4 + 4 71 72 // Compute the number of bytes of padding we'll need to maintain alignment 73 // for the next entry. 74 var padLen int 75 if len(d.Name)%direntAlignment != 0 { 76 padLen = direntAlignment - (len(d.Name) % direntAlignment) 77 } 78 79 // Do we have enough room? 80 totalLen := direntSize + len(d.Name) + padLen 81 if totalLen > len(buf) { 82 return n 83 } 84 85 // Write the header. 86 de := fuse_dirent{ 87 ino: uint64(d.Inode), 88 off: uint64(d.Offset), 89 namelen: uint32(len(d.Name)), 90 type_: uint32(d.Type), 91 } 92 93 n += copy(buf[n:], (*[direntSize]byte)(unsafe.Pointer(&de))[:]) 94 95 // Write the name afterward. 96 n += copy(buf[n:], d.Name) 97 98 // Add any necessary padding. 99 if padLen != 0 { 100 var padding [direntAlignment]byte 101 n += copy(buf[n:], padding[:padLen]) 102 } 103 104 return n 105 }