Added some data writing logic.

This commit is contained in:
Caleb Gardner
2021-02-26 01:53:16 -06:00
parent 65bc4a5d78
commit 9913b848c6
3 changed files with 110 additions and 3 deletions
+108 -1
View File
@@ -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
}