summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/fsutil/file.go
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2019-01-14 20:33:29 -0800
committerShentubot <shentubot@google.com>2019-01-14 20:34:28 -0800
commitdc8450b5676d4c4ac9bcfa23cabd862e0060527d (patch)
treea4ef1ad59764f46f674b7003221ba8ae399b9e65 /pkg/sentry/fs/fsutil/file.go
parent343ebe9789087b099ea7feae19879f5c24e59bf1 (diff)
Remove fs.Handle, ramfs.Entry, and all the DeprecatedFileOperations.
More helper structs have been added to the fsutil package to make it easier to implement fs.InodeOperations and fs.FileOperations. PiperOrigin-RevId: 229305982 Change-Id: Ib6f8d3862f4216745116857913dbfa351530223b
Diffstat (limited to 'pkg/sentry/fs/fsutil/file.go')
-rw-r--r--pkg/sentry/fs/fsutil/file.go226
1 files changed, 161 insertions, 65 deletions
diff --git a/pkg/sentry/fs/fsutil/file.go b/pkg/sentry/fs/fsutil/file.go
index 46db2e51c..0970f782b 100644
--- a/pkg/sentry/fs/fsutil/file.go
+++ b/pkg/sentry/fs/fsutil/file.go
@@ -24,12 +24,12 @@ import (
"gvisor.googlesource.com/gvisor/pkg/waiter"
)
-// NoopRelease implements FileOperations.Release for files that have no
+// FileNoopRelease implements fs.FileOperations.Release for files that have no
// resources to release.
-type NoopRelease struct{}
+type FileNoopRelease struct{}
// Release is a no-op.
-func (NoopRelease) Release() {}
+func (FileNoopRelease) Release() {}
// SeekWithDirCursor is used to implement fs.FileOperations.Seek. If dirCursor
// is not nil and the seek was on a directory, the cursor will be updated.
@@ -127,71 +127,81 @@ func SeekWithDirCursor(ctx context.Context, file *fs.File, whence fs.SeekWhence,
return current, syserror.EINVAL
}
-// GenericSeek implements FileOperations.Seek for files that use a generic
-// seek implementation.
-type GenericSeek struct{}
+// FileGenericSeek implements fs.FileOperations.Seek for files that use a
+// generic seek implementation.
+type FileGenericSeek struct{}
// Seek implements fs.FileOperations.Seek.
-func (GenericSeek) Seek(ctx context.Context, file *fs.File, whence fs.SeekWhence, offset int64) (int64, error) {
+func (FileGenericSeek) Seek(ctx context.Context, file *fs.File, whence fs.SeekWhence, offset int64) (int64, error) {
return SeekWithDirCursor(ctx, file, whence, offset, nil)
}
-// ZeroSeek implements FileOperations.Seek for files that maintain a constant
-// zero-value offset and require a no-op Seek.
-type ZeroSeek struct{}
+// FileZeroSeek implements fs.FileOperations.Seek for files that maintain a
+// constant zero-value offset and require a no-op Seek.
+type FileZeroSeek struct{}
-// Seek implements FileOperations.Seek.
-func (ZeroSeek) Seek(context.Context, *fs.File, fs.SeekWhence, int64) (int64, error) {
+// Seek implements fs.FileOperations.Seek.
+func (FileZeroSeek) Seek(context.Context, *fs.File, fs.SeekWhence, int64) (int64, error) {
return 0, nil
}
-// PipeSeek implements FileOperations.Seek and can be used for files that behave
-// like pipes (seeking is not supported).
-type PipeSeek struct{}
+// FileNoSeek implements fs.FileOperations.Seek to return EINVAL.
+type FileNoSeek struct{}
+
+// Seek implements fs.FileOperations.Seek.
+func (FileNoSeek) Seek(context.Context, *fs.File, fs.SeekWhence, int64) (int64, error) {
+ return 0, syserror.EINVAL
+}
-// Seek implements FileOperations.Seek.
-func (PipeSeek) Seek(context.Context, *fs.File, fs.SeekWhence, int64) (int64, error) {
+// FilePipeSeek implements fs.FileOperations.Seek and can be used for files
+// that behave like pipes (seeking is not supported).
+type FilePipeSeek struct{}
+
+// Seek implements fs.FileOperations.Seek.
+func (FilePipeSeek) Seek(context.Context, *fs.File, fs.SeekWhence, int64) (int64, error) {
return 0, syserror.ESPIPE
}
-// NotDirReaddir implements FileOperations.Readdir for non-directories.
-type NotDirReaddir struct{}
+// FileNotDirReaddir implements fs.FileOperations.Readdir for non-directories.
+type FileNotDirReaddir struct{}
-// Readdir implements FileOperations.NotDirReaddir.
-func (NotDirReaddir) Readdir(context.Context, *fs.File, fs.DentrySerializer) (int64, error) {
+// Readdir implements fs.FileOperations.FileNotDirReaddir.
+func (FileNotDirReaddir) Readdir(context.Context, *fs.File, fs.DentrySerializer) (int64, error) {
return 0, syserror.ENOTDIR
}
-// NoFsync implements FileOperations.Fsync for files that don't support syncing.
-type NoFsync struct{}
+// FileNoFsync implements fs.FileOperations.Fsync for files that don't support
+// syncing.
+type FileNoFsync struct{}
-// Fsync implements FileOperations.Fsync.
-func (NoFsync) Fsync(context.Context, *fs.File, int64, int64, fs.SyncType) error {
+// Fsync implements fs.FileOperations.Fsync.
+func (FileNoFsync) Fsync(context.Context, *fs.File, int64, int64, fs.SyncType) error {
return syserror.EINVAL
}
-// NoopFsync implements FileOperations.Fsync for files that don't need to synced.
-type NoopFsync struct{}
+// FileNoopFsync implements fs.FileOperations.Fsync for files that don't need
+// to synced.
+type FileNoopFsync struct{}
-// Fsync implements FileOperations.Fsync.
-func (NoopFsync) Fsync(context.Context, *fs.File, int64, int64, fs.SyncType) error {
+// Fsync implements fs.FileOperations.Fsync.
+func (FileNoopFsync) Fsync(context.Context, *fs.File, int64, int64, fs.SyncType) error {
return nil
}
-// NoopFlush implements FileOperations.Flush as a no-op.
-type NoopFlush struct{}
+// FileNoopFlush implements fs.FileOperations.Flush as a no-op.
+type FileNoopFlush struct{}
-// Flush implements FileOperations.Flush.
-func (NoopFlush) Flush(context.Context, *fs.File) error {
+// Flush implements fs.FileOperations.Flush.
+func (FileNoopFlush) Flush(context.Context, *fs.File) error {
return nil
}
-// NoMMap implements fs.FileOperations.Mappable for files that cannot
+// FileNoMMap implements fs.FileOperations.Mappable for files that cannot
// be memory mapped.
-type NoMMap struct{}
+type FileNoMMap struct{}
// ConfigureMMap implements fs.FileOperations.ConfigureMMap.
-func (NoMMap) ConfigureMMap(context.Context, *fs.File, *memmap.MMapOpts) error {
+func (FileNoMMap) ConfigureMMap(context.Context, *fs.File, *memmap.MMapOpts) error {
return syserror.ENODEV
}
@@ -204,26 +214,43 @@ func GenericConfigureMMap(file *fs.File, m memmap.Mappable, opts *memmap.MMapOpt
return nil
}
-// NoIoctl implements fs.FileOperations.Ioctl for files that don't implement
-// the ioctl syscall.
-type NoIoctl struct{}
+// FileNoIoctl implements fs.FileOperations.Ioctl for files that don't
+// implement the ioctl syscall.
+type FileNoIoctl struct{}
// Ioctl implements fs.FileOperations.Ioctl.
-func (NoIoctl) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
+func (FileNoIoctl) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
return 0, syserror.ENOTTY
}
-// DirFileOperations implements FileOperations for directories.
+// DirFileOperations implements most of fs.FileOperations for directories,
+// except for Readdir which the embedding type must implement.
+type DirFileOperations struct {
+ waiter.AlwaysReady
+ FileGenericSeek
+ FileNoFsync
+ FileNoIoctl
+ FileNoMMap
+ FileNoopFlush
+ FileNoopRelease
+}
+
+// Read implements fs.FileOperations.Read
+func (*DirFileOperations) Read(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
+ return 0, syserror.EISDIR
+}
+
+// Write implements fs.FileOperations.Write.
+func (*DirFileOperations) Write(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
+ return 0, syserror.EISDIR
+}
+
+// StaticDirFileOperations implements fs.FileOperations for directories with
+// static children.
//
// +stateify savable
-type DirFileOperations struct {
- waiter.AlwaysReady `state:"nosave"`
- NoopRelease `state:"nosave"`
- GenericSeek `state:"nosave"`
- NoFsync `state:"nosave"`
- NoopFlush `state:"nosave"`
- NoMMap `state:"nosave"`
- NoIoctl `state:"nosave"`
+type StaticDirFileOperations struct {
+ DirFileOperations
// dentryMap is a SortedDentryMap used to implement Readdir.
dentryMap *fs.SortedDentryMap
@@ -233,37 +260,106 @@ type DirFileOperations struct {
dirCursor string
}
-// NewDirFileOperations returns a new DirFileOperations that will iterate the
-// given denty map.
-func NewDirFileOperations(dentries *fs.SortedDentryMap) *DirFileOperations {
- return &DirFileOperations{
+// NewStaticDirFileOperations returns a new StaticDirFileOperations that will
+// iterate the given denty map.
+func NewStaticDirFileOperations(dentries *fs.SortedDentryMap) *StaticDirFileOperations {
+ return &StaticDirFileOperations{
dentryMap: dentries,
}
}
// IterateDir implements DirIterator.IterateDir.
-func (dfo *DirFileOperations) IterateDir(ctx context.Context, dirCtx *fs.DirCtx, offset int) (int, error) {
- n, err := fs.GenericReaddir(dirCtx, dfo.dentryMap)
+func (sdfo *StaticDirFileOperations) IterateDir(ctx context.Context, dirCtx *fs.DirCtx, offset int) (int, error) {
+ n, err := fs.GenericReaddir(dirCtx, sdfo.dentryMap)
return offset + n, err
}
-// Readdir implements FileOperations.Readdir.
-func (dfo *DirFileOperations) Readdir(ctx context.Context, file *fs.File, serializer fs.DentrySerializer) (int64, error) {
+// Readdir implements fs.FileOperations.Readdir.
+func (sdfo *StaticDirFileOperations) Readdir(ctx context.Context, file *fs.File, serializer fs.DentrySerializer) (int64, error) {
root := fs.RootFromContext(ctx)
defer root.DecRef()
dirCtx := &fs.DirCtx{
Serializer: serializer,
- DirCursor: &dfo.dirCursor,
+ DirCursor: &sdfo.dirCursor,
}
- return fs.DirentReaddir(ctx, file.Dirent, dfo, root, dirCtx, file.Offset())
+ return fs.DirentReaddir(ctx, file.Dirent, sdfo, root, dirCtx, file.Offset())
}
-// Read implements FileOperations.Read
-func (*DirFileOperations) Read(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
- return 0, syserror.EISDIR
+// NoReadWriteFile is a file that does not support reading or writing.
+//
+// +stateify savable
+type NoReadWriteFile struct {
+ waiter.AlwaysReady `state:"nosave"`
+ FileGenericSeek `state:"nosave"`
+ FileNoIoctl `state:"nosave"`
+ FileNoMMap `state:"nosave"`
+ FileNoopFsync `state:"nosave"`
+ FileNoopFlush `state:"nosave"`
+ FileNoopRelease `state:"nosave"`
+ FileNoRead `state:"nosave"`
+ FileNoWrite `state:"nosave"`
+ FileNotDirReaddir `state:"nosave"`
}
-// Write implements FileOperations.Write.
-func (*DirFileOperations) Write(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
- return 0, syserror.EISDIR
+var _ fs.FileOperations = (*NoReadWriteFile)(nil)
+
+// FileStaticContentReader is a helper to implement fs.FileOperations.Read with
+// static content.
+//
+// +stateify savable
+type FileStaticContentReader struct {
+ // content is immutable.
+ content []byte
+}
+
+// NewFileStaticContentReader initializes a FileStaticContentReader with the
+// given content.
+func NewFileStaticContentReader(b []byte) FileStaticContentReader {
+ return FileStaticContentReader{
+ content: b,
+ }
+}
+
+// Read implements fs.FileOperations.Read.
+func (scr *FileStaticContentReader) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
+ if offset < 0 {
+ return 0, syserror.EINVAL
+ }
+ if offset >= int64(len(scr.content)) {
+ return 0, nil
+ }
+ n, err := dst.CopyOut(ctx, scr.content[offset:])
+ return int64(n), err
+}
+
+// FileNoopWrite implements fs.FileOperations.Write as a noop.
+type FileNoopWrite struct{}
+
+// Write implements fs.FileOperations.Write.
+func (FileNoopWrite) Write(_ context.Context, _ *fs.File, src usermem.IOSequence, _ int64) (int64, error) {
+ return src.NumBytes(), nil
+}
+
+// FileNoRead implements fs.FileOperations.Read to return EINVAL.
+type FileNoRead struct{}
+
+// Read implements fs.FileOperations.Read.
+func (FileNoRead) Read(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
+ return 0, syserror.EINVAL
+}
+
+// FileNoWrite implements fs.FileOperations.Write to return EINVAL.
+type FileNoWrite struct{}
+
+// Write implements fs.FileOperations.Write.
+func (FileNoWrite) Write(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
+ return 0, syserror.EINVAL
+}
+
+// FileNoopRead implement fs.FileOperations.Read as a noop.
+type FileNoopRead struct{}
+
+// Read implements fs.FileOperations.Read.
+func (FileNoopRead) Read(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
+ return 0, nil
}