file.go (2721B)
1 package diskfs 2 3 import ( 4 "fmt" 5 "io/fs" 6 "os" 7 8 "git.mtkn.jp/lib9p" 9 ) 10 11 // File represents a file. 12 type File struct { 13 fs *FS // file system to which this file belongs 14 path string // relative path from the root of the fs. slash-separated. 15 file *os.File // underlying file. nil if not open. 16 dirIndex int // index for ReadDir 17 } 18 19 // Stat returns the *lib9p.FileInfo structure describing file. 20 func (f *File) Stat() (*lib9p.FileInfo, error) { 21 return f.stat() 22 } 23 24 // WStat updates the stat of the file. 25 func (f *File) WStat(s *lib9p.Stat) error { 26 return f.wstat(s) 27 } 28 29 // Close closes the file. 30 func (f *File) Close() error { 31 if f.file == nil { 32 return fmt.Errorf("not open") 33 } 34 if err := f.file.Close(); err != nil { 35 return err 36 } 37 f.file = nil 38 return nil 39 } 40 41 // Read reads up to len(b) bytes from the File and stores them in b. 42 // It returns the number of bytes read and any error encountered. 43 // At end of file. Read returns 0, io.EOF. 44 func (f *File) Read(b []byte) (int, error) { 45 if f.file == nil { 46 return 0, fmt.Errorf("not open") 47 } 48 return f.file.Read(b) 49 } 50 51 func (f *File) ReadAt(p []byte, off int64) (int, error) { 52 if f.file == nil { 53 return 0, fmt.Errorf("not open") 54 } 55 return f.file.ReadAt(p, off) 56 } 57 58 // ReadDir reads the contents of the directory and returns 59 // a slice of up to n *lib9p.DirEntry values in directory order. 60 // Subsequent calls on the same file will yield further DirEntry values. 61 // 62 // If n > 0, ReadDir returns at most n DirEntry structures. 63 // In this case, if ReadDir returns an empty slice, it will return 64 // a non-nil error explaining why. 65 // At the end of a directory, the error is io.EOF. 66 // (ReadDir must return io.EOF itself, not an error wrapping io.EOF.) 67 // 68 // If n <= 0, ReadDir returns all the DirEntry values from the directory 69 // in a single slice. In this case, if ReadDir succeeds (reads all the way 70 // to the end of the directory), it returns the slice and a nil error. 71 // If it encounters an error before the end of the directory, 72 // ReadDir returns the DirEntry list read until that point and a non-nil error. 73 // 74 // TODO: handle errors correctly. 75 func (f *File) ReadDir(n int) ([]fs.DirEntry, error) { 76 osde, err := f.file.ReadDir(n) 77 de := make([]fs.DirEntry, len(osde)) 78 for i, e := range osde { 79 fi, err := e.Info() 80 if err != nil { 81 return nil, fmt.Errorf("info: %v", err) 82 } 83 id := idFromInfo(f.path, fi) 84 stat, err := fiStat(f.fs.qidPool, id, fi) 85 if err != nil { 86 return nil, fmt.Errorf("fiStat: %v", err) 87 } 88 de[i] = &lib9p.DirEntry{Stat: *stat} 89 } 90 return de, err 91 } 92 93 func (f *File) WriteAt(p []byte, off int64) (int, error) { 94 if f.file == nil { 95 return 0, fmt.Errorf("not open") 96 } 97 return f.file.WriteAt(p, off) 98 }