github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/ext/disklayout/dirent.go (about)

     1  // Copyright 2019 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 disklayout
    16  
    17  import (
    18  	"github.com/SagerNet/gvisor/pkg/marshal"
    19  	"github.com/SagerNet/gvisor/pkg/sentry/fs"
    20  )
    21  
    22  const (
    23  	// MaxFileName is the maximum length of an ext fs file's name.
    24  	MaxFileName = 255
    25  
    26  	// DirentSize is the size of ext dirent structures.
    27  	DirentSize = 263
    28  )
    29  
    30  var (
    31  	// inodeTypeByFileType maps ext4 file types to vfs inode types.
    32  	//
    33  	// See https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html#ftype.
    34  	inodeTypeByFileType = map[uint8]fs.InodeType{
    35  		0: fs.Anonymous,
    36  		1: fs.RegularFile,
    37  		2: fs.Directory,
    38  		3: fs.CharacterDevice,
    39  		4: fs.BlockDevice,
    40  		5: fs.Pipe,
    41  		6: fs.Socket,
    42  		7: fs.Symlink,
    43  	}
    44  )
    45  
    46  // The Dirent interface should be implemented by structs representing ext
    47  // directory entries. These are for the linear classical directories which
    48  // just store a list of dirent structs. A directory is a series of data blocks
    49  // where is each data block contains a linear array of dirents. The last entry
    50  // of the block has a record size that takes it to the end of the block. The
    51  // end of the directory is when you read dirInode.Size() bytes from the blocks.
    52  //
    53  // See https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html#linear-classic-directories.
    54  type Dirent interface {
    55  	marshal.Marshallable
    56  
    57  	// Inode returns the absolute inode number of the underlying inode.
    58  	// Inode number 0 signifies an unused dirent.
    59  	Inode() uint32
    60  
    61  	// RecordSize returns the record length of this dirent on disk. The next
    62  	// dirent in the dirent list should be read after these many bytes from
    63  	// the current dirent. Must be a multiple of 4.
    64  	RecordSize() uint16
    65  
    66  	// FileName returns the name of the file. Can be at most 255 is length.
    67  	FileName() string
    68  
    69  	// FileType returns the inode type of the underlying inode. This is a
    70  	// performance hack so that we do not have to read the underlying inode struct
    71  	// to know the type of inode. This will only work when the SbDirentFileType
    72  	// feature is set. If not, the second returned value will be false indicating
    73  	// that user code has to use the inode mode to extract the file type.
    74  	FileType() (fs.InodeType, bool)
    75  }