-
-
Notifications
You must be signed in to change notification settings - Fork 321
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
server(filesystem): allow decompressing individual files
Implements logic for handling a file that is compressed but isn't an archive. Fixes pterodactyl/panel#5034 Signed-off-by: Matthew Penner <[email protected]>
- Loading branch information
Showing
2 changed files
with
104 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// SPDX-License-Identifier: MIT | ||
// SPDX-FileCopyrightText: Copyright (c) 2016 Matthew Holt | ||
|
||
// Code in this file was derived from | ||
// https://github.com/mholt/archiver/blob/v4.0.0-alpha.8/fs.go | ||
// | ||
// These modifications were necessary to allow us to use an already open file | ||
// with archiver.FileFS. | ||
|
||
package archiverext | ||
|
||
import ( | ||
"io" | ||
"io/fs" | ||
|
||
"github.com/mholt/archiver/v4" | ||
) | ||
|
||
// FileFS allows accessing a file on disk using a consistent file system interface. | ||
// The value should be the path to a regular file, not a directory. This file will | ||
// be the only entry in the file system and will be at its root. It can be accessed | ||
// within the file system by the name of "." or the filename. | ||
// | ||
// If the file is compressed, set the Compression field so that reads from the | ||
// file will be transparently decompressed. | ||
type FileFS struct { | ||
// File is the compressed file backing the FileFS. | ||
File fs.File | ||
|
||
// If file is compressed, setting this field will | ||
// transparently decompress reads. | ||
Compression archiver.Decompressor | ||
} | ||
|
||
// Open opens the named file, which must be the file used to create the file system. | ||
func (f FileFS) Open(name string) (fs.File, error) { | ||
if err := f.checkName(name, "open"); err != nil { | ||
return nil, err | ||
} | ||
if f.Compression == nil { | ||
return f.File, nil | ||
} | ||
r, err := f.Compression.OpenReader(f.File) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return compressedFile{f.File, r}, nil | ||
} | ||
|
||
// ReadDir returns a directory listing with the file as the singular entry. | ||
func (f FileFS) ReadDir(name string) ([]fs.DirEntry, error) { | ||
if err := f.checkName(name, "stat"); err != nil { | ||
return nil, err | ||
} | ||
info, err := f.Stat(name) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return []fs.DirEntry{fs.FileInfoToDirEntry(info)}, nil | ||
} | ||
|
||
// Stat stats the named file, which must be the file used to create the file system. | ||
func (f FileFS) Stat(name string) (fs.FileInfo, error) { | ||
if err := f.checkName(name, "stat"); err != nil { | ||
return nil, err | ||
} | ||
return f.File.Stat() | ||
} | ||
|
||
func (f FileFS) checkName(name, op string) error { | ||
if !fs.ValidPath(name) { | ||
return &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid} | ||
} | ||
// TODO: we may need better name validation. | ||
if name != "." { | ||
return &fs.PathError{Op: op, Path: name, Err: fs.ErrNotExist} | ||
} | ||
return nil | ||
} | ||
|
||
// compressedFile is an fs.File that specially reads | ||
// from a decompression reader, and which closes both | ||
// that reader and the underlying file. | ||
type compressedFile struct { | ||
fs.File | ||
decomp io.ReadCloser | ||
} | ||
|
||
func (cf compressedFile) Read(p []byte) (int, error) { | ||
return cf.decomp.Read(p) | ||
} | ||
|
||
func (cf compressedFile) Close() error { | ||
err := cf.File.Close() | ||
err2 := cf.decomp.Close() | ||
if err2 != nil && err == nil { | ||
err = err2 | ||
} | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters