diff --git a/datareader.go b/datareader.go index 84f4d34..60f2d5a 100644 --- a/datareader.go +++ b/datareader.go @@ -153,9 +153,12 @@ func (d *dataReader) Close() error { func (d *dataReader) Read(p []byte) (int, error) { 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++ { p[i] = d.curData[d.curReadOffset+i] } diff --git a/file.go b/file.go index b9ba55e..f1f70d3 100644 --- a/file.go +++ b/file.go @@ -255,14 +255,15 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o errs = append(errs, err) return } - err = fil.Chown(int(f.r.idTable[f.in.Header.UID]), int(f.r.idTable[f.in.Header.GID])) - if err != nil { - if verbose { - fmt.Println("Error while changing owner:", path+"/"+f.Name) - fmt.Println(err) - } - errs = append(errs, err) - } + fil.Chown(int(f.r.idTable[f.in.Header.UID]), int(f.r.idTable[f.in.Header.GID])) + //don't mention anything when it fails. Because it fails often. Probably has something to do about uid & gid 0 + // if err != nil { + // if verbose { + // fmt.Println("Error while changing owner:", path+"/"+f.Name) + // fmt.Println(err) + // } + // errs = append(errs, err) + // } err = fil.Chmod(f.Permission()) if err != nil { if verbose { @@ -324,8 +325,7 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o } errs = append(errs, err) return - } - // defer f.Close() //Since we will be reading from the file + } //Since we will be reading from the file _, err = io.Copy(fil, f) if err != nil { if verbose { @@ -335,15 +335,17 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o errs = append(errs, err) return } + f.Close() err = fil.Chown(int(f.r.idTable[f.in.Header.UID]), int(f.r.idTable[f.in.Header.GID])) - if err != nil { - if verbose { - fmt.Println("Error while changing owner:", path+"/"+f.Name) - fmt.Println(err) - } - errs = append(errs, err) - return - } + //don't mention anything when it fails. Because it fails often. Probably has something to do about uid & gid 0 + // if err != nil { + // if verbose { + // fmt.Println("Error while changing owner:", path+"/"+f.Name) + // fmt.Println(err) + // } + // errs = append(errs, err) + // return + // } err = fil.Chmod(f.Permission()) if err != nil { if verbose { @@ -354,8 +356,32 @@ func (f *File) ExtractWithOptions(path string, unbreakSymlink bool, folderPerm o } return case f.IsSymlink(): - //just a temp thing real quick - os.Symlink(f.SymlinkPath(), path+"/"+f.Name) + symPath := f.SymlinkPath() + 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 } diff --git a/metadata.go b/metadata.go index 5e8562f..c3ed076 100644 --- a/metadata.go +++ b/metadata.go @@ -104,7 +104,7 @@ func (br *metadataReader) readNextDataBlock() error { //Read reads bytes into the given byte slice. Returns the amount of data read. 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++ { p[i] = br.data[br.readOffset+i] } diff --git a/reader.go b/reader.go index c835216..d030cec 100644 --- a/reader.go +++ b/reader.go @@ -3,6 +3,7 @@ package squashfs import ( "encoding/binary" "errors" + "fmt" "io" "math" @@ -44,6 +45,9 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { if rdr.super.Magic != magic { 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() switch rdr.super.CompressionType { case gzipCompression: @@ -54,10 +58,11 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { //TODO: all compression types. return nil, errIncompatibleCompression } - // if rdr.flags.CompressorOptions { - // //TODO: parse compressor options - // return nil, errCompressorOptions - // } + if rdr.flags.CompressorOptions { + fmt.Println("has options") + //TODO: parse compressor options + return nil, errCompressorOptions + } fragBlocks := int(math.Ceil(float64(rdr.super.FragCount) / 512)) if fragBlocks > 0 { offset := int64(rdr.super.FragTableStart) @@ -74,7 +79,7 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { unread := rdr.super.IDCount blockOffsets := make([]uint64, int(math.Ceil(float64(rdr.super.IDCount)/2048))) 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]) if err != nil { return nil, err diff --git a/squash_test.go b/squash_test.go index 7fe8e00..b4ec84b 100644 --- a/squash_test.go +++ b/squash_test.go @@ -1,7 +1,6 @@ package squashfs import ( - "fmt" "io" "net/http" "os" @@ -17,7 +16,6 @@ const ( ) func TestSquashfs(t *testing.T) { - fmt.Println("YOOO") wd, err := os.Getwd() if err != nil { t.Fatal(err) @@ -31,12 +29,9 @@ func TestSquashfs(t *testing.T) { t.Fatal(err) } os.RemoveAll(wd + "/testing/" + squashfsName + ".d") - fmt.Println("Whaaaa") root, _ := rdr.GetRootFolder() - fmt.Println("WHYYYY") errs := root.ExtractWithOptions(wd+"/testing/"+squashfsName+".d", false, os.ModePerm, true) - fmt.Println(errs) - t.Fatal("No prolems here!") + t.Fatal(errs) } func TestAppImage(t *testing.T) { @@ -62,13 +57,10 @@ func TestAppImage(t *testing.T) { if err != nil { t.Fatal(err) } - fil := rdr.GetFileAtPath("/usr/bin/cool-retro-term") - if fil != nil { - fmt.Println("Worked!", fil.Path()) - } else { - t.Fatal("NOOOOOO!") - } - t.Fatal("No problems here!") + os.RemoveAll(wd + "/testing/" + appImageName + ".d") + root, _ := rdr.GetRootFolder() + errs := root.ExtractWithOptions(wd+"/testing/"+appImageName+".d", true, os.ModePerm, true) + t.Fatal(errs) } func downloadTestAppImage(t *testing.T, dir string) {