github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/abi/linux/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 linux
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	"github.com/sagernet/gvisor/pkg/abi"
    22  )
    23  
    24  // Constants for open(2).
    25  const (
    26  	O_ACCMODE  = 000000003
    27  	O_RDONLY   = 000000000
    28  	O_WRONLY   = 000000001
    29  	O_RDWR     = 000000002
    30  	O_CREAT    = 000000100
    31  	O_EXCL     = 000000200
    32  	O_NOCTTY   = 000000400
    33  	O_TRUNC    = 000001000
    34  	O_APPEND   = 000002000
    35  	O_NONBLOCK = 000004000
    36  	O_DSYNC    = 000010000
    37  	O_ASYNC    = 000020000
    38  	O_NOATIME  = 001000000
    39  	O_CLOEXEC  = 002000000
    40  	O_SYNC     = 004000000 // __O_SYNC in Linux
    41  	O_PATH     = 010000000
    42  	O_TMPFILE  = 020000000 // __O_TMPFILE in Linux
    43  )
    44  
    45  // Constants for fstatat(2).
    46  const (
    47  	AT_SYMLINK_NOFOLLOW = 0x100
    48  )
    49  
    50  // Constants for mount(2).
    51  const (
    52  	MS_RDONLY      = 0x1
    53  	MS_NOSUID      = 0x2
    54  	MS_NODEV       = 0x4
    55  	MS_NOEXEC      = 0x8
    56  	MS_SYNCHRONOUS = 0x10
    57  	MS_REMOUNT     = 0x20
    58  	MS_MANDLOCK    = 0x40
    59  	MS_DIRSYNC     = 0x80
    60  	MS_NOATIME     = 0x400
    61  	MS_NODIRATIME  = 0x800
    62  	MS_BIND        = 0x1000
    63  	MS_MOVE        = 0x2000
    64  	MS_REC         = 0x4000
    65  
    66  	MS_POSIXACL    = 0x10000
    67  	MS_UNBINDABLE  = 0x20000
    68  	MS_PRIVATE     = 0x40000
    69  	MS_SLAVE       = 0x80000
    70  	MS_SHARED      = 0x100000
    71  	MS_RELATIME    = 0x200000
    72  	MS_KERNMOUNT   = 0x400000
    73  	MS_I_VERSION   = 0x800000
    74  	MS_STRICTATIME = 0x1000000
    75  
    76  	MS_MGC_VAL = 0xC0ED0000
    77  	MS_MGC_MSK = 0xffff0000
    78  )
    79  
    80  // Constants for umount2(2).
    81  const (
    82  	MNT_FORCE       = 0x1
    83  	MNT_DETACH      = 0x2
    84  	MNT_EXPIRE      = 0x4
    85  	UMOUNT_NOFOLLOW = 0x8
    86  )
    87  
    88  // Constants for unlinkat(2).
    89  const (
    90  	AT_REMOVEDIR = 0x200
    91  )
    92  
    93  // Constants for linkat(2) and fchownat(2).
    94  const (
    95  	AT_SYMLINK_FOLLOW = 0x400
    96  	AT_EMPTY_PATH     = 0x1000
    97  )
    98  
    99  // Constants for faccessat2(2).
   100  const (
   101  	AT_EACCESS = 0x200
   102  )
   103  
   104  // Constants for all file-related ...at(2) syscalls.
   105  const (
   106  	AT_FDCWD = -100
   107  )
   108  
   109  // Special values for the ns field in utimensat(2).
   110  const (
   111  	UTIME_NOW  = ((1 << 30) - 1)
   112  	UTIME_OMIT = ((1 << 30) - 2)
   113  )
   114  
   115  // MaxSymlinkTraversals is the maximum number of links that will be followed by
   116  // the kernel to resolve a symlink.
   117  const MaxSymlinkTraversals = 40
   118  
   119  // Constants for flock(2).
   120  const (
   121  	LOCK_SH = 1 // shared lock
   122  	LOCK_EX = 2 // exclusive lock
   123  	LOCK_NB = 4 // or'd with one of the above to prevent blocking
   124  	LOCK_UN = 8 // remove lock
   125  )
   126  
   127  // Values for mode_t.
   128  const (
   129  	S_IFMT   = 0170000
   130  	S_IFSOCK = 0140000
   131  	S_IFLNK  = 0120000
   132  	S_IFREG  = 0100000
   133  	S_IFBLK  = 060000
   134  	S_IFDIR  = 040000
   135  	S_IFCHR  = 020000
   136  	S_IFIFO  = 010000
   137  
   138  	FileTypeMask        = S_IFMT
   139  	ModeSocket          = S_IFSOCK
   140  	ModeSymlink         = S_IFLNK
   141  	ModeRegular         = S_IFREG
   142  	ModeBlockDevice     = S_IFBLK
   143  	ModeDirectory       = S_IFDIR
   144  	ModeCharacterDevice = S_IFCHR
   145  	ModeNamedPipe       = S_IFIFO
   146  
   147  	S_ISUID = 04000
   148  	S_ISGID = 02000
   149  	S_ISVTX = 01000
   150  
   151  	ModeSetUID = S_ISUID
   152  	ModeSetGID = S_ISGID
   153  	ModeSticky = S_ISVTX
   154  
   155  	ModeUserAll     = 0700
   156  	ModeUserRead    = 0400
   157  	ModeUserWrite   = 0200
   158  	ModeUserExec    = 0100
   159  	ModeGroupAll    = 0070
   160  	ModeGroupRead   = 0040
   161  	ModeGroupWrite  = 0020
   162  	ModeGroupExec   = 0010
   163  	ModeOtherAll    = 0007
   164  	ModeOtherRead   = 0004
   165  	ModeOtherWrite  = 0002
   166  	ModeOtherExec   = 0001
   167  	PermissionsMask = 0777
   168  )
   169  
   170  // Values for linux_dirent64.d_type.
   171  const (
   172  	DT_UNKNOWN = 0
   173  	DT_FIFO    = 1
   174  	DT_CHR     = 2
   175  	DT_DIR     = 4
   176  	DT_BLK     = 6
   177  	DT_REG     = 8
   178  	DT_LNK     = 10
   179  	DT_SOCK    = 12
   180  	DT_WHT     = 14
   181  )
   182  
   183  // DirentType are the friendly strings for linux_dirent64.d_type.
   184  var DirentType = abi.ValueSet{
   185  	DT_UNKNOWN: "DT_UNKNOWN",
   186  	DT_FIFO:    "DT_FIFO",
   187  	DT_CHR:     "DT_CHR",
   188  	DT_DIR:     "DT_DIR",
   189  	DT_BLK:     "DT_BLK",
   190  	DT_REG:     "DT_REG",
   191  	DT_LNK:     "DT_LNK",
   192  	DT_SOCK:    "DT_SOCK",
   193  	DT_WHT:     "DT_WHT",
   194  }
   195  
   196  // Values for fs on-disk file types.
   197  const (
   198  	FT_UNKNOWN  = 0
   199  	FT_REG_FILE = 1
   200  	FT_DIR      = 2
   201  	FT_CHRDEV   = 3
   202  	FT_BLKDEV   = 4
   203  	FT_FIFO     = 5
   204  	FT_SOCK     = 6
   205  	FT_SYMLINK  = 7
   206  	FT_MAX      = 8
   207  )
   208  
   209  // Conversion from fs on-disk file type to dirent type.
   210  var direntTypeByFileType = [FT_MAX]uint8{
   211  	FT_UNKNOWN:  DT_UNKNOWN,
   212  	FT_REG_FILE: DT_REG,
   213  	FT_DIR:      DT_DIR,
   214  	FT_CHRDEV:   DT_CHR,
   215  	FT_BLKDEV:   DT_BLK,
   216  	FT_FIFO:     DT_FIFO,
   217  	FT_SOCK:     DT_SOCK,
   218  	FT_SYMLINK:  DT_LNK,
   219  }
   220  
   221  // FileTypeToDirentType converts the on-disk file type (FT_*) to the directory
   222  // entry type (DT_*).
   223  func FileTypeToDirentType(filetype uint8) uint8 {
   224  	if filetype >= FT_MAX {
   225  		return DT_UNKNOWN
   226  	}
   227  	return direntTypeByFileType[filetype]
   228  }
   229  
   230  // Values for preadv2/pwritev2.
   231  const (
   232  	// NOTE(b/120162627): gVisor does not implement the RWF_HIPRI feature, but
   233  	// the flag is accepted as a valid flag argument for preadv2/pwritev2 and
   234  	// silently ignored.
   235  	RWF_HIPRI = 0x00000001
   236  	RWF_DSYNC = 0x00000002
   237  	RWF_SYNC  = 0x00000004
   238  	RWF_VALID = RWF_HIPRI | RWF_DSYNC | RWF_SYNC
   239  )
   240  
   241  // SizeOfStat is the size of a Stat struct.
   242  var SizeOfStat = (*Stat)(nil).SizeBytes()
   243  
   244  // Flags for statx.
   245  const (
   246  	AT_NO_AUTOMOUNT       = 0x800
   247  	AT_STATX_SYNC_TYPE    = 0x6000
   248  	AT_STATX_SYNC_AS_STAT = 0x0000
   249  	AT_STATX_FORCE_SYNC   = 0x2000
   250  	AT_STATX_DONT_SYNC    = 0x4000
   251  )
   252  
   253  // Mask values for statx.
   254  const (
   255  	STATX_TYPE        = 0x00000001
   256  	STATX_MODE        = 0x00000002
   257  	STATX_NLINK       = 0x00000004
   258  	STATX_UID         = 0x00000008
   259  	STATX_GID         = 0x00000010
   260  	STATX_ATIME       = 0x00000020
   261  	STATX_MTIME       = 0x00000040
   262  	STATX_CTIME       = 0x00000080
   263  	STATX_INO         = 0x00000100
   264  	STATX_SIZE        = 0x00000200
   265  	STATX_BLOCKS      = 0x00000400
   266  	STATX_BASIC_STATS = 0x000007ff
   267  	STATX_BTIME       = 0x00000800
   268  	STATX_ALL         = 0x00000fff
   269  	STATX__RESERVED   = 0x80000000
   270  )
   271  
   272  // Bitmasks for Statx.Attributes and Statx.AttributesMask, from
   273  // include/uapi/linux/stat.h.
   274  const (
   275  	STATX_ATTR_COMPRESSED = 0x00000004
   276  	STATX_ATTR_IMMUTABLE  = 0x00000010
   277  	STATX_ATTR_APPEND     = 0x00000020
   278  	STATX_ATTR_NODUMP     = 0x00000040
   279  	STATX_ATTR_ENCRYPTED  = 0x00000800
   280  	STATX_ATTR_AUTOMOUNT  = 0x00001000
   281  )
   282  
   283  // Statx represents struct statx.
   284  //
   285  // +marshal boundCheck slice:StatxSlice
   286  type Statx struct {
   287  	Mask           uint32
   288  	Blksize        uint32
   289  	Attributes     uint64
   290  	Nlink          uint32
   291  	UID            uint32
   292  	GID            uint32
   293  	Mode           uint16
   294  	_              uint16
   295  	Ino            uint64
   296  	Size           uint64
   297  	Blocks         uint64
   298  	AttributesMask uint64
   299  	Atime          StatxTimestamp
   300  	Btime          StatxTimestamp
   301  	Ctime          StatxTimestamp
   302  	Mtime          StatxTimestamp
   303  	RdevMajor      uint32
   304  	RdevMinor      uint32
   305  	DevMajor       uint32
   306  	DevMinor       uint32
   307  }
   308  
   309  // String implements fmt.Stringer.String.
   310  func (s *Statx) String() string {
   311  	return fmt.Sprintf("Statx{Mask: %#x, Mode: %s, UID: %d, GID: %d, Ino: %d, DevMajor: %d, DevMinor: %d, Size: %d, Blocks: %d, Blksize: %d, Nlink: %d, Atime: %s, Btime: %s, Ctime: %s, Mtime: %s, Attributes: %d, AttributesMask: %d, RdevMajor: %d, RdevMinor: %d}",
   312  		s.Mask, FileMode(s.Mode), s.UID, s.GID, s.Ino, s.DevMajor, s.DevMinor, s.Size, s.Blocks, s.Blksize, s.Nlink, s.Atime.ToTime(), s.Btime.ToTime(), s.Ctime.ToTime(), s.Mtime.ToTime(), s.Attributes, s.AttributesMask, s.RdevMajor, s.RdevMinor)
   313  }
   314  
   315  // SizeOfStatx is the size of a Statx struct.
   316  var SizeOfStatx = (*Statx)(nil).SizeBytes()
   317  
   318  // FileMode represents a mode_t.
   319  //
   320  // +marshal
   321  type FileMode uint16
   322  
   323  // Permissions returns just the permission bits.
   324  func (m FileMode) Permissions() FileMode {
   325  	return m & PermissionsMask
   326  }
   327  
   328  // FileType returns just the file type bits.
   329  func (m FileMode) FileType() FileMode {
   330  	return m & FileTypeMask
   331  }
   332  
   333  // ExtraBits returns everything but the file type and permission bits.
   334  func (m FileMode) ExtraBits() FileMode {
   335  	return m &^ (PermissionsMask | FileTypeMask)
   336  }
   337  
   338  // IsDir returns true if file type represents a directory.
   339  func (m FileMode) IsDir() bool {
   340  	return m.FileType() == S_IFDIR
   341  }
   342  
   343  // String returns a string representation of m.
   344  func (m FileMode) String() string {
   345  	var s []string
   346  	if ft := m.FileType(); ft != 0 {
   347  		s = append(s, fileType.Parse(uint64(ft)))
   348  	}
   349  	if eb := m.ExtraBits(); eb != 0 {
   350  		s = append(s, modeExtraBits.Parse(uint64(eb)))
   351  	}
   352  	s = append(s, fmt.Sprintf("0o%o", m.Permissions()))
   353  	return strings.Join(s, "|")
   354  }
   355  
   356  // DirentType maps file types to dirent types appropriate for (struct
   357  // dirent)::d_type.
   358  func (m FileMode) DirentType() uint8 {
   359  	switch m.FileType() {
   360  	case ModeSocket:
   361  		return DT_SOCK
   362  	case ModeSymlink:
   363  		return DT_LNK
   364  	case ModeRegular:
   365  		return DT_REG
   366  	case ModeBlockDevice:
   367  		return DT_BLK
   368  	case ModeDirectory:
   369  		return DT_DIR
   370  	case ModeCharacterDevice:
   371  		return DT_CHR
   372  	case ModeNamedPipe:
   373  		return DT_FIFO
   374  	default:
   375  		return DT_UNKNOWN
   376  	}
   377  }
   378  
   379  var modeExtraBits = abi.FlagSet{
   380  	{
   381  		Flag: ModeSetUID,
   382  		Name: "S_ISUID",
   383  	},
   384  	{
   385  		Flag: ModeSetGID,
   386  		Name: "S_ISGID",
   387  	},
   388  	{
   389  		Flag: ModeSticky,
   390  		Name: "S_ISVTX",
   391  	},
   392  }
   393  
   394  var fileType = abi.ValueSet{
   395  	ModeSocket:          "S_IFSOCK",
   396  	ModeSymlink:         "S_IFLINK",
   397  	ModeRegular:         "S_IFREG",
   398  	ModeBlockDevice:     "S_IFBLK",
   399  	ModeDirectory:       "S_IFDIR",
   400  	ModeCharacterDevice: "S_IFCHR",
   401  	ModeNamedPipe:       "S_IFIFO",
   402  }
   403  
   404  // Constants for memfd_create(2). Source: include/uapi/linux/memfd.h
   405  const (
   406  	MFD_CLOEXEC       = 0x0001
   407  	MFD_ALLOW_SEALING = 0x0002
   408  )
   409  
   410  // Constants related to file seals. Source: include/uapi/{asm-generic,linux}/fcntl.h
   411  const (
   412  	F_LINUX_SPECIFIC_BASE = 1024
   413  	F_ADD_SEALS           = F_LINUX_SPECIFIC_BASE + 9
   414  	F_GET_SEALS           = F_LINUX_SPECIFIC_BASE + 10
   415  
   416  	F_SEAL_SEAL   = 0x0001 // Prevent further seals from being set.
   417  	F_SEAL_SHRINK = 0x0002 // Prevent file from shrinking.
   418  	F_SEAL_GROW   = 0x0004 // Prevent file from growing.
   419  	F_SEAL_WRITE  = 0x0008 // Prevent writes.
   420  )
   421  
   422  // Constants related to fallocate(2). Source: include/uapi/linux/falloc.h
   423  const (
   424  	FALLOC_FL_KEEP_SIZE      = 0x01
   425  	FALLOC_FL_PUNCH_HOLE     = 0x02
   426  	FALLOC_FL_NO_HIDE_STALE  = 0x04
   427  	FALLOC_FL_COLLAPSE_RANGE = 0x08
   428  	FALLOC_FL_ZERO_RANGE     = 0x10
   429  	FALLOC_FL_INSERT_RANGE   = 0x20
   430  	FALLOC_FL_UNSHARE_RANGE  = 0x40
   431  )
   432  
   433  // Constants related to close_range(2). Source: /include/uapi/linux/close_range.h
   434  const (
   435  	CLOSE_RANGE_UNSHARE = uint32(1 << 1)
   436  	CLOSE_RANGE_CLOEXEC = uint32(1 << 2)
   437  )