Extracting is mostly finished.

Fixed reading metadata and data blocks that are the exactly correct size
This commit is contained in:
Caleb Gardner
2020-12-02 01:05:31 -06:00
parent 28bb0f873a
commit fef7bec20d
5 changed files with 67 additions and 41 deletions
+5 -2
View File
@@ -153,9 +153,12 @@ func (d *dataReader) Close() error {
func (d *dataReader) Read(p []byte) (int, error) { func (d *dataReader) Read(p []byte) (int, error) {
if d.curData == nil { if d.curData == nil {
d.readCurBlock() err := d.readCurBlock()
if err != nil {
return 0, err
} }
if d.curReadOffset+len(p) < len(d.curData) { }
if d.curReadOffset+len(p) <= len(d.curData) {
for i := 0; i < len(p); i++ { for i := 0; i < len(p); i++ {
p[i] = d.curData[d.curReadOffset+i] p[i] = d.curData[d.curReadOffset+i]
} }
+46 -20
View File
@@ -255,14 +255,15 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o
errs = append(errs, err) errs = append(errs, err)
return return
} }
err = fil.Chown(int(f.r.idTable[f.in.Header.UID]), int(f.r.idTable[f.in.Header.GID])) fil.Chown(int(f.r.idTable[f.in.Header.UID]), int(f.r.idTable[f.in.Header.GID]))
if err != nil { //don't mention anything when it fails. Because it fails often. Probably has something to do about uid & gid 0
if verbose { // if err != nil {
fmt.Println("Error while changing owner:", path+"/"+f.Name) // if verbose {
fmt.Println(err) // fmt.Println("Error while changing owner:", path+"/"+f.Name)
} // fmt.Println(err)
errs = append(errs, err) // }
} // errs = append(errs, err)
// }
err = fil.Chmod(f.Permission()) err = fil.Chmod(f.Permission())
if err != nil { if err != nil {
if verbose { if verbose {
@@ -324,8 +325,7 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o
} }
errs = append(errs, err) errs = append(errs, err)
return return
} } //Since we will be reading from the file
// defer f.Close() //Since we will be reading from the file
_, err = io.Copy(fil, f) _, err = io.Copy(fil, f)
if err != nil { if err != nil {
if verbose { if verbose {
@@ -335,15 +335,17 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o
errs = append(errs, err) errs = append(errs, err)
return return
} }
f.Close()
err = fil.Chown(int(f.r.idTable[f.in.Header.UID]), int(f.r.idTable[f.in.Header.GID])) err = fil.Chown(int(f.r.idTable[f.in.Header.UID]), int(f.r.idTable[f.in.Header.GID]))
if err != nil { //don't mention anything when it fails. Because it fails often. Probably has something to do about uid & gid 0
if verbose { // if err != nil {
fmt.Println("Error while changing owner:", path+"/"+f.Name) // if verbose {
fmt.Println(err) // fmt.Println("Error while changing owner:", path+"/"+f.Name)
} // fmt.Println(err)
errs = append(errs, err) // }
return // errs = append(errs, err)
} // return
// }
err = fil.Chmod(f.Permission()) err = fil.Chmod(f.Permission())
if err != nil { if err != nil {
if verbose { if verbose {
@@ -354,8 +356,32 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o
} }
return return
case f.IsSymlink(): case f.IsSymlink():
//just a temp thing real quick symPath := f.SymlinkPath()
os.Symlink(f.SymlinkPath(), path+"/"+f.Name) if unbreakSymlink {
fil := f.GetSymlinkFile()
if fil != nil {
symPath = path + "/" + symPath
paths := strings.Split(symPath, "/")
extracSymErrs := fil.ExtractWithOptions(strings.Join(paths[:len(paths)-1], "/"), unbreakSymlink, folderPerm, verbose)
if len(extracSymErrs) > 0 {
if verbose {
fmt.Println("Error(s) while extracting the symlink's file:", path+"/"+f.Name)
fmt.Println(extracSymErrs)
}
errs = append(errs, extracSymErrs...)
}
} else {
fmt.Println("Symlink path(", symPath, ") is outside the archive:"+path+"/"+f.Name)
}
}
err = os.Symlink(f.SymlinkPath(), path+"/"+f.Name)
if err != nil {
if verbose {
fmt.Println("Error while making symlink:", path+"/"+f.Name)
fmt.Println(err)
}
errs = append(errs, err)
}
} }
return return
} }
+1 -1
View File
@@ -104,7 +104,7 @@ func (br *metadataReader) readNextDataBlock() error {
//Read reads bytes into the given byte slice. Returns the amount of data read. //Read reads bytes into the given byte slice. Returns the amount of data read.
func (br *metadataReader) Read(p []byte) (int, error) { func (br *metadataReader) Read(p []byte) (int, error) {
if br.readOffset+len(p) < len(br.data) { if br.readOffset+len(p) <= len(br.data) {
for i := 0; i < len(p); i++ { for i := 0; i < len(p); i++ {
p[i] = br.data[br.readOffset+i] p[i] = br.data[br.readOffset+i]
} }
+10 -5
View File
@@ -3,6 +3,7 @@ package squashfs
import ( import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"math" "math"
@@ -44,6 +45,9 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) {
if rdr.super.Magic != magic { if rdr.super.Magic != magic {
return nil, errNoMagic return nil, errNoMagic
} }
// if rdr.super.BlockLog == uint16(math.Log2(float64(rdr.super.BlockSize))) {
// return nil, errors.New("BlockSize and BlockLog doesn't match. The archive is probably corrupt")
// }
rdr.flags = rdr.super.GetFlags() rdr.flags = rdr.super.GetFlags()
switch rdr.super.CompressionType { switch rdr.super.CompressionType {
case gzipCompression: case gzipCompression:
@@ -54,10 +58,11 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) {
//TODO: all compression types. //TODO: all compression types.
return nil, errIncompatibleCompression return nil, errIncompatibleCompression
} }
// if rdr.flags.CompressorOptions { if rdr.flags.CompressorOptions {
// //TODO: parse compressor options fmt.Println("has options")
// return nil, errCompressorOptions //TODO: parse compressor options
// } return nil, errCompressorOptions
}
fragBlocks := int(math.Ceil(float64(rdr.super.FragCount) / 512)) fragBlocks := int(math.Ceil(float64(rdr.super.FragCount) / 512))
if fragBlocks > 0 { if fragBlocks > 0 {
offset := int64(rdr.super.FragTableStart) offset := int64(rdr.super.FragTableStart)
@@ -74,7 +79,7 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) {
unread := rdr.super.IDCount unread := rdr.super.IDCount
blockOffsets := make([]uint64, int(math.Ceil(float64(rdr.super.IDCount)/2048))) blockOffsets := make([]uint64, int(math.Ceil(float64(rdr.super.IDCount)/2048)))
for i := range blockOffsets { for i := range blockOffsets {
secRdr := io.NewSectionReader(r, int64(rdr.super.IDTableStart)+8*int64(i), 8) secRdr := io.NewSectionReader(r, int64(rdr.super.IDTableStart)+(8*int64(i)), 8)
err = binary.Read(secRdr, binary.LittleEndian, &blockOffsets[i]) err = binary.Read(secRdr, binary.LittleEndian, &blockOffsets[i])
if err != nil { if err != nil {
return nil, err return nil, err
+5 -13
View File
@@ -1,7 +1,6 @@
package squashfs package squashfs
import ( import (
"fmt"
"io" "io"
"net/http" "net/http"
"os" "os"
@@ -17,7 +16,6 @@ const (
) )
func TestSquashfs(t *testing.T) { func TestSquashfs(t *testing.T) {
fmt.Println("YOOO")
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@@ -31,12 +29,9 @@ func TestSquashfs(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
os.RemoveAll(wd + "/testing/" + squashfsName + ".d") os.RemoveAll(wd + "/testing/" + squashfsName + ".d")
fmt.Println("Whaaaa")
root, _ := rdr.GetRootFolder() root, _ := rdr.GetRootFolder()
fmt.Println("WHYYYY")
errs := root.ExtractWithOptions(wd+"/testing/"+squashfsName+".d", false, os.ModePerm, true) errs := root.ExtractWithOptions(wd+"/testing/"+squashfsName+".d", false, os.ModePerm, true)
fmt.Println(errs) t.Fatal(errs)
t.Fatal("No prolems here!")
} }
func TestAppImage(t *testing.T) { func TestAppImage(t *testing.T) {
@@ -62,13 +57,10 @@ func TestAppImage(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
fil := rdr.GetFileAtPath("/usr/bin/cool-retro-term") os.RemoveAll(wd + "/testing/" + appImageName + ".d")
if fil != nil { root, _ := rdr.GetRootFolder()
fmt.Println("Worked!", fil.Path()) errs := root.ExtractWithOptions(wd+"/testing/"+appImageName+".d", true, os.ModePerm, true)
} else { t.Fatal(errs)
t.Fatal("NOOOOOO!")
}
t.Fatal("No problems here!")
} }
func downloadTestAppImage(t *testing.T, dir string) { func downloadTestAppImage(t *testing.T, dir string) {