Setup for differnet types of compression for Writer

Added some TODOs
This commit is contained in:
Caleb Gardner
2021-01-08 14:35:32 -06:00
parent 3f71404a2a
commit 4b3d5d12f8
8 changed files with 119 additions and 20 deletions
+7 -12
View File
@@ -15,23 +15,21 @@ type gzipInit struct {
//Gzip is a decompressor for gzip type compression. Uses zlib for compression and decompression //Gzip is a decompressor for gzip type compression. Uses zlib for compression and decompression
type Gzip struct { type Gzip struct {
CompressionLevel int32 gzipInit
HasCustomWindow bool HasCustomWindow bool
HasStrategies bool HasStrategies bool
} }
//NewGzipCompressorWithOptions creates a new gzip compressor/decompressor with options read from the given reader. //NewGzipCompressorWithOptions creates a new gzip compressor/decompressor with options read from the given reader.
func NewGzipCompressorWithOptions(r io.Reader) (*Gzip, error) { func NewGzipCompressorWithOptions(r io.Reader) (*Gzip, error) {
var gzip Gzip var gzip Gzip
var init gzipInit err := binary.Read(r, binary.LittleEndian, &gzip.gzipInit)
err := binary.Read(r, binary.LittleEndian, &init)
if err != nil { if err != nil {
return nil, err return nil, err
} }
gzip.CompressionLevel = init.CompressionLevel
//TODO: proper support for window size and strategies //TODO: proper support for window size and strategies
gzip.HasCustomWindow = init.WindowSize != 15 gzip.HasCustomWindow = gzip.WindowSize != 15
gzip.HasStrategies = init.Strategies != 0 && init.Strategies != 1 gzip.HasStrategies = gzip.Strategies != 0 && gzip.Strategies != 1
return &gzip, nil return &gzip, nil
} }
@@ -58,9 +56,6 @@ func (g *Gzip) Compress(data []byte) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = wrt.Flush() wrt.Close()
if err != nil {
return nil, err
}
return buf.Bytes(), nil return buf.Bytes(), nil
} }
+18
View File
@@ -35,3 +35,21 @@ func (l *Lz4) Decompress(r io.Reader) ([]byte, error) {
_, err := io.Copy(&buf, rdr) _, err := io.Copy(&buf, rdr)
return buf.Bytes(), err return buf.Bytes(), err
} }
//Compress implements compression.Compress
func (l *Lz4) Compress(data []byte) ([]byte, error) {
var buf bytes.Buffer
w := lz4.NewWriter(&buf)
if l.HC {
err := w.Apply(lz4.CompressionLevelOption(lz4.Level9))
if err != nil {
return nil, err
}
}
_, err := w.Write(data)
if err != nil {
return nil, err
}
w.Close()
return buf.Bytes(), nil
}
+15
View File
@@ -23,3 +23,18 @@ func (l *Lzma) Decompress(rdr io.Reader) ([]byte, error) {
} }
return buf.Bytes(), nil return buf.Bytes(), nil
} }
//Compress implements compression.Compress
func (l *Lzma) Compress(data []byte) ([]byte, error) {
var buf bytes.Buffer
w, err := lzma.NewWriter(&buf)
if err != nil {
return nil, err
}
_, err = w.Write(data)
if err != nil {
return nil, err
}
w.Close()
return buf.Bytes(), nil
}
+20
View File
@@ -53,3 +53,23 @@ func (x *Xz) Decompress(rdr io.Reader) ([]byte, error) {
} }
return buf.Bytes(), nil return buf.Bytes(), nil
} }
//Compress implements compression.Compress
func (x *Xz) Compress(data []byte) ([]byte, error) {
var buf bytes.Buffer
w, err := xz.NewWriter(&buf)
if err != nil {
return nil, err
}
w.DictCap = int(x.DictionarySize)
err = w.Verify()
if err != nil {
return nil, err
}
_, err = w.Write(data)
if err != nil {
return nil, err
}
w.Close()
return buf.Bytes(), nil
}
+15
View File
@@ -34,3 +34,18 @@ func (z *Zstd) Decompress(r io.Reader) ([]byte, error) {
_, err = io.Copy(&buf, rdr) _, err = io.Copy(&buf, rdr)
return buf.Bytes(), err return buf.Bytes(), err
} }
//Compress impelements compression.Compress
func (z *Zstd) Compress(data []byte) ([]byte, error) {
var buf bytes.Buffer
w, err := zstd.NewWriter(&buf, zstd.WithEncoderLevel(zstd.EncoderLevel(z.CompressionLevel)))
if err != nil {
return nil, err
}
_, err = w.Write(data)
if err != nil {
return nil, err
}
w.Close()
return buf.Bytes(), nil
}
-3
View File
@@ -77,9 +77,6 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if lz4.HC {
hasUnsupportedOptions = true
}
rdr.decompressor = lz4 rdr.decompressor = lz4
case ZstdCompression: case ZstdCompression:
zstd, err := compression.NewZstdCompressorWithOptions(io.NewSectionReader(rdr.r, int64(binary.Size(rdr.super)), 4)) zstd, err := compression.NewZstdCompressorWithOptions(io.NewSectionReader(rdr.r, int64(binary.Size(rdr.super)), 4))
+29 -5
View File
@@ -7,6 +7,8 @@ import (
"os" "os"
"path" "path"
"strings" "strings"
"github.com/CalebQ42/squashfs/internal/compression"
) )
type fileHolder struct { type fileHolder struct {
@@ -14,6 +16,8 @@ type fileHolder struct {
path string path string
name string name string
symLocation string symLocation string
UID int
GUID int
folder bool folder bool
symlink bool symlink bool
} }
@@ -21,19 +25,37 @@ type fileHolder struct {
//Writer is used to creaste squashfs archives. Currently unusable //Writer is used to creaste squashfs archives. Currently unusable
//TODO: Make usable //TODO: Make usable
type Writer struct { type Writer struct {
compressor compression.Compressor
structure map[string][]*fileHolder structure map[string][]*fileHolder
symlinkTable map[string]string //[oldpath]newpath symlinkTable map[string]string //[oldpath]newpath
superblock superblock
compressionType int compressionType int
allowErrors bool //AllowErrors allows errors when adding folders and their children. allowErrors bool
} }
//NewWriter creates a new //NewWriter creates a new with the default options (Gzip compression and allow errors)
func NewWriter() (*Writer, error) { func NewWriter() (*Writer, error) {
return NewWriterWithOptions(GzipCompression, true) return NewWriterWithOptions(GzipCompression, true)
} }
//NewWriterWithOptions creates a new squashfs.Writer with the given options.
//compressionType can be of any types, except LZO (which this library doesn't have support for yet)
//allowErrors determines if, when adding folders, it allows errors encountered with it's sub-directories and instead logs the errors.
func NewWriterWithOptions(compressionType int, allowErrors bool) (*Writer, error) { func NewWriterWithOptions(compressionType int, allowErrors bool) (*Writer, error) {
if compressionType < 0 || compressionType > 6 {
return nil, errors.New("Incorrect compression type")
}
if compressionType == 3 {
return nil, errors.New("LZO compression is not (currently) supported")
}
return &Writer{
structure: map[string][]*fileHolder{
"/": make([]*fileHolder, 0),
},
symlinkTable: make(map[string]string),
compressionType: compressionType,
allowErrors: allowErrors,
}, nil
} }
//AddFile attempts to add an os.File to the archive at it's root. //AddFile attempts to add an os.File to the archive at it's root.
@@ -83,7 +105,7 @@ func (w *Writer) AddFileTo(filepath string, file *os.File) error {
return err return err
} }
err = w.AddFileToFolder(holder.path+"/"+holder.name, fil) err = w.AddFileToFolder(holder.path+"/"+holder.name, fil)
if err != nil && !w.AllowErrors { if err != nil && !w.allowErrors {
for _, dir := range dirsAdded { for _, dir := range dirsAdded {
w.Remove(dir) w.Remove(dir)
} }
@@ -92,7 +114,7 @@ func (w *Writer) AddFileTo(filepath string, file *os.File) error {
log.Println("Error while adding", fil.Name()) log.Println("Error while adding", fil.Name())
log.Println(err) log.Println(err)
} }
if !w.AllowErrors { if !w.allowErrors {
dirsAdded = append(dirsAdded, holder.path+"/"+holder.name) dirsAdded = append(dirsAdded, holder.path+"/"+holder.name)
} }
} }
@@ -149,6 +171,7 @@ func (w *Writer) Remove(filepath string) bool {
// //
//If this is not run before writing, you may end up with broken symlinks. //If this is not run before writing, you may end up with broken symlinks.
func (w *Writer) FixSymlinks() error { func (w *Writer) FixSymlinks() error {
//TODO
return errors.New("DON'T") return errors.New("DON'T")
} }
@@ -164,5 +187,6 @@ func (w *Writer) WriteToFilename(filepath string) error {
//WriteTo attempts to write the archive to the given io.Writer. //WriteTo attempts to write the archive to the given io.Writer.
func (w *Writer) WriteTo(write io.Writer) (int64, error) { func (w *Writer) WriteTo(write io.Writer) (int64, error) {
//TODO
return 0, errors.New("I SAID DON'T") return 0, errors.New("I SAID DON'T")
} }
+15
View File
@@ -0,0 +1,15 @@
package squashfs
//TODO: Allow settings the options
// func (w *Writer) SetGzipOptions() error {}
// func (w *Writer) SetLzmaOptions() error {}
// func (w *Writer) SetLzoOptions() error {}
// func (w *Writer) SetXzOptions() error {}
// func (w *Writer) SetLz4Options() error {}
// func (w *Writer) SetZstdOptions() error {}