// 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) }