Adds IsDir and Seek to platform.File (#1441)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user