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