wings/server/filesystem/archive_test.go
Matthew Penner d1c0ca5260
server(filesystem): rebuild everything imaginable
This wonderfully large commit replaces basically everything under the
`server/filesystem` package, re-implementing essentially everything.

This is related to
https://github.com/pterodactyl/wings/security/advisories/GHSA-494h-9924-xww9

If any vulnerabilities related to symlinks persist after this commit, I
will be very upset.

Signed-off-by: Matthew Penner <me@matthewp.io>
2024-03-13 12:27:29 -06:00

123 lines
2.6 KiB
Go

package filesystem
import (
"context"
iofs "io/fs"
"os"
"path/filepath"
"sort"
"strings"
"testing"
. "github.com/franela/goblin"
"github.com/mholt/archiver/v4"
)
func TestArchive_Stream(t *testing.T) {
g := Goblin(t)
fs, rfs := NewFs()
g.Describe("Archive", func() {
g.AfterEach(func() {
// Reset the filesystem after each run.
_ = fs.TruncateRootDirectory()
})
g.It("creates archive with intended files", func() {
g.Assert(fs.CreateDirectory("test", "/")).IsNil()
g.Assert(fs.CreateDirectory("test2", "/")).IsNil()
r := strings.NewReader("hello, world!\n")
err := fs.Write("test/file.txt", r, r.Size(), 0o644)
g.Assert(err).IsNil()
r = strings.NewReader("hello, world!\n")
err = fs.Write("test2/file.txt", r, r.Size(), 0o644)
g.Assert(err).IsNil()
r = strings.NewReader("hello, world!\n")
err = fs.Write("test_file.txt", r, r.Size(), 0o644)
g.Assert(err).IsNil()
r = strings.NewReader("hello, world!\n")
err = fs.Write("test_file.txt.old", r, r.Size(), 0o644)
g.Assert(err).IsNil()
a := &Archive{
Filesystem: fs,
Files: []string{
"test",
"test_file.txt",
},
}
// Create the archive.
archivePath := filepath.Join(rfs.root, "archive.tar.gz")
g.Assert(a.Create(context.Background(), archivePath)).IsNil()
// Ensure the archive exists.
_, err = os.Stat(archivePath)
g.Assert(err).IsNil()
// Open the archive.
genericFs, err := archiver.FileSystem(context.Background(), archivePath)
g.Assert(err).IsNil()
// Assert that we are opening an archive.
afs, ok := genericFs.(archiver.ArchiveFS)
g.Assert(ok).IsTrue()
// Get the names of the files recursively from the archive.
files, err := getFiles(afs, ".")
g.Assert(err).IsNil()
// Ensure the files in the archive match what we are expecting.
expected := []string{
"test_file.txt",
"test/file.txt",
}
// Sort the slices to ensure the comparison never fails if the
// contents are sorted differently.
sort.Strings(expected)
sort.Strings(files)
g.Assert(files).Equal(expected)
})
})
}
func getFiles(f iofs.ReadDirFS, name string) ([]string, error) {
var v []string
entries, err := f.ReadDir(name)
if err != nil {
return nil, err
}
for _, e := range entries {
entryName := e.Name()
if name != "." {
entryName = filepath.Join(name, entryName)
}
if e.IsDir() {
files, err := getFiles(f, entryName)
if err != nil {
return nil, err
}
if files == nil {
return nil, nil
}
v = append(v, files...)
continue
}
v = append(v, entryName)
}
return v, nil
}