lib9p

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

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 }