pkg/sdk/fsutil/targzfs/file.go (114 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package targzfs import ( "archive/tar" "io" "io/fs" "time" ) type tarEntry struct { h *tar.Header b []byte // If the file is a directory, the following property will contain // owned files. entries []fs.DirEntry } // Implementation of fs.DirEntry for tarEntry. var _ fs.DirEntry = (*tarEntry)(nil) // Name returns the basename of the file. func (f *tarEntry) Name() string { return f.h.FileInfo().Name() } // Type returns file mode. func (f *tarEntry) Type() fs.FileMode { return f.h.FileInfo().Mode() & fs.ModeType } // IsDir returns whether this file is a directory (always false). func (f *tarEntry) IsDir() bool { return f.h.FileInfo().IsDir() } // Info returns file info. func (f *tarEntry) Info() (fs.FileInfo, error) { return f.h.FileInfo(), nil } type tarFile struct { tarEntry r io.ReadSeeker readDirPos int } // Implementation of fs.File for tarFile. var _ fs.File = (*tarFile)(nil) // Stat returns a fs.FileInfo for the given file. func (f *tarFile) Stat() (fs.FileInfo, error) { return f.h.FileInfo(), nil } // Read reads the next len(p) bytes from the buffer or until the buffer is drained. func (f *tarFile) Read(buf []byte) (int, error) { if f.IsDir() { return 0, &fs.PathError{Op: "read", Path: f.Name(), Err: fs.ErrInvalid} } return f.r.Read(buf) } // Close is a no-op. func (f *tarFile) Close() error { return nil } // Implementation of io.Seeker for tarFile. var _ io.Seeker = (*tarFile)(nil) func (f *tarFile) Seek(offset int64, whence int) (int64, error) { if f.IsDir() { return 0, &fs.PathError{Op: "seek", Path: f.Name(), Err: fs.ErrInvalid} } return f.r.Seek(offset, whence) } // Implementation of fs.ReadDirFile for tarFile. var _ fs.ReadDirFile = (*tarFile)(nil) func (f *tarFile) ReadDir(n int) ([]fs.DirEntry, error) { if !f.IsDir() { return nil, &fs.PathError{Op: "readdir", Path: f.Name(), Err: fs.ErrInvalid} } if f.readDirPos >= len(f.entries) { if n <= 0 { return nil, nil } return nil, io.EOF } var entries []fs.DirEntry if n > 0 && f.readDirPos+n <= len(f.entries) { entries = f.entries[f.readDirPos : f.readDirPos+n] f.readDirPos += n } else { entries = f.entries[f.readDirPos:] f.readDirPos += len(entries) } return entries, nil } // Implmentation of fs.FileInfo for tarFile. var _ fs.FileInfo = (*tarFile)(nil) // Size returns the length in bytes for this file. func (f *tarFile) Size() int64 { return f.h.Size } // Mode returns the mode for this file. func (f *tarFile) Mode() fs.FileMode { return f.h.FileInfo().Mode() } // Mode returns the mtime for this file (always the Unix epoch). func (f *tarFile) ModTime() time.Time { return f.h.ModTime } // Sys returns nil. func (f *tarFile) Sys() interface{} { return nil } // ----------------------------------------------------------------------------- type rootFile struct{} var _ fs.File = (*rootFile)(nil) func (rf *rootFile) Stat() (fs.FileInfo, error) { return rf, nil } func (*rootFile) Read([]byte) (int, error) { return 0, &fs.PathError{Op: "read", Path: ".", Err: fs.ErrInvalid} } func (*rootFile) Close() error { return nil } var _ fs.FileInfo = (*rootFile)(nil) func (rf *rootFile) Name() string { return "." } func (rf *rootFile) Size() int64 { return 0 } func (rf *rootFile) Mode() fs.FileMode { return fs.ModeDir | 0o755 } func (rf *rootFile) ModTime() time.Time { return time.Time{} } func (rf *rootFile) IsDir() bool { return true } func (rf *rootFile) Sys() interface{} { return nil }