lib9p

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

commit 2bbf1a97d3e0f23e87da85cbbdc809e603371461
parent 99310f35f7a64b95f962bafe1b8fccabd4b13260
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 19 Dec 2023 11:36:30 +0900

change fiStat to return error

Diffstat:
Mdiskfs/file.go | 7++++++-
Mdiskfs/stat_plan9.go | 10+++++++---
Mdiskfs/stat_unix.go | 57++++++++++++++++-----------------------------------------
Mdiskfs/stat_windows.go | 45++++++++++-----------------------------------
4 files changed, 39 insertions(+), 80 deletions(-)

diff --git a/diskfs/file.go b/diskfs/file.go @@ -82,7 +82,12 @@ func (f *File) ReadDir(n int) ([]fs.DirEntry, error) { return nil, fmt.Errorf("info: %v", err) } id := idFromInfo(f.path, fi) - de[i] = &lib9p.DirEntry{Stat: *fiStat(f.fs.qidPool, id, fi)} + stat, err := fiStat(f.fs.qidPool, id, fi) + if err != nil { + return nil, fmt.Errorf("fiStat: %v") + } + de[i] = &lib9p.DirEntry{Stat: *stat} + } return de, nil } diff --git a/diskfs/stat_plan9.go b/diskfs/stat_plan9.go @@ -16,7 +16,7 @@ import ( // fiStat generates lib9p.Stat from the FileInfo. // It requires QidPool and fileID to fill the Qid field of Stat. -func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { +func fiStat(pool *QidPool, id fileID, info fs.FileInfo) (*lib9p.Stat, error) { dir := info.Sys().(*syscall.Dir) qid := lib9p.Qid{ Type: lib9p.QidType(dir.Qid.Type), @@ -35,7 +35,7 @@ func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { Uid: dir.Uid, Gid: dir.Gid, Muid: dir.Muid, - } + }, nil } // Stat is real implementation of File.Stat. @@ -44,7 +44,11 @@ func (f *File) stat() (*lib9p.FileInfo, error) { if err != nil { return nil, fmt.Errorf("stat: %v", err) } - return &lib9p.FileInfo{Stat: *fiStat(nil, fileID{}, fi)}, nil + stat, err := fiStat(nil, fileID{}, fi) + if err != nil { + return nil, fmt.Errorf("fiStat: %v", err) + } + return &lib9p.FileInfo{Stat: *stat}, nil } // wstat is the real implementation of File.WStat. diff --git a/diskfs/stat_unix.go b/diskfs/stat_unix.go @@ -17,7 +17,7 @@ import ( // fiStat generates lib9p.Stat from the FileInfo. // It requires QidPool and fileID to fill the Qid field of Stat. -func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { +func fiStat(pool *QidPool, id fileID, info fs.FileInfo) (*lib9p.Stat, error) { qid, ok := pool.lookupID(id, info.ModTime()) if !ok { var err error @@ -30,14 +30,15 @@ func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { stat := info.Sys().(*syscall.Stat_t) usr, err := user.LookupId(strconv.Itoa(int(stat.Uid))) if err != nil { - panic(fmt.Errorf("user: %v", err)) + return nil, fmt.Errorf("user: %v", err) } - group, err := user.LookupGroupId(strconv.Itoa(int(stat.Gid))) - if err != nil { - // BUG: in OpenBSD, "user: lookup groupid 1000: too many open files" - panic(fmt.Errorf("group: %v", err)) + if _, ok := gidCache[id]; !ok { + group, err := user.LookupGroupId(strconv.Itoa(int(stat.Gid))) + if err != nil { + return nil, fmt.Errorf("LookupGroupId(%d): %v", stat.Gid, err) + } + gidCache[id] = group.Name } - return &lib9p.Stat{ Type: 0, Dev: 0, @@ -48,9 +49,9 @@ func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { Length: stat.Size, Name: info.Name(), Uid: usr.Username, - Gid: group.Name, + Gid: gidCache[id], Muid: "", - } + }, nil } var gidCache map[fileID]string @@ -66,41 +67,15 @@ func (f *File) stat() (*lib9p.FileInfo, error) { if err != nil { return nil, fmt.Errorf("stat: %v", err) } - var stat lib9p.Stat - stat.Type = 0 - stat.Dev = 0 - qid, ok := f.fs.qidPool.lookup(f) - if !ok { - qid, err = f.fs.qidPool.add(f) - if err != nil { - panic(fmt.Errorf("alloc qid: %v", err)) - } - } - stat_t := fsfi.Sys().(*syscall.Stat_t) - stat.Qid = qid - stat.Length = fsfi.Size() - stat.Mode = fsfi.Mode() - stat.Name = fsfi.Name() - stat.Atime = uint32(stat_t.Atim.Sec) - stat.Mtime = uint32(stat_t.Mtim.Sec) - uid := stat_t.Uid - usr, err := user.LookupId(strconv.Itoa(int(uid))) + id, err := f.id() if err != nil { - return nil, fmt.Errorf("LookupId(%d): %v", uid, err) + return nil, fmt.Errorf("id: %v", err) } - stat.Uid = usr.Username - gid := stat_t.Gid - fileid := fileID{device: uint64(stat_t.Dev), inode: stat_t.Ino} - if _, ok := gidCache[fileid]; !ok { - group, err := user.LookupGroupId(strconv.Itoa(int(gid))) - if err != nil { - return nil, fmt.Errorf("LookupGroupId(%d): %v", gid, err) - } - gidCache[fileid] = group.Name + stat, err := fiStat(f.fs.qidPool, id, fsfi) + if err != nil { + return nil, fmt.Errorf("fiStat: %v", err) } - stat.Gid = gidCache[fileid] - stat.Muid = "" - return &lib9p.FileInfo{stat}, nil + return &lib9p.FileInfo{*stat}, nil } // wstat is the real implementation of File.WStat. diff --git a/diskfs/stat_windows.go b/diskfs/stat_windows.go @@ -21,27 +21,26 @@ func fileTimeToUnixTime(t syscall.Filetime) uint32 { // fiStat generates lib9p.Stat from the FileInfo. // It requires QidPool and fileID to fill the Qid field of Stat. -func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { +func fiStat(pool *QidPool, id fileID, info fs.FileInfo) (*lib9p.Stat, error) { qid, ok := pool.lookupID(id, info.ModTime()) if !ok { var err error qid, err = pool.addID(id, info) if err != nil { - panic(fmt.Errorf("allocID: %v", err)) + return nil, fmt.Errorf("allocID: %v", err) } } - stat := info.Sys().(*syscall.Win32FileAttributeData) /* // TODO: get actual file uid usr, err := user.LookupId(strconv.Itoa(syscall.Getuid())) if err != nil { - panic(fmt.Errorf("user: %v", err)) + return nil, fmt.Errorf("user: %v", err) } // TODO: get actual file gid group, err := user.LookupGroupId(strconv.Itoa(syscall.Getgid())) if err != nil { - panic(fmt.Errorf("group: %v", err)) + return nil, fmt.Errorf("group: %v", err) } */ return &lib9p.Stat{ @@ -56,7 +55,7 @@ func fiStat(pool *QidPool, id fileID, info fs.FileInfo) *lib9p.Stat { Uid: "kenji", //usr.Username, Gid: "kenji", //group.Name, Muid: "", - } + }, nil } var gidCache map[fileID]string @@ -72,39 +71,15 @@ func (f *File) stat() (*lib9p.FileInfo, error) { if err != nil { return nil, fmt.Errorf("stat: %v", err) } - var stat lib9p.Stat - stat.Type = 0 - stat.Dev = 0 - qid, ok := f.fs.qidPool.lookup(f) - if !ok { - qid, err = f.fs.qidPool.add(f) - if err != nil { - panic(fmt.Errorf("alloc qid: %v", err)) - } - } - stat.Qid = qid - winfs := fsfi.Sys().(*syscall.Win32FileAttributeData) - stat.Length = fsfi.Size() - stat.Mode = fsfi.Mode() - stat.Name = fsfi.Name() - stat.Atime = fileTimeToUnixTime(winfs.LastAccessTime) - stat.Mtime = fileTimeToUnixTime(winfs.LastWriteTime) -/* - usr, err := user.LookupId(strconv.Itoa(syscall.Getuid())) + id, err := f.id() if err != nil { - return nil, fmt.Errorf("LookupId: %v", err) + return nil, fmt.Errorf("id: %v", err) } -*/ - stat.Uid = "kenji" // usr.Username -/* - group, err := user.LookupGroupId(strconv.Itoa(syscall.Getgid())) + stat, err := fiStat(f.fs.qidPool, id, fsfi) if err != nil { - return nil, fmt.Errorf("LookupGroupId: %v", err) + return nil, fmt.Errorf("fiStat: %v", err) } -*/ - stat.Gid = "kenji" //group.Name - stat.Muid = "" - return &lib9p.FileInfo{stat}, nil + return &lib9p.FileInfo{*stat}, nil } // wstat is the real implementation of File.WStat.