github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/file_operations.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fs 16 17 import ( 18 "io" 19 20 "github.com/SagerNet/gvisor/pkg/context" 21 "github.com/SagerNet/gvisor/pkg/sentry/arch" 22 "github.com/SagerNet/gvisor/pkg/sentry/memmap" 23 "github.com/SagerNet/gvisor/pkg/usermem" 24 "github.com/SagerNet/gvisor/pkg/waiter" 25 ) 26 27 // SpliceOpts define how a splice works. 28 type SpliceOpts struct { 29 // Length is the length of the splice operation. 30 Length int64 31 32 // SrcOffset indicates whether the existing source file offset should 33 // be used. If this is true, then the Start value below is used. 34 // 35 // When passed to FileOperations object, this should always be true as 36 // the offset will be provided by a layer above, unless the object in 37 // question is a pipe or socket. This value can be relied upon for such 38 // an indicator. 39 SrcOffset bool 40 41 // SrcStart is the start of the source file. This is used only if 42 // SrcOffset is false. 43 SrcStart int64 44 45 // Dup indicates that the contents should not be consumed from the 46 // source (e.g. in the case of a socket or a pipe), but duplicated. 47 Dup bool 48 49 // DstOffset indicates that the destination file offset should be used. 50 // 51 // See SrcOffset for additional information. 52 DstOffset bool 53 54 // DstStart is the start of the destination file. This is used only if 55 // DstOffset is false. 56 DstStart int64 57 } 58 59 // FileOperations are operations on a File that diverge per file system. 60 // 61 // Operations that take a *File may use only the following interfaces: 62 // 63 // - File.UniqueID: Operations may only read this value. 64 // - File.Dirent: Operations must not take or drop a reference. 65 // - File.Offset(): This value is guaranteed to not change for the 66 // duration of the operation. 67 // - File.Flags(): This value may change during the operation. 68 type FileOperations interface { 69 // Release release resources held by FileOperations. 70 Release(ctx context.Context) 71 72 // Waitable defines how this File can be waited on for read and 73 // write readiness. 74 waiter.Waitable 75 76 // Seek seeks to offset based on SeekWhence. Returns the new 77 // offset or no change in the offset and an error. 78 Seek(ctx context.Context, file *File, whence SeekWhence, offset int64) (int64, error) 79 80 // Readdir reads the directory entries of file and serializes them 81 // using serializer. 82 // 83 // Returns the new directory offset or no change in the offset and 84 // an error. The offset returned must not be less than file.Offset(). 85 // 86 // Serialization of directory entries must not happen asynchronously. 87 Readdir(ctx context.Context, file *File, serializer DentrySerializer) (int64, error) 88 89 // Read reads from file into dst at offset and returns the number 90 // of bytes read which must be greater than or equal to 0. File 91 // systems that do not support reading at an offset, (i.e. pipefs, 92 // sockfs) may ignore the offset. These file systems are expected 93 // to construct Files with !FileFlags.Pread. 94 // 95 // Read may return a nil error and only partially fill dst (at or 96 // before EOF). If the file represents a symlink, Read reads the target 97 // value of the symlink. 98 // 99 // Read does not check permissions nor flags. 100 // 101 // Read must not be called if !FileFlags.Read. 102 Read(ctx context.Context, file *File, dst usermem.IOSequence, offset int64) (int64, error) 103 104 // WriteTo is a variant of read that takes another file as a 105 // destination. For a splice (copy or move from one file to another), 106 // first a WriteTo on the source is attempted, followed by a ReadFrom 107 // on the destination, following by a buffered copy with standard Read 108 // and Write operations. 109 // 110 // If dup is set, the data should be duplicated into the destination 111 // and retained. 112 // 113 // The same preconditions as Read apply. 114 WriteTo(ctx context.Context, file *File, dst io.Writer, count int64, dup bool) (int64, error) 115 116 // Write writes src to file at offset and returns the number of bytes 117 // written which must be greater than or equal to 0. Like Read, file 118 // systems that do not support writing at an offset (i.e. pipefs, sockfs) 119 // may ignore the offset. These file systems are expected to construct 120 // Files with !FileFlags.Pwrite. 121 // 122 // If only part of src could be written, Write must return an error 123 // indicating why (e.g. syserror.ErrWouldBlock). 124 // 125 // Write does not check permissions nor flags. 126 // 127 // Write must not be called if !FileFlags.Write. 128 Write(ctx context.Context, file *File, src usermem.IOSequence, offset int64) (int64, error) 129 130 // ReadFrom is a variant of write that takes a another file as a 131 // source. See WriteTo for details regarding how this is called. 132 // 133 // The same preconditions as Write apply; FileFlags.Write must be set. 134 ReadFrom(ctx context.Context, file *File, src io.Reader, count int64) (int64, error) 135 136 // Fsync writes buffered modifications of file and/or flushes in-flight 137 // operations to backing storage based on syncType. The range to sync is 138 // [start, end]. The end is inclusive so that the last byte of a maximally 139 // sized file can be synced. 140 Fsync(ctx context.Context, file *File, start, end int64, syncType SyncType) error 141 142 // Flush this file's buffers/state (on close(2)). 143 Flush(ctx context.Context, file *File) error 144 145 // ConfigureMMap mutates opts to implement mmap(2) for the file. Most 146 // implementations can either embed fsutil.FileNoMMap (if they don't support 147 // memory mapping) or call fsutil.GenericConfigureMMap with the appropriate 148 // memmap.Mappable. 149 ConfigureMMap(ctx context.Context, file *File, opts *memmap.MMapOpts) error 150 151 // UnstableAttr returns the "unstable" attributes of the inode represented 152 // by the file. Most implementations can embed 153 // fsutil.FileUseInodeUnstableAttr, which delegates to 154 // InodeOperations.UnstableAttr. 155 UnstableAttr(ctx context.Context, file *File) (UnstableAttr, error) 156 157 // Ioctl implements the ioctl(2) linux syscall. 158 // 159 // io provides access to the virtual memory space to which pointers in args 160 // refer. 161 // 162 // Preconditions: 163 // * The AddressSpace (if any) that io refers to is activated. 164 // * Must only be called from a task goroutine. 165 Ioctl(ctx context.Context, file *File, io usermem.IO, args arch.SyscallArguments) (uintptr, error) 166 } 167 168 // FifoSizer is an interface for setting and getting the size of a pipe. 169 type FifoSizer interface { 170 // FifoSize returns the pipe capacity in bytes. 171 FifoSize(ctx context.Context, file *File) (int64, error) 172 173 // SetFifoSize sets the new pipe capacity in bytes. 174 // 175 // The new size is returned (which may be capped). 176 SetFifoSize(size int64) (int64, error) 177 }