// ReadDir reads entries in a specific directory. // // Required for fuse.FileSystem. func (k *KodingNetworkFS) ReadDir(ctx context.Context, op *fuseops.ReadDirOp) error { dir, err := k.getDir(ctx, op.Inode) if err != nil { return err } entries, err := dir.ReadEntries(op.Offset) if err != nil { return err } var bytesRead int for _, e := range entries { c := fuseutil.WriteDirent(op.Dst[bytesRead:], *e) if c == 0 { break } bytesRead += c } op.BytesRead = bytesRead return nil }
// LOCKS_EXCLUDED(fs.mu) func (fs *Goofys) ReadDir( ctx context.Context, op *fuseops.ReadDirOp) (err error) { // Find the handle. fs.mu.Lock() dh := fs.dirHandles[op.Handle] //inode := fs.inodes[op.Inode] fs.mu.Unlock() if dh == nil { panic(fmt.Sprintf("can't find dh=%v", op.Handle)) } dh.inode.logFuse("ReadDir", op.Offset) dh.mu.Lock() defer dh.mu.Unlock() for i := op.Offset; ; i++ { e, err := dh.ReadDir(fs, i) if err != nil { return err } if e == nil { break } n := fuseutil.WriteDirent(op.Dst[op.BytesRead:], *e) if n == 0 { break } dh.inode.logFuse("<-- ReadDir", e.Name, e.Offset) op.BytesRead += n } 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( ctx context.Context, 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(ctx) 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++ { n := fuseutil.WriteDirent(op.Dst[op.BytesRead:], dh.entries[i]) if n == 0 { break } op.BytesRead += n } return }
// Serve a ReadDir request. // // REQUIRES: in.isDir() func (in *inode) ReadDir(p []byte, offset int) (n int) { 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 } tmp := fuseutil.WriteDirent(p[n:], in.entries[i]) if tmp == 0 { break } n += tmp } return }
func (fs *helloFS) ReadDir( ctx context.Context, 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 { n := fuseutil.WriteDirent(op.Dst[op.BytesRead:], e) if n == 0 { break } op.BytesRead += n } return }
func (fs *flushFS) ReadDir( ctx context.Context, 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 { n := fuseutil.WriteDirent(op.Dst[op.BytesRead:], de) // We don't support doing this in anything more than one shot. if n == 0 { err = fmt.Errorf("Couldn't fit listing in %v bytes", len(op.Dst)) return } op.BytesRead += n } return }