file.go (1708B)
1 package iofs 2 3 import ( 4 "fmt" 5 // "io" 6 "io/fs" 7 "path" 8 9 "git.mtkn.jp/lib9p" 10 ) 11 12 type File struct { 13 fs *FS // file system to which this file belongs 14 file fs.File // underlying file 15 path string // absolute path from the root of the fs. 16 } 17 18 func (f *File) Stat() (*lib9p.FileInfo, error) { 19 fsfile, err := f.fs.fs.Open(f.path) 20 if err != nil { 21 return nil, fmt.Errorf("open: %v", err) 22 } 23 defer fsfile.Close() 24 25 fsfi, err := fsfile.Stat() 26 if err != nil { 27 return nil, fmt.Errorf("stat: %v", err) 28 } 29 30 var stat lib9p.Stat 31 stat.Type = 0 32 stat.Dev = 0 33 qid, ok := f.fs.qidPool.lookup(f) 34 if !ok { 35 qid, err = f.fs.qidPool.alloc(f) 36 if err != nil { 37 panic(fmt.Errorf("alloc qid: %v", err)) 38 } 39 } 40 stat.Qid = qid 41 stat.Length = fsfi.Size() 42 // TODO: fix this work around. 43 // should preserve permission bits 44 stat.Mode = (fsfi.Mode() &^ fs.ModePerm) | 0555 45 stat.Name = fsfi.Name() 46 stat.Atime = uint32(fsfi.ModTime().Unix()) 47 stat.Mtime = uint32(fsfi.ModTime().Unix()) 48 stat.Uid = "" 49 stat.Gid = "" 50 stat.Muid = "" 51 return &lib9p.FileInfo{Stat: stat}, nil 52 } 53 54 func (f *File) Close() error { 55 return f.file.Close() 56 } 57 58 func (f *File) Read(b []byte) (int, error) { 59 return f.file.Read(b) 60 } 61 62 func (f *File) ReadDir(n int) ([]fs.DirEntry, error) { 63 dir, ok := f.file.(fs.ReadDirFile) 64 if !ok { 65 return nil, fmt.Errorf("not a directory") 66 } 67 fsde, err := dir.ReadDir(n) 68 if err != nil { 69 return nil, err 70 } 71 de := make([]fs.DirEntry, len(fsde)) 72 for i, e := range fsde { 73 id := fileID(path.Join(f.path, e.Name())) 74 info, err := e.Info() 75 if err != nil { 76 return nil, fmt.Errorf("info: %v", err) 77 } 78 st := fiStat(f.fs.qidPool, id, info) 79 de[i] = &lib9p.FileInfo{Stat: *st} 80 } 81 return de, nil 82 }