qid_windows.go (2617B)
1 //go:build windows 2 3 package diskfs 4 5 import ( 6 "fmt" 7 "io/fs" 8 "os" 9 "path/filepath" 10 "time" 11 12 "git.mtkn.jp/lib9p" 13 ) 14 15 // fileID is the identifier of a windows file. 16 // It is used to assosiate the file with Qid. 17 type fileID string 18 19 // qidReq is used to update the Qid.Vers by checking the file's 20 // modified time. 21 type qidRec struct { 22 qid *lib9p.Qid 23 mtime time.Time 24 } 25 26 // QidPool is the list of Qids in the file system. 27 type QidPool struct { 28 m map[fileID]*qidRec 29 nextQid uint64 30 } 31 32 // id derives the fileID from the file. 33 func (f *File) id() (fileID, error) { 34 return fileID(f.path), nil 35 } 36 37 // idFromInfo derives the fileID from the fs.FileInfo. 38 func idFromInfo(path string, info fs.FileInfo) fileID { 39 return fileID(path) 40 } 41 42 // newQidPool allocates a QidPool. 43 func newQidPool() *QidPool { 44 return &QidPool{ 45 m: make(map[fileID]*qidRec), 46 } 47 } 48 49 // lookup looks up the file in the QidPool. 50 // If found, it returns the corresponding Qid and true. 51 // If not found, it returns nil and false. 52 func (pool *QidPool) lookup(f *File) (lib9p.Qid, bool) { 53 id, err := f.id() 54 if err != nil { 55 return lib9p.Qid{}, false 56 } 57 ospath := filepath.Join(f.fs.rootPath, f.path) 58 fsfi, err := os.Stat(ospath) 59 if err != nil { 60 return lib9p.Qid{}, false 61 } 62 return pool.lookupID(id, fsfi.ModTime()) 63 } 64 65 // lookupID looksup the file in the QidPool by fileID. 66 // It also checks if the file is modified after the last access by 67 // comparing the qidReq.mtime and mtime, and update Qid.Vers if needed. 68 func (pool *QidPool) lookupID(id fileID, mtime time.Time) (lib9p.Qid, bool) { 69 qrec, ok := pool.m[id] 70 if !ok { 71 return lib9p.Qid{}, false 72 } 73 if qrec.mtime.Before(mtime) { 74 qrec.qid.Vers++ 75 qrec.mtime = mtime 76 } 77 return *qrec.qid, ok 78 } 79 80 // add adds the file's Qid to the QidPool and returns the newly added Qid. 81 func (pool *QidPool) add(f *File) (lib9p.Qid, error) { 82 id, err := f.id() 83 if err != nil { 84 return lib9p.Qid{}, fmt.Errorf("get id: %v", err) 85 } 86 ospath := filepath.Join(f.fs.rootPath, f.path) 87 fi, err := os.Stat(ospath) 88 if err != nil { 89 return lib9p.Qid{}, fmt.Errorf("stat %v: %v", f, err) 90 } 91 return pool.addID(id, fi) 92 } 93 94 // addID does the same as add, but by fileID. 95 func (pool *QidPool) addID(id fileID, info fs.FileInfo) (lib9p.Qid, error) { 96 qtype := lib9p.FSModeToQidType(info.Mode()) 97 qid := &lib9p.Qid{ 98 Path: pool.nextQid, 99 Type: qtype, 100 } 101 pool.m[id] = &qidRec{qid: qid, mtime: info.ModTime()} 102 pool.nextQid++ 103 return *qid, nil 104 } 105 106 // delete deletes Qid associated with f from the QidPool. 107 func (pool *QidPool) delete(f *File) { 108 id, err := f.id() 109 if err != nil { 110 return 111 } 112 delete(pool.m, id) 113 }