Adds IsDir and Seek to platform.File (#1441)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2023-05-09 07:47:25 +08:00
committed by GitHub
parent 99d45623c0
commit 29c7c7667b
18 changed files with 576 additions and 273 deletions

View File

@@ -214,6 +214,11 @@ func (r *lazyDir) AccessMode() int {
return syscall.O_RDONLY
}
// IsDir implements the same method as documented on platform.File
func (r *lazyDir) IsDir() (bool, syscall.Errno) {
return true, 0
}
// Stat implements the same method as documented on platform.File
func (r *lazyDir) Stat() (platform.Stat_t, syscall.Errno) {
if f, ok := r.file(); !ok {
@@ -233,6 +238,11 @@ func (r *lazyDir) Pread([]byte, int64) (int, syscall.Errno) {
return 0, syscall.EISDIR
}
// Seek implements File.Seek
func (r *lazyDir) Seek(int64, int) (int64, syscall.Errno) {
return 0, syscall.EISDIR
}
// Write implements the same method as documented on platform.File
func (r *lazyDir) Write([]byte) (int, syscall.Errno) {
return 0, syscall.EBADF
@@ -359,20 +369,17 @@ type FileEntry struct {
type cachedStat struct {
// Ino is the file serial number, or zero if not available.
Ino uint64
// Type is the same as what's documented on platform.Dirent.
Type fs.FileMode
}
// CachedStat returns the cacheable parts of platform.Stat_t or an error if
// they couldn't be retrieved.
func (f *FileEntry) CachedStat() (ino uint64, fileType fs.FileMode, errno syscall.Errno) {
// Inode returns the cached inode from of platform.Stat_t or an error if it
// couldn't be retrieved.
func (f *FileEntry) Inode() (ino uint64, errno syscall.Errno) {
if f.cachedStat == nil {
if _, errno = f.Stat(); errno != 0 {
return
}
}
return f.cachedStat.Ino, f.cachedStat.Type, 0
return f.cachedStat.Ino, 0
}
// Stat returns the underlying stat of this file.
@@ -387,7 +394,7 @@ func (f *FileEntry) Stat() (st platform.Stat_t, errno syscall.Errno) {
}
if errno == 0 {
f.cachedStat = &cachedStat{Ino: st.Ino, Type: st.Mode & fs.ModeType}
f.cachedStat = &cachedStat{Ino: st.Ino}
}
return
}
@@ -547,10 +554,10 @@ func (c *FSContext) ReOpenDir(fd int32) (*FileEntry, syscall.Errno) {
f, ok := c.openedFiles.Lookup(fd)
if !ok {
return nil, syscall.EBADF
} else if _, ft, errno := f.CachedStat(); errno != 0 {
} else if isDir, errno := f.File.IsDir(); errno != 0 {
return nil, errno
} else if ft.Type() != fs.ModeDir {
return nil, syscall.EISDIR
} else if !isDir {
return nil, syscall.ENOTDIR
}
if errno := c.reopen(f); errno != 0 {
@@ -583,9 +590,9 @@ func (c *FSContext) ChangeOpenFlag(fd int32, flag int) syscall.Errno {
f, ok := c.LookupFile(fd)
if !ok {
return syscall.EBADF
} else if _, ft, errno := f.CachedStat(); errno != 0 {
} else if isDir, errno := f.File.IsDir(); errno != 0 {
return errno
} else if ft.Type() == fs.ModeDir {
} else if isDir {
return syscall.EISDIR
}

View File

@@ -87,7 +87,7 @@ func TestNewFSContext(t *testing.T) {
// test to ensure that our implementation properly reuses descriptor
// numbers but if we were to change the reuse strategy, this test
// would likely break and need to be updated.
require.Zero(t, fsc.CloseFile(f1))
require.EqualErrno(t, 0, fsc.CloseFile(f1))
f2, errno := fsc.OpenFile(preopenedDir.FS, preopenedDir.Name, 0, 0)
require.EqualErrno(t, 0, errno)
require.Equal(t, f1, f2)
@@ -113,7 +113,7 @@ func TestFSContext_CloseFile(t *testing.T) {
require.EqualErrno(t, 0, errno)
// Close
require.Zero(t, fsc.CloseFile(fdToClose))
require.EqualErrno(t, 0, fsc.CloseFile(fdToClose))
// Verify fdToClose is closed and removed from the opened FDs.
_, ok := fsc.LookupFile(fdToClose)
@@ -127,7 +127,7 @@ func TestFSContext_CloseFile(t *testing.T) {
require.EqualErrno(t, syscall.EBADF, fsc.CloseFile(42)) // 42 is an arbitrary invalid FD
})
t.Run("Can close a pre-open", func(t *testing.T) {
require.Zero(t, fsc.CloseFile(FdPreopen))
require.EqualErrno(t, 0, fsc.CloseFile(FdPreopen))
})
}
@@ -275,7 +275,7 @@ func TestFSContext_ReOpenDir(t *testing.T) {
require.EqualErrno(t, 0, errno)
_, errno = fsc.ReOpenDir(fd)
require.EqualErrno(t, syscall.EISDIR, errno)
require.EqualErrno(t, syscall.ENOTDIR, errno)
})
}
@@ -301,7 +301,7 @@ func TestFSContext_Renumber(t *testing.T) {
prevDirFile, ok := fsc.LookupFile(fromFd)
require.True(t, ok)
require.Zero(t, fsc.Renumber(fromFd, toFd))
require.EqualErrno(t, 0, fsc.Renumber(fromFd, toFd))
renumberedDirFile, ok := fsc.LookupFile(toFd)
require.True(t, ok)
@@ -355,13 +355,13 @@ func TestFSContext_ChangeOpenFlag(t *testing.T) {
require.Equal(t, f0.openFlag&syscall.O_APPEND, 0)
// Set the APPEND flag.
require.Zero(t, fsc.ChangeOpenFlag(fd, syscall.O_APPEND))
require.EqualErrno(t, 0, fsc.ChangeOpenFlag(fd, syscall.O_APPEND))
f1, ok := fsc.openedFiles.Lookup(fd)
require.True(t, ok)
require.Equal(t, f1.openFlag&syscall.O_APPEND, syscall.O_APPEND)
// Remove the APPEND flag.
require.Zero(t, fsc.ChangeOpenFlag(fd, 0))
require.EqualErrno(t, 0, fsc.ChangeOpenFlag(fd, 0))
f2, ok := fsc.openedFiles.Lookup(fd)
require.True(t, ok)
require.Equal(t, f2.openFlag&syscall.O_APPEND, 0)

View File

@@ -2,7 +2,6 @@ package sys
import (
"bytes"
"io/fs"
"runtime"
"strings"
"testing"
@@ -67,7 +66,7 @@ func TestDefaultSysContext(t *testing.T) {
require.Equal(t, expectedOpenedFiles, sysCtx.FS().openedFiles)
}
func TestFileEntry_cachedStat(t *testing.T) {
func TestFileEntryInode(t *testing.T) {
t.Parallel()
tmpDir := t.TempDir()
@@ -98,14 +97,13 @@ func TestFileEntry_cachedStat(t *testing.T) {
f, ok := fsc.LookupFile(FdPreopen)
require.True(t, ok)
ino, ft, errno := f.CachedStat()
ino, errno := f.Inode()
require.EqualErrno(t, 0, errno)
require.Equal(t, fs.ModeDir, ft)
if !canReadDirInode() {
tc.expectedIno = 0
}
require.Equal(t, tc.expectedIno, ino)
require.Equal(t, &cachedStat{Ino: tc.expectedIno, Type: fs.ModeDir}, f.cachedStat)
require.Equal(t, &cachedStat{Ino: tc.expectedIno}, f.cachedStat)
})
}
}