Started work on proper tests.
STILL HAVING STUPID UNEXPLAINABLE NIL POINTERS.
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package squashfs
|
package squashfs
|
||||||
|
|
||||||
|
//A place for temporary, expiremental tests. Not meant for actual testing purposes.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -25,8 +25,9 @@ type Reader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrorMagic = errors.New("magic incorrect. probably not reading squashfs archive")
|
ErrorMagic = errors.New("magic incorrect. probably not reading squashfs archive")
|
||||||
ErrorLog = errors.New("block log is incorrect. possible corrupted archive")
|
ErrorLog = errors.New("block log is incorrect. possible corrupted archive")
|
||||||
|
ErrorVersion = errors.New("squashfs version of archive is not 4.0")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -53,12 +54,15 @@ func NewReader(r io.ReaderAt) (*Reader, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !squash.s.hasMagic() {
|
if !squash.s.checkMagic() {
|
||||||
return nil, ErrorMagic
|
return nil, ErrorMagic
|
||||||
}
|
}
|
||||||
if !squash.s.checkBlockLog() {
|
if !squash.s.checkBlockLog() {
|
||||||
return nil, ErrorLog
|
return nil, ErrorLog
|
||||||
}
|
}
|
||||||
|
if !squash.s.checkVersion() {
|
||||||
|
return nil, ErrorVersion
|
||||||
|
}
|
||||||
switch squash.s.CompType {
|
switch squash.s.CompType {
|
||||||
case GZipCompression:
|
case GZipCompression:
|
||||||
squash.d = decompress.GZip{}
|
squash.d = decompress.GZip{}
|
||||||
|
|||||||
+3
-6
@@ -101,7 +101,7 @@ func (f *File) ReadDir(n int) (out []fs.DirEntry, err error) {
|
|||||||
err = io.EOF
|
err = io.EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var fi FileInfo
|
var fi fileInfo
|
||||||
for _, e := range ents[start:end] {
|
for _, e := range ents[start:end] {
|
||||||
fi, err = f.r.newFileInfo(e)
|
fi, err = f.r.newFileInfo(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -190,10 +190,7 @@ type ExtractionOptions struct {
|
|||||||
//DefaultOptions is the default ExtractionOptions.
|
//DefaultOptions is the default ExtractionOptions.
|
||||||
func DefaultOptions() ExtractionOptions {
|
func DefaultOptions() ExtractionOptions {
|
||||||
return ExtractionOptions{
|
return ExtractionOptions{
|
||||||
DereferenceSymlink: false,
|
FolderPerm: 0755,
|
||||||
UnbreakSymlink: false,
|
|
||||||
Verbose: false,
|
|
||||||
FolderPerm: fs.ModePerm,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +205,7 @@ func (f File) ExtractTo(folder string) error {
|
|||||||
func (f File) ExtractSymlink(folder string) error {
|
func (f File) ExtractSymlink(folder string) error {
|
||||||
return f.ExtractWithOptions(folder, ExtractionOptions{
|
return f.ExtractWithOptions(folder, ExtractionOptions{
|
||||||
DereferenceSymlink: true,
|
DereferenceSymlink: true,
|
||||||
FolderPerm: fs.ModePerm,
|
FolderPerm: 0755,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-12
@@ -8,29 +8,29 @@ import (
|
|||||||
"github.com/CalebQ42/squashfs/internal/inode"
|
"github.com/CalebQ42/squashfs/internal/inode"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileInfo struct {
|
type fileInfo struct {
|
||||||
e directory.Entry
|
e directory.Entry
|
||||||
size int64
|
size int64
|
||||||
perm uint32
|
perm uint32
|
||||||
modTime uint32
|
modTime uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Reader) newFileInfo(e directory.Entry) (FileInfo, error) {
|
func (r Reader) newFileInfo(e directory.Entry) (fileInfo, error) {
|
||||||
i, err := r.inodeFromDir(e)
|
i, err := r.inodeFromDir(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return FileInfo{}, err
|
return fileInfo{}, err
|
||||||
}
|
}
|
||||||
return newFileInfo(e, i), nil
|
return newFileInfo(e, i), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFileInfo(e directory.Entry, i inode.Inode) FileInfo {
|
func newFileInfo(e directory.Entry, i inode.Inode) fileInfo {
|
||||||
var size int64
|
var size int64
|
||||||
if i.Type == inode.Fil {
|
if i.Type == inode.Fil {
|
||||||
size = int64(i.Data.(inode.File).Size)
|
size = int64(i.Data.(inode.File).Size)
|
||||||
} else if i.Type == inode.EFil {
|
} else if i.Type == inode.EFil {
|
||||||
size = int64(i.Data.(inode.EFile).Size)
|
size = int64(i.Data.(inode.EFile).Size)
|
||||||
}
|
}
|
||||||
return FileInfo{
|
return fileInfo{
|
||||||
e: e,
|
e: e,
|
||||||
size: size,
|
size: size,
|
||||||
perm: uint32(i.Perm),
|
perm: uint32(i.Perm),
|
||||||
@@ -38,30 +38,29 @@ func newFileInfo(e directory.Entry, i inode.Inode) FileInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) Name() string {
|
func (f fileInfo) Name() string {
|
||||||
return f.e.Name
|
return f.e.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) Size() int64 {
|
func (f fileInfo) Size() int64 {
|
||||||
return f.size
|
return f.size
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) Mode() fs.FileMode {
|
func (f fileInfo) Mode() fs.FileMode {
|
||||||
if f.IsDir() {
|
if f.IsDir() {
|
||||||
return fs.FileMode(f.perm | uint32(fs.ModeDir))
|
return fs.FileMode(f.perm | uint32(fs.ModeDir))
|
||||||
}
|
}
|
||||||
return fs.FileMode(f.perm)
|
return fs.FileMode(f.perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) ModTime() time.Time {
|
func (f fileInfo) ModTime() time.Time {
|
||||||
return time.Unix(int64(f.modTime), 0)
|
return time.Unix(int64(f.modTime), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) IsDir() bool {
|
func (f fileInfo) IsDir() bool {
|
||||||
return f.e.Type == inode.Dir
|
return f.e.Type == inode.Dir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) Sys() any {
|
func (f fileInfo) Sys() any {
|
||||||
//TODO
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package squashfs_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/CalebQ42/squashfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
squashfsURL = "https://darkstorm.tech/LinuxPATest.sfs"
|
||||||
|
squashfsName = "LinuxPATest.sfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func preTest(dir string) (fil *os.File, err error) {
|
||||||
|
_, err = os.Open(filepath.Join(dir, squashfsName))
|
||||||
|
if err != nil {
|
||||||
|
_, err = os.Open(dir)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err = os.Mkdir(dir, 0755)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
os.Remove(filepath.Join(dir, squashfsName))
|
||||||
|
fil, err = os.Create(filepath.Join(dir, squashfsName))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var resp *http.Response
|
||||||
|
resp, err = http.DefaultClient.Get(squashfsURL)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = io.Copy(fil, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = exec.LookPath("unsquashfs")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = exec.LookPath("mksquashfs")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExtractQuick(t *testing.T) {
|
||||||
|
|
||||||
|
//First, setup everything and extract the archive using the library and unsquashfs
|
||||||
|
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
fil, err := preTest(tmpDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
libPath := filepath.Join(tmpDir, "ExtractLib")
|
||||||
|
unsquashPath := filepath.Join(tmpDir, "ExtractSquashfs")
|
||||||
|
os.Remove(libPath)
|
||||||
|
os.Remove(unsquashPath)
|
||||||
|
rdr, err := squashfs.NewReader(fil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = rdr.ExtractTo(libPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cmd := exec.Command("unsquashfs", "-d", unsquashPath, fil.Name())
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Then compare the sizes and existance between the two (using unsquashfs as a reference).
|
||||||
|
//If the file doesn't exist, or the size is different, we exit.
|
||||||
|
//TODO: Add long test that checks contents.
|
||||||
|
|
||||||
|
squashFils := os.DirFS(unsquashPath)
|
||||||
|
err = fs.WalkDir(squashFils, "", func(path string, d fs.DirEntry, err error) error {
|
||||||
|
t.Log(path)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Fatal("This is a test")
|
||||||
|
}
|
||||||
+5
-1
@@ -24,7 +24,7 @@ type superblock struct {
|
|||||||
ExportTableStart uint64
|
ExportTableStart uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s superblock) hasMagic() bool {
|
func (s superblock) checkMagic() bool {
|
||||||
return s.Magic == 0x73717368
|
return s.Magic == 0x73717368
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +32,10 @@ func (s superblock) checkBlockLog() bool {
|
|||||||
return s.BlockLog == uint16(math.Log2(float64(s.BlockSize)))
|
return s.BlockLog == uint16(math.Log2(float64(s.BlockSize)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s superblock) checkVersion() bool {
|
||||||
|
return s.VerMaj == 4 && s.VerMin == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (s superblock) uncompressedInodes() bool {
|
func (s superblock) uncompressedInodes() bool {
|
||||||
return s.Flags&0x1 == 0x1
|
return s.Flags&0x1 == 0x1
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user