Open returns an [io.ReadCloser] that provides access to the [File]'s contents. Multiple files may be read concurrently.
()
| 147 | // Open returns an [io.ReadCloser] that provides access to the [File]'s |
| 148 | // contents. Multiple files may be read concurrently. |
| 149 | func (f *File) Open() (io.ReadCloser, error) { |
| 150 | if f.isEmptyStream || f.isEmptyFile { |
| 151 | // Return empty reader for directory or empty file |
| 152 | return io.NopCloser(bytes.NewReader(nil)), nil |
| 153 | } |
| 154 | |
| 155 | rc, _ := f.zip.pool[f.folder].Get(f.offset) |
| 156 | if rc == nil { |
| 157 | var ( |
| 158 | encrypted bool |
| 159 | err error |
| 160 | ) |
| 161 | |
| 162 | rc, _, encrypted, err = f.zip.folderReader(f.zip.si, f.folder) |
| 163 | if err != nil { |
| 164 | return nil, &ReadError{ |
| 165 | Encrypted: encrypted, |
| 166 | Err: err, |
| 167 | } |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | if _, err := rc.Seek(f.offset, io.SeekStart); err != nil { |
| 172 | e := &ReadError{ |
| 173 | Err: err, |
| 174 | } |
| 175 | |
| 176 | if fr, ok := rc.(*folderReadCloser); ok { |
| 177 | e.Encrypted = fr.hasEncryption |
| 178 | } |
| 179 | |
| 180 | return nil, e |
| 181 | } |
| 182 | |
| 183 | return &fileReader{ |
| 184 | rc: rc, |
| 185 | f: f, |
| 186 | n: int64(f.UncompressedSize), //nolint:gosec |
| 187 | }, nil |
| 188 | } |
| 189 | |
| 190 | func openReader(fs afero.Fs, name string) (io.ReaderAt, int64, []afero.File, error) { |
| 191 | f, err := fs.Open(filepath.Clean(name)) |