github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/pkg/p9/file.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 p9
    16  
    17  import (
    18  	"github.com/ttpreport/gvisor-ligolo/pkg/fd"
    19  	"golang.org/x/sys/unix"
    20  )
    21  
    22  // AttacherOptions contains Attacher configuration.
    23  type AttacherOptions struct {
    24  	// SetAttrOnDeleted is set to true if it's safe to call File.SetAttr for
    25  	// deleted files.
    26  	SetAttrOnDeleted bool
    27  
    28  	// AllocateOnDeleted is set to true if it's safe to call File.Allocate for
    29  	// deleted files.
    30  	AllocateOnDeleted bool
    31  
    32  	// MultiGetAttrSupported is set to true if it's safe to call
    33  	// File.MultiGetAttr with read concurrency guarantee only on start directory.
    34  	MultiGetAttrSupported bool
    35  }
    36  
    37  // NoServerOptions partially implements Attacher with empty AttacherOptions.
    38  type NoServerOptions struct{}
    39  
    40  // ServerOptions implements Attacher.
    41  func (*NoServerOptions) ServerOptions() AttacherOptions {
    42  	return AttacherOptions{}
    43  }
    44  
    45  // Attacher is provided by the server.
    46  type Attacher interface {
    47  	// Attach returns a new File.
    48  	//
    49  	// The client-side attach will be translated to a series of walks from
    50  	// the file returned by this Attach call.
    51  	Attach() (File, error)
    52  
    53  	// ServerOptions returns configuration options for this attach point.
    54  	//
    55  	// This is never caller in the client-side.
    56  	ServerOptions() AttacherOptions
    57  }
    58  
    59  // File is a set of operations corresponding to a single node.
    60  //
    61  // Note that on the server side, the server logic places constraints on
    62  // concurrent operations to make things easier. This may reduce the need for
    63  // complex, error-prone locking and logic in the backend. These are documented
    64  // for each method.
    65  //
    66  // There are three different types of guarantees provided:
    67  //
    68  // none: There is no concurrency guarantee. The method may be invoked
    69  // concurrently with any other method on any other file.
    70  //
    71  // read: The method is guaranteed to be exclusive of any write or global
    72  // operation that is mutating the state of the directory tree starting at this
    73  // node. For example, this means creating new files, symlinks, directories or
    74  // renaming a directory entry (or renaming in to this target), but the method
    75  // may be called concurrently with other read methods.
    76  //
    77  // write: The method is guaranteed to be exclusive of any read, write or global
    78  // operation that is mutating the state of the directory tree starting at this
    79  // node, as described in read above. There may however, be other write
    80  // operations executing concurrently on other components in the directory tree.
    81  //
    82  // global: The method is guaranteed to be exclusive of any read, write or
    83  // global operation.
    84  type File interface {
    85  	// Walk walks to the path components given in names.
    86  	//
    87  	// Walk returns QIDs in the same order that the names were passed in.
    88  	//
    89  	// An empty list of arguments should return a copy of the current file.
    90  	//
    91  	// On the server, Walk has a read concurrency guarantee.
    92  	Walk(names []string) ([]QID, File, error)
    93  
    94  	// WalkGetAttr walks to the next file and returns its maximal set of
    95  	// attributes.
    96  	//
    97  	// Server-side p9.Files may return unix.ENOSYS to indicate that Walk
    98  	// and GetAttr should be used separately to satisfy this request.
    99  	//
   100  	// On the server, WalkGetAttr has a read concurrency guarantee.
   101  	WalkGetAttr([]string) ([]QID, File, AttrMask, Attr, error)
   102  
   103  	// MultiGetAttr batches up multiple calls to GetAttr(). names is a list of
   104  	// path components similar to Walk(). If the first component name is empty,
   105  	// the current file is stat'd and included in the results. If the walk reaches
   106  	// a file that doesn't exist or not a directory, MultiGetAttr returns the
   107  	// partial result with no error.
   108  	//
   109  	// On the server, MultiGetAttr has a read concurrency guarantee.
   110  	MultiGetAttr(names []string) ([]FullStat, error)
   111  
   112  	// StatFS returns information about the file system associated with
   113  	// this file.
   114  	//
   115  	// On the server, StatFS has no concurrency guarantee.
   116  	StatFS() (FSStat, error)
   117  
   118  	// GetAttr returns attributes of this node.
   119  	//
   120  	// On the server, GetAttr has a read concurrency guarantee.
   121  	GetAttr(req AttrMask) (QID, AttrMask, Attr, error)
   122  
   123  	// SetAttr sets attributes on this node.
   124  	//
   125  	// On the server, SetAttr has a write concurrency guarantee.
   126  	SetAttr(valid SetAttrMask, attr SetAttr) error
   127  
   128  	// GetXattr returns extended attributes of this node.
   129  	//
   130  	// Size indicates the size of the buffer that has been allocated to hold the
   131  	// attribute value. If the value is larger than size, implementations may
   132  	// return ERANGE to indicate that the buffer is too small, but they are also
   133  	// free to ignore the hint entirely (i.e. the value returned may be larger
   134  	// than size). All size checking is done independently at the syscall layer.
   135  	//
   136  	// On the server, GetXattr has a read concurrency guarantee.
   137  	GetXattr(name string, size uint64) (string, error)
   138  
   139  	// SetXattr sets extended attributes on this node.
   140  	//
   141  	// On the server, SetXattr has a write concurrency guarantee.
   142  	SetXattr(name, value string, flags uint32) error
   143  
   144  	// ListXattr lists the names of the extended attributes on this node.
   145  	//
   146  	// Size indicates the size of the buffer that has been allocated to hold the
   147  	// attribute list. If the list would be larger than size, implementations may
   148  	// return ERANGE to indicate that the buffer is too small, but they are also
   149  	// free to ignore the hint entirely (i.e. the value returned may be larger
   150  	// than size). All size checking is done independently at the syscall layer.
   151  	//
   152  	// On the server, ListXattr has a read concurrency guarantee.
   153  	ListXattr(size uint64) (map[string]struct{}, error)
   154  
   155  	// RemoveXattr removes extended attributes on this node.
   156  	//
   157  	// On the server, RemoveXattr has a write concurrency guarantee.
   158  	RemoveXattr(name string) error
   159  
   160  	// Allocate allows the caller to directly manipulate the allocated disk space
   161  	// for the file. See fallocate(2) for more details.
   162  	Allocate(mode AllocateMode, offset, length uint64) error
   163  
   164  	// Close is called when all references are dropped on the server side,
   165  	// and Close should be called by the client to drop all references.
   166  	//
   167  	// For server-side implementations of Close, the error is ignored.
   168  	//
   169  	// Close must be called even when Open has not been called.
   170  	//
   171  	// On the server, Close has no concurrency guarantee.
   172  	Close() error
   173  
   174  	// SetAttrClose is the equivalent of calling SetAttr() followed by Close().
   175  	// This can be used to set file times before closing the file in a single
   176  	// operation.
   177  	//
   178  	// On the server, SetAttr has a write concurrency guarantee.
   179  	// On the server, Close has no concurrency guarantee.
   180  	SetAttrClose(valid SetAttrMask, attr SetAttr) error
   181  
   182  	// Open must be called prior to using Read, Write or Readdir. Once Open
   183  	// is called, some operations, such as Walk, will no longer work.
   184  	//
   185  	// On the client, Open should be called only once. The fd return is
   186  	// optional, and may be nil.
   187  	//
   188  	// On the server, Open has a read concurrency guarantee. If an *fd.FD
   189  	// is provided, ownership now belongs to the caller. Open is guaranteed
   190  	// to be called only once.
   191  	//
   192  	// N.B. The server must resolve any lazy paths when open is called.
   193  	// After this point, read and write may be called on files with no
   194  	// deletion check, so resolving in the data path is not viable.
   195  	Open(flags OpenFlags) (*fd.FD, QID, uint32, error)
   196  
   197  	// Read reads from this file. Open must be called first.
   198  	//
   199  	// This may return io.EOF in addition to unix.Errno values.
   200  	//
   201  	// On the server, ReadAt has a read concurrency guarantee. See Open for
   202  	// additional requirements regarding lazy path resolution.
   203  	ReadAt(p []byte, offset uint64) (int, error)
   204  
   205  	// Write writes to this file. Open must be called first.
   206  	//
   207  	// This may return io.EOF in addition to unix.Errno values.
   208  	//
   209  	// On the server, WriteAt has a read concurrency guarantee. See Open
   210  	// for additional requirements regarding lazy path resolution.
   211  	WriteAt(p []byte, offset uint64) (int, error)
   212  
   213  	// FSync syncs this node. Open must be called first.
   214  	//
   215  	// On the server, FSync has a read concurrency guarantee.
   216  	FSync() error
   217  
   218  	// Create creates a new regular file and opens it according to the
   219  	// flags given. This file is already Open.
   220  	//
   221  	// N.B. On the client, the returned file is a reference to the current
   222  	// file, which now represents the created file. This is not the case on
   223  	// the server. These semantics are very subtle and can easily lead to
   224  	// bugs, but are a consequence of the 9P create operation.
   225  	//
   226  	// See p9.File.Open for a description of *fd.FD.
   227  	//
   228  	// On the server, Create has a write concurrency guarantee.
   229  	Create(name string, flags OpenFlags, permissions FileMode, uid UID, gid GID) (*fd.FD, File, QID, uint32, error)
   230  
   231  	// Mkdir creates a subdirectory.
   232  	//
   233  	// On the server, Mkdir has a write concurrency guarantee.
   234  	Mkdir(name string, permissions FileMode, uid UID, gid GID) (QID, error)
   235  
   236  	// Symlink makes a new symbolic link.
   237  	//
   238  	// On the server, Symlink has a write concurrency guarantee.
   239  	Symlink(oldName string, newName string, uid UID, gid GID) (QID, error)
   240  
   241  	// Link makes a new hard link.
   242  	//
   243  	// On the server, Link has a write concurrency guarantee.
   244  	Link(target File, newName string) error
   245  
   246  	// Mknod makes a new device node.
   247  	//
   248  	// On the server, Mknod has a write concurrency guarantee.
   249  	Mknod(name string, mode FileMode, major uint32, minor uint32, uid UID, gid GID) (QID, error)
   250  
   251  	// Rename renames the file.
   252  	//
   253  	// Rename will never be called on the server, and RenameAt will always
   254  	// be used instead.
   255  	Rename(newDir File, newName string) error
   256  
   257  	// RenameAt renames a given file to a new name in a potentially new
   258  	// directory.
   259  	//
   260  	// oldName must be a name relative to this file, which must be a
   261  	// directory. newName is a name relative to newDir.
   262  	//
   263  	// On the server, RenameAt has a global concurrency guarantee.
   264  	RenameAt(oldName string, newDir File, newName string) error
   265  
   266  	// UnlinkAt the given named file.
   267  	//
   268  	// name must be a file relative to this directory.
   269  	//
   270  	// Flags are implementation-specific (e.g. O_DIRECTORY), but are
   271  	// generally Linux unlinkat(2) flags.
   272  	//
   273  	// On the server, UnlinkAt has a write concurrency guarantee.
   274  	UnlinkAt(name string, flags uint32) error
   275  
   276  	// Readdir reads directory entries.
   277  	//
   278  	// This may return io.EOF in addition to unix.Errno values. count is the
   279  	// number of bytes to read.
   280  	//
   281  	// direntOffset is the directory offset at which the read should happen.
   282  	// direntOffset can be set to 0 to start reading the directory from start.
   283  	// direntOffset is used more like a cookie. The unit of direntOffset is
   284  	// unspecified. Gofers can choose their own unit. The client must set it
   285  	// to one of the values returned in Dirent.Offset, preferably the last offset
   286  	// returned, which should cause the readdir to continue from where it was
   287  	// left off.
   288  	//
   289  	// On the server, Readdir has a read concurrency guarantee.
   290  	Readdir(direntOffset uint64, count uint32) ([]Dirent, error)
   291  
   292  	// Readlink reads the link target.
   293  	//
   294  	// On the server, Readlink has a read concurrency guarantee.
   295  	Readlink() (string, error)
   296  
   297  	// Flush is called prior to Close.
   298  	//
   299  	// Whereas Close drops all references to the file, Flush cleans up the
   300  	// file state. Behavior is implementation-specific.
   301  	//
   302  	// Flush is not related to flush(9p). Flush is an extension to 9P2000.L,
   303  	// see version.go.
   304  	//
   305  	// On the server, Flush has a read concurrency guarantee.
   306  	Flush() error
   307  
   308  	// Bind binds to a host unix domain socket. If successful, it creates a
   309  	// socket file on the host filesystem and returns a File for the newly
   310  	// created socket file. The File implementation must save the bound socket
   311  	// FD so that subsequent Listen and Accept operations on the File can be
   312  	// served.
   313  	//
   314  	// Bind is an extension to 9P2000.L, see version.go.
   315  	//
   316  	// On the server, Bind has a write concurrency guarantee.
   317  	Bind(sockType uint32, sockName string, uid UID, gid GID) (File, QID, AttrMask, Attr, error)
   318  
   319  	// Connect establishes a new host-socket backed connection with a
   320  	// socket. A File does not need to be opened before it can be connected
   321  	// and it can be connected to multiple times resulting in a unique
   322  	// *fd.FD each time. In addition, the lifetime of the *fd.FD is
   323  	// independent from the lifetime of the p9.File and must be managed by
   324  	// the caller.
   325  	//
   326  	// The returned FD must be non-blocking.
   327  	//
   328  	// Flags indicates the requested type of socket.
   329  	//
   330  	// On the server, Connect has a read concurrency guarantee.
   331  	Connect(socketType SocketType) (*fd.FD, error)
   332  
   333  	// Renamed is called when this node is renamed.
   334  	//
   335  	// This may not fail. The file will hold a reference to its parent
   336  	// within the p9 package, and is therefore safe to use for the lifetime
   337  	// of this File (until Close is called).
   338  	//
   339  	// This method should not be called by clients, who should use the
   340  	// relevant Rename methods. (Although the method will be a no-op.)
   341  	//
   342  	// On the server, Renamed has a global concurrency guarantee.
   343  	Renamed(newDir File, newName string)
   344  }
   345  
   346  // DefaultWalkGetAttr implements File.WalkGetAttr to return ENOSYS for server-side Files.
   347  type DefaultWalkGetAttr struct{}
   348  
   349  // WalkGetAttr implements File.WalkGetAttr.
   350  func (*DefaultWalkGetAttr) WalkGetAttr([]string) ([]QID, File, AttrMask, Attr, error) {
   351  	return nil, nil, AttrMask{}, Attr{}, unix.ENOSYS
   352  }
   353  
   354  // DisallowClientCalls panics if a client-only function is called.
   355  type DisallowClientCalls struct{}
   356  
   357  // SetAttrClose implements File.SetAttrClose.
   358  func (*DisallowClientCalls) SetAttrClose(SetAttrMask, SetAttr) error {
   359  	panic("SetAttrClose should not be called on the server")
   360  }
   361  
   362  // DisallowServerCalls panics if a server-only function is called.
   363  type DisallowServerCalls struct{}
   364  
   365  // Renamed implements File.Renamed.
   366  func (*DisallowServerCalls) Renamed(File, string) {
   367  	panic("Renamed should not be called on the client")
   368  }
   369  
   370  // ServerOptions implements Attacher.
   371  func (*DisallowServerCalls) ServerOptions() AttacherOptions {
   372  	panic("ServerOptions should not be called on the client")
   373  }