github.com/avfs/avfs@v0.33.1-0.20240303173310-c6ba67c33eb7/vfs/memfs/memfs_file.go (about)

     1  //
     2  //  Copyright 2020 The AVFS authors
     3  //
     4  //  Licensed under the Apache License, Version 2.0 (the "License");
     5  //  you may not use this file except in compliance with the License.
     6  //  You may obtain a copy of the License at
     7  //
     8  //  	http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  //  Unless required by applicable law or agreed to in writing, software
    11  //  distributed under the License is distributed on an "AS IS" BASIS,
    12  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  //  See the License for the specific language governing permissions and
    14  //  limitations under the License.
    15  //
    16  
    17  package memfs
    18  
    19  import (
    20  	"io"
    21  	"io/fs"
    22  	"time"
    23  
    24  	"github.com/avfs/avfs"
    25  )
    26  
    27  // Chdir changes the current working directory to the file,
    28  // which must be a directory.
    29  // If there is an error, it will be of type *PathError.
    30  func (f *MemFile) Chdir() error {
    31  	const op = "chdir"
    32  
    33  	if f == nil {
    34  		return fs.ErrInvalid
    35  	}
    36  
    37  	f.mu.Lock()
    38  	defer f.mu.Unlock()
    39  
    40  	if f.name == "" {
    41  		return fs.ErrInvalid
    42  	}
    43  
    44  	if f.nd == nil {
    45  		return &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
    46  	}
    47  
    48  	_, ok := f.nd.(*dirNode)
    49  	if !ok {
    50  		err := error(avfs.ErrNotADirectory)
    51  		if f.vfs.OSType() == avfs.OsWindows {
    52  			err = avfs.ErrWinDirNameInvalid
    53  		}
    54  
    55  		return &fs.PathError{Op: op, Path: f.name, Err: err}
    56  	}
    57  
    58  	_ = f.vfs.SetCurDir(f.name)
    59  
    60  	return nil
    61  }
    62  
    63  // Chmod changes the mode of the file to mode.
    64  // If there is an error, it will be of type *PathError.
    65  func (f *MemFile) Chmod(mode fs.FileMode) error {
    66  	const op = "chmod"
    67  
    68  	if f == nil {
    69  		return fs.ErrInvalid
    70  	}
    71  
    72  	f.mu.Lock()
    73  	defer f.mu.Unlock()
    74  
    75  	if f.name == "" {
    76  		return fs.ErrInvalid
    77  	}
    78  
    79  	if f.nd == nil {
    80  		return &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
    81  	}
    82  
    83  	nd := f.nd
    84  
    85  	nd.Lock()
    86  	defer nd.Unlock()
    87  
    88  	if !nd.setMode(mode, f.vfs.User()) {
    89  		return &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.PermDenied}
    90  	}
    91  
    92  	return nil
    93  }
    94  
    95  // Chown changes the numeric uid and gid of the named file.
    96  // If there is an error, it will be of type *PathError.
    97  //
    98  // On Windows, it always returns the syscall.EWINDOWS error, wrapped
    99  // in *PathError.
   100  func (f *MemFile) Chown(uid, gid int) error {
   101  	const op = "chown"
   102  
   103  	if f == nil {
   104  		return fs.ErrInvalid
   105  	}
   106  
   107  	f.mu.Lock()
   108  	defer f.mu.Unlock()
   109  
   110  	if f.name == "" {
   111  		return fs.ErrInvalid
   112  	}
   113  
   114  	if f.nd == nil {
   115  		return &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   116  	}
   117  
   118  	if f.vfs.OSType() == avfs.OsWindows {
   119  		return &fs.PathError{Op: op, Path: f.name, Err: avfs.ErrWinNotSupported}
   120  	}
   121  
   122  	nd := f.nd
   123  
   124  	nd.Lock()
   125  	defer nd.Unlock()
   126  
   127  	if !nd.checkPermission(avfs.OpenWrite, f.vfs.User()) {
   128  		return &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.OpNotPermitted}
   129  	}
   130  
   131  	nd.setOwner(uid, gid)
   132  
   133  	return nil
   134  }
   135  
   136  // Close closes the File, rendering it unusable for I/O.
   137  // On files that support SetDeadline, any pending I/O operations will
   138  // be canceled and return immediately with an error.
   139  func (f *MemFile) Close() error {
   140  	const op = "close"
   141  
   142  	if f == nil {
   143  		return fs.ErrInvalid
   144  	}
   145  
   146  	f.mu.Lock()
   147  	defer f.mu.Unlock()
   148  
   149  	if f.nd == nil {
   150  		if f.name == "" {
   151  			return fs.ErrInvalid
   152  		}
   153  
   154  		return &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   155  	}
   156  
   157  	f.dirEntries = nil
   158  	f.dirNames = nil
   159  	f.nd = nil
   160  
   161  	return nil
   162  }
   163  
   164  // Fd returns the integer Unix file descriptor referencing the open file.
   165  // The file descriptor is valid only until f.Close is called or f is garbage collected.
   166  // On Unix systems this will cause the SetDeadline methods to stop working.
   167  func (f *MemFile) Fd() uintptr {
   168  	return ^(uintptr(0))
   169  }
   170  
   171  // Name returns the link of the file as presented to Open.
   172  func (f *MemFile) Name() string {
   173  	if f == nil {
   174  		panic("")
   175  	}
   176  
   177  	f.mu.RLock()
   178  	name := f.name
   179  	f.mu.RUnlock()
   180  
   181  	return name
   182  }
   183  
   184  // Read reads up to len(b) bytes from the MemFile.
   185  // It returns the number of bytes read and any error encountered.
   186  // At end of file, Read returns 0, io.EOF.
   187  func (f *MemFile) Read(b []byte) (n int, err error) {
   188  	const op = "read"
   189  
   190  	if f == nil {
   191  		return 0, fs.ErrInvalid
   192  	}
   193  
   194  	f.mu.Lock()
   195  	defer f.mu.Unlock()
   196  
   197  	if f.name == "" {
   198  		return 0, fs.ErrInvalid
   199  	}
   200  
   201  	if f.nd == nil {
   202  		return 0, &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   203  	}
   204  
   205  	nd, ok := f.nd.(*fileNode)
   206  	if !ok {
   207  		err = avfs.ErrIsADirectory
   208  		if f.vfs.OSType() == avfs.OsWindows {
   209  			err = avfs.ErrWinIncorrectFunc
   210  		}
   211  
   212  		return 0, &fs.PathError{Op: op, Path: f.name, Err: err}
   213  	}
   214  
   215  	if f.openMode&avfs.OpenRead == 0 {
   216  		return 0, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.BadFileDesc}
   217  	}
   218  
   219  	nd.mu.RLock()
   220  	n = copy(b, nd.data[f.at:])
   221  	nd.mu.RUnlock()
   222  
   223  	f.at += int64(n)
   224  
   225  	if n == 0 {
   226  		return 0, io.EOF
   227  	}
   228  
   229  	return n, nil
   230  }
   231  
   232  // ReadAt reads len(b) bytes from the File starting at byte offset off.
   233  // It returns the number of bytes read and the error, if any.
   234  // ReadAt always returns a non-nil error when n < len(b).
   235  // At end of file, that error is io.EOF.
   236  func (f *MemFile) ReadAt(b []byte, off int64) (n int, err error) {
   237  	const op = "read"
   238  
   239  	if f == nil {
   240  		return 0, fs.ErrInvalid
   241  	}
   242  
   243  	f.mu.RLock()
   244  	defer f.mu.RUnlock()
   245  
   246  	if f.name == "" {
   247  		return 0, fs.ErrInvalid
   248  	}
   249  
   250  	if f.nd == nil {
   251  		return 0, &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   252  	}
   253  
   254  	nd, ok := f.nd.(*fileNode)
   255  	if !ok {
   256  		err = avfs.ErrIsADirectory
   257  		if f.vfs.OSType() == avfs.OsWindows {
   258  			err = avfs.ErrWinIncorrectFunc
   259  		}
   260  
   261  		return 0, &fs.PathError{Op: op, Path: f.name, Err: err}
   262  	}
   263  
   264  	if off < 0 {
   265  		return 0, &fs.PathError{Op: "readat", Path: f.name, Err: avfs.ErrNegativeOffset}
   266  	}
   267  
   268  	if f.openMode&avfs.OpenRead == 0 {
   269  		return 0, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.BadFileDesc}
   270  	}
   271  
   272  	nd.mu.RLock()
   273  	defer nd.mu.RUnlock()
   274  
   275  	if int(off) > len(nd.data) {
   276  		return 0, io.EOF
   277  	}
   278  
   279  	n = copy(b, nd.data[off:])
   280  	if n < len(b) {
   281  		return n, io.EOF
   282  	}
   283  
   284  	return n, nil
   285  }
   286  
   287  // ReadDir reads the contents of the directory associated with the file f
   288  // and returns a slice of DirEntry values in directory order.
   289  // Subsequent calls on the same file will yield later DirEntry records in the directory.
   290  //
   291  // If n > 0, ReadDir returns at most n DirEntry records.
   292  // In this case, if ReadDir returns an empty slice, it will return an error explaining why.
   293  // At the end of a directory, the error is io.EOF.
   294  //
   295  // If n <= 0, ReadDir returns all the DirEntry records remaining in the directory.
   296  // When it succeeds, it returns a nil error (not io.EOF).
   297  func (f *MemFile) ReadDir(n int) (entries []fs.DirEntry, err error) {
   298  	if f == nil {
   299  		return nil, fs.ErrInvalid
   300  	}
   301  
   302  	f.mu.Lock()
   303  	defer f.mu.Unlock()
   304  
   305  	if f.name == "" {
   306  		return nil, fs.ErrInvalid
   307  	}
   308  
   309  	op := "readdirent"
   310  	if f.vfs.OSType() == avfs.OsWindows {
   311  		op = "readdir"
   312  	}
   313  
   314  	if f.nd == nil {
   315  		err = avfs.ErrFileClosing
   316  		if f.vfs.OSType() == avfs.OsWindows {
   317  			err = avfs.ErrWinInvalidHandle
   318  		}
   319  
   320  		return nil, &fs.PathError{Op: op, Path: f.name, Err: err}
   321  	}
   322  
   323  	nd, ok := f.nd.(*dirNode)
   324  	if !ok {
   325  		return nil, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.NotADirectory}
   326  	}
   327  
   328  	if n <= 0 || f.dirEntries == nil {
   329  		nd.mu.RLock()
   330  		entries = nd.dirEntries()
   331  		nd.mu.RUnlock()
   332  
   333  		f.dirIndex = 0
   334  
   335  		if n <= 0 {
   336  			f.dirEntries = nil
   337  
   338  			return entries, nil
   339  		}
   340  
   341  		f.dirEntries = entries
   342  	}
   343  
   344  	start := f.dirIndex
   345  	if start >= len(f.dirEntries) {
   346  		f.dirIndex = 0
   347  		f.dirEntries = nil
   348  
   349  		return nil, io.EOF
   350  	}
   351  
   352  	end := start + n
   353  	if end > len(f.dirEntries) {
   354  		end = len(f.dirEntries)
   355  	}
   356  
   357  	f.dirIndex = end
   358  
   359  	return f.dirEntries[start:end], nil
   360  }
   361  
   362  // Readdirnames reads and returns a slice of names from the directory f.
   363  //
   364  // If n > 0, Readdirnames returns at most n names. In this case, if
   365  // Readdirnames returns an empty slice, it will return a non-nil error
   366  // explaining why. At the end of a directory, the error is io.EOF.
   367  //
   368  // If n <= 0, Readdirnames returns all the names from the directory in
   369  // a single slice. In this case, if Readdirnames succeeds (reads all
   370  // the way to the end of the directory), it returns the slice and a
   371  // nil error. If it encounters an error before the end of the
   372  // directory, Readdirnames returns the names read until that point and
   373  // a non-nil error.
   374  func (f *MemFile) Readdirnames(n int) (names []string, err error) {
   375  	if f == nil {
   376  		return nil, fs.ErrInvalid
   377  	}
   378  
   379  	f.mu.Lock()
   380  	defer f.mu.Unlock()
   381  
   382  	if f.name == "" {
   383  		return nil, fs.ErrInvalid
   384  	}
   385  
   386  	op := "readdirent"
   387  	if f.vfs.OSType() == avfs.OsWindows {
   388  		op = "readdir"
   389  	}
   390  
   391  	if f.nd == nil {
   392  		err = avfs.ErrFileClosing
   393  		if f.vfs.OSType() == avfs.OsWindows {
   394  			err = avfs.ErrWinInvalidHandle
   395  		}
   396  
   397  		return nil, &fs.PathError{Op: op, Path: f.name, Err: err}
   398  	}
   399  
   400  	nd, ok := f.nd.(*dirNode)
   401  	if !ok {
   402  		return nil, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.NotADirectory}
   403  	}
   404  
   405  	if n <= 0 || f.dirNames == nil {
   406  		nd.mu.RLock()
   407  		names = nd.dirNames()
   408  		nd.mu.RUnlock()
   409  
   410  		f.dirIndex = 0
   411  
   412  		if n <= 0 {
   413  			f.dirNames = nil
   414  
   415  			return names, nil
   416  		}
   417  
   418  		f.dirNames = names
   419  	}
   420  
   421  	start := f.dirIndex
   422  	if start >= len(f.dirNames) {
   423  		f.dirIndex = 0
   424  		f.dirNames = nil
   425  
   426  		return nil, io.EOF
   427  	}
   428  
   429  	end := start + n
   430  	if end > len(f.dirNames) {
   431  		end = len(f.dirNames)
   432  	}
   433  
   434  	f.dirIndex = end
   435  
   436  	return f.dirNames[start:end], nil
   437  }
   438  
   439  // Seek sets the offset for the next Read or Write on file to offset, interpreted
   440  // according to whence: 0 means relative to the origin of the file, 1 means
   441  // relative to the current offset, and 2 means relative to the end.
   442  // It returns the new offset and an error, if any.
   443  // The behavior of Seek on a file opened with O_APPEND is not specified.
   444  func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
   445  	const op = "seek"
   446  
   447  	if f == nil {
   448  		return 0, fs.ErrInvalid
   449  	}
   450  
   451  	f.mu.Lock()
   452  	defer f.mu.Unlock()
   453  
   454  	if f.name == "" {
   455  		return 0, fs.ErrInvalid
   456  	}
   457  
   458  	if f.nd == nil {
   459  		return 0, &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   460  	}
   461  
   462  	nd, ok := f.nd.(*fileNode)
   463  	if !ok {
   464  		return 0, nil
   465  	}
   466  
   467  	nd.mu.RLock()
   468  	size := int64(len(nd.data))
   469  	nd.mu.RUnlock()
   470  
   471  	switch whence {
   472  	case io.SeekStart:
   473  		if offset < 0 {
   474  			return 0, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.InvalidArgument}
   475  		}
   476  
   477  		f.at = offset
   478  	case io.SeekCurrent:
   479  		if f.at+offset < 0 {
   480  			return 0, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.InvalidArgument}
   481  		}
   482  
   483  		f.at += offset
   484  	case io.SeekEnd:
   485  		if size+offset < 0 {
   486  			return 0, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.InvalidArgument}
   487  		}
   488  
   489  		f.at = size + offset
   490  	default:
   491  		if f.vfs.OSType() != avfs.OsWindows {
   492  			return 0, &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.InvalidArgument}
   493  		}
   494  
   495  		return 0, nil
   496  	}
   497  
   498  	return f.at, nil
   499  }
   500  
   501  // Stat returns the FileInfo structure describing file.
   502  // If there is an error, it will be of type *PathError.
   503  func (f *MemFile) Stat() (info fs.FileInfo, err error) {
   504  	if f == nil {
   505  		return nil, fs.ErrInvalid
   506  	}
   507  
   508  	f.mu.RLock()
   509  	defer f.mu.RUnlock()
   510  
   511  	if f.name == "" {
   512  		return nil, fs.ErrInvalid
   513  	}
   514  
   515  	op := "stat"
   516  	if f.vfs.OSType() == avfs.OsWindows {
   517  		op = "GetFileType"
   518  	}
   519  
   520  	if f.nd == nil {
   521  		err = avfs.ErrFileClosing
   522  		if f.vfs.OSType() == avfs.OsWindows {
   523  			err = avfs.ErrWinInvalidHandle
   524  		}
   525  
   526  		return &MemInfo{}, &fs.PathError{Op: op, Path: f.name, Err: err}
   527  	}
   528  
   529  	name := f.vfs.Base(f.name)
   530  	fst := f.nd.fillStatFrom(name)
   531  
   532  	return fst, nil
   533  }
   534  
   535  // Sync commits the current contents of the file to stable storage.
   536  // Typically, this means flushing the file system's in-memory copy
   537  // of recently written data to disk.
   538  func (f *MemFile) Sync() error {
   539  	const op = "sync"
   540  
   541  	if f == nil {
   542  		return fs.ErrInvalid
   543  	}
   544  
   545  	f.mu.RLock()
   546  	defer f.mu.RUnlock()
   547  
   548  	if f.name == "" {
   549  		return fs.ErrInvalid
   550  	}
   551  
   552  	if f.nd == nil {
   553  		return &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   554  	}
   555  
   556  	return nil
   557  }
   558  
   559  // Truncate changes the size of the file.
   560  // It does not change the I/O offset.
   561  // If there is an error, it will be of type *PathError.
   562  func (f *MemFile) Truncate(size int64) error {
   563  	const op = "truncate"
   564  
   565  	if f == nil {
   566  		return fs.ErrInvalid
   567  	}
   568  
   569  	f.mu.RLock()
   570  	defer f.mu.RUnlock()
   571  
   572  	if f.name == "" {
   573  		return fs.ErrInvalid
   574  	}
   575  
   576  	if size < 0 {
   577  		return &fs.PathError{Op: op, Path: f.name, Err: f.vfs.err.InvalidArgument}
   578  	}
   579  
   580  	if f.nd == nil {
   581  		return &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   582  	}
   583  
   584  	nd, ok := f.nd.(*fileNode)
   585  	if !ok {
   586  		err := error(avfs.ErrInvalidArgument)
   587  		if f.vfs.OSType() == avfs.OsWindows {
   588  			err = avfs.ErrWinAccessDenied
   589  		}
   590  
   591  		return &fs.PathError{Op: op, Path: f.name, Err: err}
   592  	}
   593  
   594  	if f.openMode&avfs.OpenWrite == 0 {
   595  		err := error(avfs.ErrInvalidArgument)
   596  		if f.vfs.OSType() == avfs.OsWindows {
   597  			err = avfs.ErrWinAccessDenied
   598  		}
   599  
   600  		return &fs.PathError{Op: op, Path: f.name, Err: err}
   601  	}
   602  
   603  	nd.mu.Lock()
   604  
   605  	nd.truncate(size)
   606  	nd.mtime = time.Now().UnixNano()
   607  
   608  	nd.mu.Unlock()
   609  
   610  	return nil
   611  }
   612  
   613  // Write writes len(b) bytes to the File.
   614  // It returns the number of bytes written and an error, if any.
   615  // Write returns a non-nil error when n != len(b).
   616  func (f *MemFile) Write(b []byte) (n int, err error) {
   617  	const op = "write"
   618  
   619  	if f == nil {
   620  		return 0, fs.ErrInvalid
   621  	}
   622  
   623  	f.mu.Lock()
   624  	defer f.mu.Unlock()
   625  
   626  	if f.name == "" {
   627  		return 0, fs.ErrInvalid
   628  	}
   629  
   630  	if f.nd == nil {
   631  		return 0, &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   632  	}
   633  
   634  	nd, ok := f.nd.(*fileNode)
   635  	if !ok {
   636  		err = avfs.ErrBadFileDesc
   637  		if f.vfs.OSType() == avfs.OsWindows {
   638  			err = avfs.ErrWinAccessDenied
   639  		}
   640  
   641  		return 0, &fs.PathError{Op: op, Path: f.name, Err: err}
   642  	}
   643  
   644  	if f.openMode&avfs.OpenWrite == 0 {
   645  		err = avfs.ErrBadFileDesc
   646  		if f.vfs.OSType() == avfs.OsWindows {
   647  			err = avfs.ErrWinAccessDenied
   648  		}
   649  
   650  		return 0, &fs.PathError{Op: op, Path: f.name, Err: err}
   651  	}
   652  
   653  	nd.mu.Lock()
   654  
   655  	n = copy(nd.data[f.at:], b)
   656  	if n < len(b) {
   657  		nd.data = append(nd.data, b[n:]...)
   658  		n = len(b)
   659  	}
   660  
   661  	nd.mtime = time.Now().UnixNano()
   662  
   663  	nd.mu.Unlock()
   664  
   665  	f.at += int64(n)
   666  
   667  	return n, nil
   668  }
   669  
   670  // WriteAt writes len(b) bytes to the File starting at byte offset off.
   671  // It returns the number of bytes written and an error, if any.
   672  // WriteAt returns a non-nil error when n != len(b).
   673  func (f *MemFile) WriteAt(b []byte, off int64) (n int, err error) {
   674  	const op = "write"
   675  
   676  	if f == nil {
   677  		return 0, fs.ErrInvalid
   678  	}
   679  
   680  	if off < 0 {
   681  		return 0, &fs.PathError{Op: "writeat", Path: f.name, Err: avfs.ErrNegativeOffset}
   682  	}
   683  
   684  	f.mu.RLock()
   685  	defer f.mu.RUnlock()
   686  
   687  	if f.name == "" {
   688  		return 0, fs.ErrInvalid
   689  	}
   690  
   691  	if f.nd == nil {
   692  		return 0, &fs.PathError{Op: op, Path: f.name, Err: fs.ErrClosed}
   693  	}
   694  
   695  	nd, ok := f.nd.(*fileNode)
   696  	if !ok {
   697  		err = avfs.ErrBadFileDesc
   698  		if f.vfs.OSType() == avfs.OsWindows {
   699  			err = avfs.ErrWinAccessDenied
   700  		}
   701  
   702  		return 0, &fs.PathError{Op: op, Path: f.name, Err: err}
   703  	}
   704  
   705  	if f.openMode&avfs.OpenWrite == 0 {
   706  		err = avfs.ErrBadFileDesc
   707  		if f.vfs.OSType() == avfs.OsWindows {
   708  			err = avfs.ErrWinAccessDenied
   709  		}
   710  
   711  		return 0, &fs.PathError{Op: op, Path: f.name, Err: err}
   712  	}
   713  
   714  	nd.mu.Lock()
   715  
   716  	diff := off + int64(len(b)) - nd.size()
   717  	if diff > 0 {
   718  		nd.data = append(nd.data, make([]byte, diff)...)
   719  	}
   720  
   721  	n = copy(nd.data[off:], b)
   722  
   723  	nd.mtime = time.Now().UnixNano()
   724  
   725  	nd.mu.Unlock()
   726  
   727  	return n, nil
   728  }
   729  
   730  // WriteString is like Write, but writes the contents of string s rather than
   731  // a slice of bytes.
   732  func (f *MemFile) WriteString(s string) (n int, err error) {
   733  	return f.Write([]byte(s))
   734  }
   735  
   736  // MemInfo is the implementation of FileInfo returned by Stat and Lstat.
   737  
   738  // Info returns the FileInfo for the file or subdirectory described by the entry.
   739  // The returned FileInfo may be from the time of the original directory read
   740  // or from the time of the call to Info. If the file has been removed or renamed
   741  // since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist).
   742  // If the entry denotes a symbolic link, Info reports the information about the link itself,
   743  // not the link's target.
   744  func (info *MemInfo) Info() (fs.FileInfo, error) {
   745  	return info, nil
   746  }
   747  
   748  // IsDir reports whether the entry describes a directory.
   749  func (info *MemInfo) IsDir() bool {
   750  	return info.mode.IsDir()
   751  }
   752  
   753  // Mode returns the file mode bits.
   754  func (info *MemInfo) Mode() fs.FileMode {
   755  	return info.mode
   756  }
   757  
   758  // ModTime returns the modification time.
   759  func (info *MemInfo) ModTime() time.Time {
   760  	return time.Unix(0, info.mtime)
   761  }
   762  
   763  // Name returns the base name of the file.
   764  func (info *MemInfo) Name() string {
   765  	return info.name
   766  }
   767  
   768  // Size returns the length in bytes for regular files; system-dependent for others.
   769  func (info *MemInfo) Size() int64 {
   770  	return info.size
   771  }
   772  
   773  // Sys returns the underlying data source (can return nil).
   774  func (info *MemInfo) Sys() any {
   775  	return info
   776  }
   777  
   778  // Type returns the type bits for the entry.
   779  // The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method.
   780  func (info *MemInfo) Type() fs.FileMode {
   781  	return info.mode & fs.ModeType
   782  }
   783  
   784  // Gid returns the group id.
   785  func (info *MemInfo) Gid() int {
   786  	return info.gid
   787  }
   788  
   789  // Uid returns the user id.
   790  func (info *MemInfo) Uid() int {
   791  	return info.uid
   792  }
   793  
   794  // Nlink returns the number of hard links.
   795  func (info *MemInfo) Nlink() uint64 {
   796  	return uint64(info.nlink)
   797  }