Added some data writing logic.
This commit is contained in:
+108
-1
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user