lib9p

Go 9P library.
Log | Files | Refs | LICENSE

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 }