Centralizes docs on Ino, specifically zero (#1560)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -7,16 +7,38 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Dirent is an entry read from a directory.
|
||||
// Ino is the file serial number, or zero if unknown.
|
||||
//
|
||||
// The inode is used for a file equivalence, like os.SameFile, so any constant
|
||||
// value will interfere that.
|
||||
//
|
||||
// When zero is returned by File.Readdir, certain callers will fan-out to
|
||||
// File.Stat to retrieve a non-zero value. Callers using this for darwin's
|
||||
// definition of `getdirentries` conflate zero `d_fileno` with a deleted file
|
||||
// and skip the entry. See /RATIONALE.md for more on this.
|
||||
type Ino = uint64
|
||||
|
||||
// FileType is fs.FileMode masked on fs.ModeType. For example, zero is a
|
||||
// regular file, fs.ModeDir is a directory and fs.ModeIrregular is unknown.
|
||||
//
|
||||
// Note: This is defined by Linux, not POSIX.
|
||||
type FileType = fs.FileMode
|
||||
|
||||
// Dirent is an entry read from a directory via File.Readdir.
|
||||
//
|
||||
// # Notes
|
||||
//
|
||||
// - This extends `dirent` defined in POSIX with some fields defined by
|
||||
// Linux. See https://man7.org/linux/man-pages/man3/readdir.3.html and
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/dirent.h.html
|
||||
// - This has a subset of fields defined in Stat_t. Notably, there is no
|
||||
// field corresponding to Stat_t.Dev because that value will be constant
|
||||
// for all files in a directory. To get the Dev value, call File.Stat on
|
||||
// the directory File.Readdir was called on.
|
||||
type Dirent struct {
|
||||
// Ino is the file serial number, or zero if not available.
|
||||
Ino uint64
|
||||
// Ino is the file serial number, or zero if not available. See Ino for
|
||||
// more details including impact returning a zero value.
|
||||
Ino Ino
|
||||
|
||||
// Name is the base name of the directory entry. Empty is invalid.
|
||||
Name string
|
||||
|
||||
@@ -55,7 +55,7 @@ type File interface {
|
||||
//
|
||||
// - Implementations should cache this result.
|
||||
// - This combined with Dev can implement os.SameFile.
|
||||
Ino() (uint64, syscall.Errno)
|
||||
Ino() (Ino, syscall.Errno)
|
||||
|
||||
// IsDir returns true if this file is a directory or an error there was an
|
||||
// error retrieving this information.
|
||||
|
||||
@@ -13,8 +13,9 @@ type Stat_t struct {
|
||||
// Dev is the device ID of device containing the file.
|
||||
Dev uint64
|
||||
|
||||
// Ino is the file serial number.
|
||||
Ino uint64
|
||||
// Ino is the file serial number, or zero if not available. See Ino for
|
||||
// more details including impact returning a zero value.
|
||||
Ino Ino
|
||||
|
||||
// Uid is the user ID that owns the file, or zero if unsupported.
|
||||
// For example, this is unsupported on some virtual filesystems or windows.
|
||||
|
||||
@@ -97,7 +97,7 @@ func (UnimplementedFile) Dev() (uint64, syscall.Errno) {
|
||||
}
|
||||
|
||||
// Ino implements File.Ino
|
||||
func (UnimplementedFile) Ino() (uint64, syscall.Errno) {
|
||||
func (UnimplementedFile) Ino() (Ino, syscall.Errno) {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,8 @@ func synthesizeDotEntries(f *FileEntry) ([]fsapi.Dirent, syscall.Errno) {
|
||||
}
|
||||
result := [2]fsapi.Dirent{}
|
||||
result[0] = fsapi.Dirent{Name: ".", Ino: dotIno, Type: fs.ModeDir}
|
||||
// See /RATIONALE.md for why we don't attempt to get an inode for ".."
|
||||
// See /RATIONALE.md for why we don't attempt to get an inode for ".." and
|
||||
// why in wasi-libc this won't fan-out either.
|
||||
result[1] = fsapi.Dirent{Name: "..", Ino: 0, Type: fs.ModeDir}
|
||||
return result[:], 0
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func (r *lazyDir) Dev() (uint64, syscall.Errno) {
|
||||
}
|
||||
|
||||
// Ino implements the same method as documented on fsapi.File
|
||||
func (r *lazyDir) Ino() (uint64, syscall.Errno) {
|
||||
func (r *lazyDir) Ino() (fsapi.Ino, syscall.Errno) {
|
||||
if f, ok := r.file(); !ok {
|
||||
return 0, syscall.EBADF
|
||||
} else {
|
||||
|
||||
@@ -124,7 +124,7 @@ type cachedStat struct {
|
||||
dev uint64
|
||||
|
||||
// dev is the same as fsapi.Stat_t Ino.
|
||||
ino uint64
|
||||
ino fsapi.Ino
|
||||
|
||||
// isDir is fsapi.Stat_t Mode masked with fs.ModeDir
|
||||
isDir bool
|
||||
@@ -132,7 +132,7 @@ type cachedStat struct {
|
||||
|
||||
// cachedStat returns the cacheable parts of fsapi.Stat_t or an error if they
|
||||
// couldn't be retrieved.
|
||||
func (f *fsFile) cachedStat() (dev, ino uint64, isDir bool, errno syscall.Errno) {
|
||||
func (f *fsFile) cachedStat() (dev uint64, ino fsapi.Ino, isDir bool, errno syscall.Errno) {
|
||||
if f.cachedSt == nil {
|
||||
if _, errno = f.Stat(); errno != 0 {
|
||||
return
|
||||
@@ -148,7 +148,7 @@ func (f *fsFile) Dev() (uint64, syscall.Errno) {
|
||||
}
|
||||
|
||||
// Ino implements the same method as documented on fsapi.File
|
||||
func (f *fsFile) Ino() (uint64, syscall.Errno) {
|
||||
func (f *fsFile) Ino() (fsapi.Ino, syscall.Errno) {
|
||||
_, ino, _, errno := f.cachedStat()
|
||||
return ino, errno
|
||||
}
|
||||
@@ -435,7 +435,7 @@ func readdir(f readdirFile, path string, n int) (dirents []fsapi.Dirent, errno s
|
||||
dirents = make([]fsapi.Dirent, 0, len(fis))
|
||||
|
||||
// linux/darwin won't have to fan out to lstat, but windows will.
|
||||
var ino uint64
|
||||
var ino fsapi.Ino
|
||||
for fi := range fis {
|
||||
t := fis[fi]
|
||||
if ino, errno = inoFromFileInfo(path, t); errno != 0 {
|
||||
|
||||
@@ -151,7 +151,7 @@ func TestFileIno(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fs fs.FS
|
||||
expectedIno uint64
|
||||
expectedIno fsapi.Ino
|
||||
}{
|
||||
{name: "os.DirFS", fs: dirFS, expectedIno: st.Ino},
|
||||
{name: "embed.api.FS", fs: embedFS},
|
||||
|
||||
@@ -44,7 +44,7 @@ type osFile struct {
|
||||
|
||||
// cachedStat returns the cacheable parts of fsapi.Stat_t or an error if they
|
||||
// couldn't be retrieved.
|
||||
func (f *osFile) cachedStat() (dev, ino uint64, isDir bool, errno syscall.Errno) {
|
||||
func (f *osFile) cachedStat() (dev uint64, ino fsapi.Ino, isDir bool, errno syscall.Errno) {
|
||||
if f.cachedSt == nil {
|
||||
if _, errno = f.Stat(); errno != 0 {
|
||||
return
|
||||
@@ -60,7 +60,7 @@ func (f *osFile) Dev() (uint64, syscall.Errno) {
|
||||
}
|
||||
|
||||
// Ino implements the same method as documented on fsapi.File
|
||||
func (f *osFile) Ino() (uint64, syscall.Errno) {
|
||||
func (f *osFile) Ino() (fsapi.Ino, syscall.Errno) {
|
||||
_, ino, _, errno := f.cachedStat()
|
||||
return ino, errno
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func (r *readFile) Dev() (uint64, syscall.Errno) {
|
||||
}
|
||||
|
||||
// Ino implements the same method as documented on fsapi.File.
|
||||
func (r *readFile) Ino() (uint64, syscall.Errno) {
|
||||
func (r *readFile) Ino() (fsapi.Ino, syscall.Errno) {
|
||||
return r.f.Ino()
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ func statFile(f fs.File) (fsapi.Stat_t, syscall.Errno) {
|
||||
return defaultStatFile(f)
|
||||
}
|
||||
|
||||
func inoFromFileInfo(_ string, t fs.FileInfo) (ino uint64, err syscall.Errno) {
|
||||
func inoFromFileInfo(_ string, t fs.FileInfo) (ino fsapi.Ino, err syscall.Errno) {
|
||||
if d, ok := t.Sys().(*syscall.Stat_t); ok {
|
||||
ino = d.Ino
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func statFile(f fs.File) (fsapi.Stat_t, syscall.Errno) {
|
||||
return defaultStatFile(f)
|
||||
}
|
||||
|
||||
func inoFromFileInfo(_ string, t fs.FileInfo) (ino uint64, err syscall.Errno) {
|
||||
func inoFromFileInfo(_ string, t fs.FileInfo) (ino fsapi.Ino, err syscall.Errno) {
|
||||
if d, ok := t.Sys().(*syscall.Stat_t); ok {
|
||||
ino = d.Ino
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func statFile(f fs.File) (fsapi.Stat_t, syscall.Errno) {
|
||||
return defaultStatFile(f)
|
||||
}
|
||||
|
||||
func inoFromFileInfo(_ string, t fs.FileInfo) (ino uint64, err syscall.Errno) {
|
||||
func inoFromFileInfo(_ string, t fs.FileInfo) (ino fsapi.Ino, err syscall.Errno) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ func statFile(f fs.File) (fsapi.Stat_t, syscall.Errno) {
|
||||
}
|
||||
|
||||
// inoFromFileInfo uses stat to get the inode information of the file.
|
||||
func inoFromFileInfo(filePath string, t fs.FileInfo) (ino uint64, errno syscall.Errno) {
|
||||
func inoFromFileInfo(filePath string, t fs.FileInfo) (ino fsapi.Ino, errno syscall.Errno) {
|
||||
if filePath == "" {
|
||||
// This is a fs.File backed implementation which doesn't have access to
|
||||
// the original file path.
|
||||
|
||||
Reference in New Issue
Block a user