github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/fsutil/targzfs/file.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package targzfs
    19  
    20  import (
    21  	"archive/tar"
    22  	"io"
    23  	"io/fs"
    24  	"time"
    25  )
    26  
    27  type tarEntry struct {
    28  	h *tar.Header
    29  	b []byte
    30  
    31  	// If the file is a directory, the following property will contain
    32  	// owned files.
    33  	entries []fs.DirEntry
    34  }
    35  
    36  // Implementation of fs.DirEntry for tarEntry.
    37  var _ fs.DirEntry = (*tarEntry)(nil)
    38  
    39  // Name returns the basename of the file.
    40  func (f *tarEntry) Name() string {
    41  	return f.h.FileInfo().Name()
    42  }
    43  
    44  // Type returns file mode.
    45  func (f *tarEntry) Type() fs.FileMode {
    46  	return f.h.FileInfo().Mode() & fs.ModeType
    47  }
    48  
    49  // IsDir returns whether this file is a directory (always false).
    50  func (f *tarEntry) IsDir() bool {
    51  	return f.h.FileInfo().IsDir()
    52  }
    53  
    54  // Info returns file info.
    55  func (f *tarEntry) Info() (fs.FileInfo, error) {
    56  	return f.h.FileInfo(), nil
    57  }
    58  
    59  type tarFile struct {
    60  	tarEntry
    61  	r          io.ReadSeeker
    62  	readDirPos int
    63  }
    64  
    65  // Implementation of fs.File for tarFile.
    66  var _ fs.File = (*tarFile)(nil)
    67  
    68  // Stat returns a fs.FileInfo for the given file.
    69  func (f *tarFile) Stat() (fs.FileInfo, error) {
    70  	return f.h.FileInfo(), nil
    71  }
    72  
    73  // Read reads the next len(p) bytes from the buffer or until the buffer is drained.
    74  func (f *tarFile) Read(buf []byte) (int, error) {
    75  	if f.IsDir() {
    76  		return 0, &fs.PathError{Op: "read", Path: f.Name(), Err: fs.ErrInvalid}
    77  	}
    78  
    79  	return f.r.Read(buf)
    80  }
    81  
    82  // Close is a no-op.
    83  func (f *tarFile) Close() error {
    84  	return nil
    85  }
    86  
    87  // Implementation of io.Seeker for tarFile.
    88  var _ io.Seeker = (*tarFile)(nil)
    89  
    90  func (f *tarFile) Seek(offset int64, whence int) (int64, error) {
    91  	if f.IsDir() {
    92  		return 0, &fs.PathError{Op: "seek", Path: f.Name(), Err: fs.ErrInvalid}
    93  	}
    94  
    95  	return f.r.Seek(offset, whence)
    96  }
    97  
    98  // Implementation of fs.ReadDirFile for tarFile.
    99  var _ fs.ReadDirFile = (*tarFile)(nil)
   100  
   101  func (f *tarFile) ReadDir(n int) ([]fs.DirEntry, error) {
   102  	if !f.IsDir() {
   103  		return nil, &fs.PathError{Op: "readdir", Path: f.Name(), Err: fs.ErrInvalid}
   104  	}
   105  
   106  	if f.readDirPos >= len(f.entries) {
   107  		if n <= 0 {
   108  			return nil, nil
   109  		}
   110  		return nil, io.EOF
   111  	}
   112  
   113  	var entries []fs.DirEntry
   114  
   115  	if n > 0 && f.readDirPos+n <= len(f.entries) {
   116  		entries = f.entries[f.readDirPos : f.readDirPos+n]
   117  		f.readDirPos += n
   118  	} else {
   119  		entries = f.entries[f.readDirPos:]
   120  		f.readDirPos += len(entries)
   121  	}
   122  
   123  	return entries, nil
   124  }
   125  
   126  // Implmentation of fs.FileInfo for tarFile.
   127  var _ fs.FileInfo = (*tarFile)(nil)
   128  
   129  // Size returns the length in bytes for this file.
   130  func (f *tarFile) Size() int64 {
   131  	return f.h.Size
   132  }
   133  
   134  // Mode returns the mode for this file.
   135  func (f *tarFile) Mode() fs.FileMode {
   136  	return f.h.FileInfo().Mode()
   137  }
   138  
   139  // Mode returns the mtime for this file (always the Unix epoch).
   140  func (f *tarFile) ModTime() time.Time {
   141  	return f.h.ModTime
   142  }
   143  
   144  // Sys returns nil.
   145  func (f *tarFile) Sys() interface{} {
   146  	return nil
   147  }
   148  
   149  // -----------------------------------------------------------------------------
   150  
   151  type rootFile struct{}
   152  
   153  var _ fs.File = (*rootFile)(nil)
   154  
   155  func (rf *rootFile) Stat() (fs.FileInfo, error) {
   156  	return rf, nil
   157  }
   158  
   159  func (*rootFile) Read([]byte) (int, error) {
   160  	return 0, &fs.PathError{Op: "read", Path: ".", Err: fs.ErrInvalid}
   161  }
   162  
   163  func (*rootFile) Close() error {
   164  	return nil
   165  }
   166  
   167  var _ fs.FileInfo = (*rootFile)(nil)
   168  
   169  func (rf *rootFile) Name() string {
   170  	return "."
   171  }
   172  
   173  func (rf *rootFile) Size() int64 {
   174  	return 0
   175  }
   176  
   177  func (rf *rootFile) Mode() fs.FileMode {
   178  	return fs.ModeDir | 0o755
   179  }
   180  
   181  func (rf *rootFile) ModTime() time.Time {
   182  	return time.Time{}
   183  }
   184  
   185  func (rf *rootFile) IsDir() bool {
   186  	return true
   187  }
   188  
   189  func (rf *rootFile) Sys() interface{} {
   190  	return nil
   191  }