From 9913b848c69abdc8c6887391b2c9d5665c60c206 Mon Sep 17 00:00:00 2001 From: Caleb Gardner Date: Fri, 26 Feb 2021 01:53:16 -0600 Subject: [PATCH] Added some data writing logic. --- fragment.go | 2 +- writer_compress.go | 109 ++++++++++++++++++++++++++++++++++++++++++++- writer_write.go | 2 +- 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/fragment.go b/fragment.go index 647853c..698e49b 100644 --- a/fragment.go +++ b/fragment.go @@ -12,7 +12,7 @@ import ( type fragmentEntry struct { Start uint64 Size uint32 - // Unused uint32 + _ uint32 //unused } //GetFragmentDataFromInode returns the fragment data for a given inode. diff --git a/writer_compress.go b/writer_compress.go index f2f135f..af88746 100644 --- a/writer_compress.go +++ b/writer_compress.go @@ -1,11 +1,18 @@ package squashfs -import "reflect" +import ( + "io" + "reflect" + "sync" +) func (w *Writer) compressData(data []byte) ([]byte, error) { if reflect.DeepEqual(data, make([]byte, len(data))) { return nil, nil } + if w.Flags.UncompressedData || w.compressor == nil { + return data, nil + } compressedData, err := w.compressor.Compress(data) if err != nil { return nil, err @@ -15,3 +22,103 @@ func (w *Writer) compressData(data []byte) ([]byte, error) { } return compressedData, nil } + +//Writes the given fileHolder to the WriterAt at the given offset. +//If fil.Reader implements io.ReaderAt, the process is threaded. +func (w *Writer) writeFile(fil *fileHolder, write io.WriterAt, startOffset int64) (endOffset int64, err error) { + endOffset = startOffset + var sizes []uint32 + if fil.fragIndex != -1 { + sizes = fil.blockSizes[:len(fil.blockSizes)-1] + } else { + sizes = fil.blockSizes + } + if rdrAt, ok := fil.reader.(io.ReaderAt); ok { + type writeReturn struct { + err error + byts []byte + i int + } + out := make(chan *writeReturn) + var filOffset int64 + var sync sync.WaitGroup + sync.Add(len(sizes)) + for i, size := range sizes { + go func(offset int64, size uint32, i int) { + var ret writeReturn + ret.i = i + defer func() { + out <- &ret + }() + ret.byts = make([]byte, size) + _, ret.err = rdrAt.ReadAt(ret.byts, offset) + if ret.err != nil { + return + } + ret.byts, ret.err = w.compressData(ret.byts) + sync.Done() + }(filOffset, size, i) + filOffset += int64(size) + } + var curInd int + var holdingArea []*writeReturn + for curInd < len(sizes) { + var tmp *writeReturn + for _, ret := range holdingArea { + if ret.i == curInd { + tmp = ret + break + } + } + if tmp == nil { + tmp = <-out + if tmp.err != nil { + sync.Wait() + return endOffset, tmp.err + } + if tmp.i != curInd { + holdingArea = append(holdingArea, tmp) + continue + } + } + fil.blockSizes[curInd] = uint32(len(tmp.byts)) + if len(tmp.byts) == int(w.BlockSize) { + //set uncompressed bit if not compressed + fil.blockSizes[curInd] |= (1 << 24) + } + var n int + n, err = write.WriteAt(tmp.byts, endOffset) + endOffset += int64(n) + if err != nil { + sync.Wait() + return + } + curInd++ + } + return + } + var byts []byte + for i, size := range sizes { + byts = make([]byte, size) + _, err = fil.reader.Read(byts) + if err != nil { + return + } + byts, err = w.compressData(byts) + if err != nil { + return + } + fil.blockSizes[i] = uint32(len(byts)) + if len(byts) == int(w.BlockSize) { + //set uncompressed bit if not compressed + fil.blockSizes[i] |= (1 << 24) + } + var n int + n, err = write.WriteAt(byts, endOffset) + endOffset += int64(n) + if err != nil { + return + } + } + return +} diff --git a/writer_write.go b/writer_write.go index 03e8609..0f19ab9 100644 --- a/writer_write.go +++ b/writer_write.go @@ -26,7 +26,7 @@ func (w *Writer) fixFolders() error { //are added with full permission (777). // //Not working. Yet. -func (w *Writer) WriteTo(write io.Writer) (int64, error) { +func (w *Writer) WriteTo(write io.WriterAt) (int64, error) { err := w.fixFolders() if err != nil { return 0, err