func (fs *helloFS) ReadDir( op *fuseops.ReadDirOp) (err error) { // Find the info for this inode. info, ok := gInodeInfo[op.Inode] if !ok { err = fuse.ENOENT return } if !info.dir { err = fuse.EIO return } entries := info.children // Grab the range of interest. if op.Offset > fuseops.DirOffset(len(entries)) { err = fuse.EIO return } entries = entries[op.Offset:] // Resume at the specified offset into the array. for _, e := range entries { op.Data = fuseutil.AppendDirent(op.Data, e) if len(op.Data) > op.Size { op.Data = op.Data[:op.Size] break } } return }
func (fs *flushFS) ReadDir( op *fuseops.ReadDirOp) (err error) { fs.mu.Lock() defer fs.mu.Unlock() // Create the appropriate listing. var dirents []fuseutil.Dirent switch op.Inode { case fuseops.RootInodeID: dirents = []fuseutil.Dirent{ fuseutil.Dirent{ Offset: 1, Inode: fooID, Name: "foo", Type: fuseutil.DT_File, }, fuseutil.Dirent{ Offset: 2, Inode: barID, Name: "bar", Type: fuseutil.DT_Directory, }, } case barID: default: err = fmt.Errorf("Unexpected inode: %v", op.Inode) return } // If the offset is for the end of the listing, we're done. Otherwise we // expect it to be for the start. switch op.Offset { case fuseops.DirOffset(len(dirents)): return case 0: default: err = fmt.Errorf("Unexpected offset: %v", op.Offset) return } // Fill in the listing. for _, de := range dirents { op.Data = fuseutil.AppendDirent(op.Data, de) } // We don't support doing this in anything more than one shot. if len(op.Data) > op.Size { err = fmt.Errorf("Couldn't fit listing in %v bytes", op.Size) return } return }
// Handle a request to read from the directory, without responding. // // Special case: we assume that a zero offset indicates that rewinddir has been // called (since fuse gives us no way to intercept and know for sure), and // start the listing process over again. // // LOCKS_REQUIRED(dh.Mu) // LOCKS_EXCLUDED(du.in) func (dh *dirHandle) ReadDir( op *fuseops.ReadDirOp) (err error) { // If the request is for offset zero, we assume that either this is the first // call or rewinddir has been called. Reset state. if op.Offset == 0 { dh.entries = nil dh.entriesValid = false } // Do we need to read entries from GCS? if !dh.entriesValid { err = dh.ensureEntries(op.Context()) if err != nil { return } } // Is the offset past the end of what we have buffered? If so, this must be // an invalid seekdir according to posix. index := int(op.Offset) if index > len(dh.entries) { err = fuse.EINVAL return } // We copy out entries until we run out of entries or space. for i := index; i < len(dh.entries); i++ { op.Data = fuseutil.AppendDirent(op.Data, dh.entries[i]) if len(op.Data) > op.Size { op.Data = op.Data[:op.Size] break } } return }
// Serve a ReadDir request. // // REQUIRES: in.isDir() func (in *inode) ReadDir(offset int, size int) (data []byte) { if !in.isDir() { panic("ReadDir called on non-directory.") } for i := offset; i < len(in.entries); i++ { e := in.entries[i] // Skip unused entries. if e.Type == fuseutil.DT_Unknown { continue } data = fuseutil.AppendDirent(data, in.entries[i]) // Trim and stop early if we've exceeded the requested size. if len(data) > size { data = data[:size] break } } return }