diff --git a/reader.go b/reader.go index 992676a..04c6851 100644 --- a/reader.go +++ b/reader.go @@ -54,7 +54,7 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { rdr.flags = rdr.super.GetFlags() if rdr.flags.CompressorOptions { switch rdr.super.CompressionType { - case gzipCompression: + case GzipCompression: gzip, err := compression.NewGzipCompressorWithOptions(io.NewSectionReader(rdr.r, int64(binary.Size(rdr.super)), 8)) if err != nil { return nil, err @@ -63,7 +63,7 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { hasUnsupportedOptions = true } rdr.decompressor = gzip - case xzCompression: + case XzCompression: xz, err := compression.NewXzCompressorWithOptions(io.NewSectionReader(rdr.r, int64(binary.Size(rdr.super)), 8)) if err != nil { return nil, err @@ -72,7 +72,7 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { return nil, errors.New("XZ compression options has filters. These are not yet supported") } rdr.decompressor = xz - case lz4Compression: + case Lz4Compression: lz4, err := compression.NewLz4CompressorWithOptions(io.NewSectionReader(rdr.r, int64(binary.Size(rdr.super)), 8)) if err != nil { return nil, err @@ -81,26 +81,26 @@ func NewSquashfsReader(r io.ReaderAt) (*Reader, error) { hasUnsupportedOptions = true } rdr.decompressor = lz4 - case zstdCompression: + case ZstdCompression: zstd, err := compression.NewZstdCompressorWithOptions(io.NewSectionReader(rdr.r, int64(binary.Size(rdr.super)), 4)) if err != nil { return nil, err } rdr.decompressor = zstd default: - return nil, errCompressorOptions + return nil, errIncompatibleCompression } } else { switch rdr.super.CompressionType { - case gzipCompression: + case GzipCompression: rdr.decompressor = &compression.Gzip{} - case lzmaCompression: + case LzmaCompression: rdr.decompressor = &compression.Lzma{} - case xzCompression: + case XzCompression: rdr.decompressor = &compression.Xz{} - case lz4Compression: + case Lz4Compression: rdr.decompressor = &compression.Lz4{} - case zstdCompression: + case ZstdCompression: rdr.decompressor = &compression.Zstd{} default: //TODO: all compression types. diff --git a/superblock.go b/superblock.go index e21910d..ffffc05 100644 --- a/superblock.go +++ b/superblock.go @@ -1,12 +1,13 @@ package squashfs +//The types of compression supported by squashfs. const ( - gzipCompression = 1 + iota - lzmaCompression - lzoCompression - xzCompression - lz4Compression - zstdCompression + GzipCompression = 1 + iota + LzmaCompression + LzoCompression + XzCompression + Lz4Compression + ZstdCompression ) //Superblock contains important information about a squashfs file. Located at the very front of the archive. diff --git a/writer.go b/writer.go index 06ce484..7f94b39 100644 --- a/writer.go +++ b/writer.go @@ -3,36 +3,67 @@ package squashfs import ( "errors" "os" - - "github.com/CalebQ42/squashfs/internal/inode" + "path" ) //Writer is an interface to write a squashfs. Doesn't write until you call Write (TODO: maybe not do Write...) type Writer struct { - files map[string]*File - directories []string + files map[string][]*File + directories []string + resolveSymlinks bool + compression int + temp []*File } -func convertFile(file *os.File) (*File, error) { +//NewWriter creates a new squashfs.Writer with the default settings (gzip compression and autoresolving symlinks) +func NewWriter() (*Writer, error) { + return NewWriterWithOptions(true, GzipCompression) +} + +//NewWriterWithOptions creates a new squashfs.Writer with the given options. +//ResolveSymlinks tries to make sure symlinks aren't broken, and if they would be +func NewWriterWithOptions(resolveSymlinks bool, compressionType int) (*Writer, error) { + if compressionType < 0 || compressionType > 6 || compressionType == 3 { + return nil, errors.New("Incompatible compression type") + } + return &Writer{ + files: map[string][]*File{ + "/": make([]*File, 0), + }, + directories: []string{"/"}, + resolveSymlinks: resolveSymlinks, + compression: compressionType, + }, nil +} + +func (w *Writer) convertFile(squashfsPath string, file *os.File) error { + var fil File + fil.Reader = file + fil.name = path.Base(file.Name()) + fil.path = squashfsPath stat, err := file.Stat() if err != nil { - return nil, err + return err } - var filType int + defer func() { w.temp = append(w.temp, &fil) }() if stat.IsDir() { - //TODO - } else if stat.Mode().IsRegular() { - filType = inode.BasicFileType - return &File{ - Reader: file, - name: file.Name(), - filType: filType, - }, nil - } else if stat.Mode()&os.ModeSymlink == os.ModeSymlink { - //TODO: implement symlink support - return nil, errors.New("No symlink support. No support at all actually...") + dirs, err := file.Readdirnames(-1) + if err != nil { + return err + } + for _, dir := range dirs { + subFil, err := os.Open(file.Name() + dir) + if err != nil { + return err + } + err = w.convertFile(fil.Path(), subFil) + if err != nil { + return err + } + } } - return nil, errors.New("File type is NOT supported") + //TODO: reg files & symlinks + return nil } //AddFilesToPath adds the give os.Files to the given path within the squashfs archive.