| // Copyright 2018 The gVisor Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package fs |
| |
| import ( |
| "io" |
| |
| "gvisor.dev/gvisor/pkg/context" |
| "gvisor.dev/gvisor/pkg/sentry/arch" |
| "gvisor.dev/gvisor/pkg/sentry/memmap" |
| "gvisor.dev/gvisor/pkg/usermem" |
| "gvisor.dev/gvisor/pkg/waiter" |
| ) |
| |
| // SpliceOpts define how a splice works. |
| type SpliceOpts struct { |
| // Length is the length of the splice operation. |
| Length int64 |
| |
| // SrcOffset indicates whether the existing source file offset should |
| // be used. If this is true, then the Start value below is used. |
| // |
| // When passed to FileOperations object, this should always be true as |
| // the offset will be provided by a layer above, unless the object in |
| // question is a pipe or socket. This value can be relied upon for such |
| // an indicator. |
| SrcOffset bool |
| |
| // SrcStart is the start of the source file. This is used only if |
| // SrcOffset is false. |
| SrcStart int64 |
| |
| // Dup indicates that the contents should not be consumed from the |
| // source (e.g. in the case of a socket or a pipe), but duplicated. |
| Dup bool |
| |
| // DstOffset indicates that the destination file offset should be used. |
| // |
| // See SrcOffset for additional information. |
| DstOffset bool |
| |
| // DstStart is the start of the destination file. This is used only if |
| // DstOffset is false. |
| DstStart int64 |
| } |
| |
| // FileOperations are operations on a File that diverge per file system. |
| // |
| // Operations that take a *File may use only the following interfaces: |
| // |
| // - File.UniqueID: Operations may only read this value. |
| // - File.Dirent: Operations must not take or drop a reference. |
| // - File.Offset(): This value is guaranteed to not change for the |
| // duration of the operation. |
| // - File.Flags(): This value may change during the operation. |
| type FileOperations interface { |
| // Release release resources held by FileOperations. |
| Release(ctx context.Context) |
| |
| // Waitable defines how this File can be waited on for read and |
| // write readiness. |
| waiter.Waitable |
| |
| // Seek seeks to offset based on SeekWhence. Returns the new |
| // offset or no change in the offset and an error. |
| Seek(ctx context.Context, file *File, whence SeekWhence, offset int64) (int64, error) |
| |
| // Readdir reads the directory entries of file and serializes them |
| // using serializer. |
| // |
| // Returns the new directory offset or no change in the offset and |
| // an error. The offset returned must not be less than file.Offset(). |
| // |
| // Serialization of directory entries must not happen asynchronously. |
| Readdir(ctx context.Context, file *File, serializer DentrySerializer) (int64, error) |
| |
| // Read reads from file into dst at offset and returns the number |
| // of bytes read which must be greater than or equal to 0. File |
| // systems that do not support reading at an offset, (i.e. pipefs, |
| // sockfs) may ignore the offset. These file systems are expected |
| // to construct Files with !FileFlags.Pread. |
| // |
| // Read may return a nil error and only partially fill dst (at or |
| // before EOF). If the file represents a symlink, Read reads the target |
| // value of the symlink. |
| // |
| // Read does not check permissions nor flags. |
| // |
| // Read must not be called if !FileFlags.Read. |
| Read(ctx context.Context, file *File, dst usermem.IOSequence, offset int64) (int64, error) |
| |
| // WriteTo is a variant of read that takes another file as a |
| // destination. For a splice (copy or move from one file to another), |
| // first a WriteTo on the source is attempted, followed by a ReadFrom |
| // on the destination, following by a buffered copy with standard Read |
| // and Write operations. |
| // |
| // If dup is set, the data should be duplicated into the destination |
| // and retained. |
| // |
| // The same preconditions as Read apply. |
| WriteTo(ctx context.Context, file *File, dst io.Writer, count int64, dup bool) (int64, error) |
| |
| // Write writes src to file at offset and returns the number of bytes |
| // written which must be greater than or equal to 0. Like Read, file |
| // systems that do not support writing at an offset (i.e. pipefs, sockfs) |
| // may ignore the offset. These file systems are expected to construct |
| // Files with !FileFlags.Pwrite. |
| // |
| // If only part of src could be written, Write must return an error |
| // indicating why (e.g. syserror.ErrWouldBlock). |
| // |
| // Write does not check permissions nor flags. |
| // |
| // Write must not be called if !FileFlags.Write. |
| Write(ctx context.Context, file *File, src usermem.IOSequence, offset int64) (int64, error) |
| |
| // ReadFrom is a variant of write that takes a another file as a |
| // source. See WriteTo for details regarding how this is called. |
| // |
| // The same preconditions as Write apply; FileFlags.Write must be set. |
| ReadFrom(ctx context.Context, file *File, src io.Reader, count int64) (int64, error) |
| |
| // Fsync writes buffered modifications of file and/or flushes in-flight |
| // operations to backing storage based on syncType. The range to sync is |
| // [start, end]. The end is inclusive so that the last byte of a maximally |
| // sized file can be synced. |
| Fsync(ctx context.Context, file *File, start, end int64, syncType SyncType) error |
| |
| // Flush this file's buffers/state (on close(2)). |
| Flush(ctx context.Context, file *File) error |
| |
| // ConfigureMMap mutates opts to implement mmap(2) for the file. Most |
| // implementations can either embed fsutil.FileNoMMap (if they don't support |
| // memory mapping) or call fsutil.GenericConfigureMMap with the appropriate |
| // memmap.Mappable. |
| ConfigureMMap(ctx context.Context, file *File, opts *memmap.MMapOpts) error |
| |
| // UnstableAttr returns the "unstable" attributes of the inode represented |
| // by the file. Most implementations can embed |
| // fsutil.FileUseInodeUnstableAttr, which delegates to |
| // InodeOperations.UnstableAttr. |
| UnstableAttr(ctx context.Context, file *File) (UnstableAttr, error) |
| |
| // Ioctl implements the ioctl(2) linux syscall. |
| // |
| // io provides access to the virtual memory space to which pointers in args |
| // refer. |
| // |
| // Preconditions: |
| // * The AddressSpace (if any) that io refers to is activated. |
| // * Must only be called from a task goroutine. |
| Ioctl(ctx context.Context, file *File, io usermem.IO, args arch.SyscallArguments) (uintptr, error) |
| } |
| |
| // FifoSizer is an interface for setting and getting the size of a pipe. |
| type FifoSizer interface { |
| // FifoSize returns the pipe capacity in bytes. |
| FifoSize(ctx context.Context, file *File) (int64, error) |
| |
| // SetFifoSize sets the new pipe capacity in bytes. |
| // |
| // The new size is returned (which may be capped). |
| SetFifoSize(size int64) (int64, error) |
| } |