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 }