diff --git a/writer.go b/writer.go index 5939109..5fd70ce 100644 --- a/writer.go +++ b/writer.go @@ -33,6 +33,7 @@ type Writer struct { //variables used when actually writing. superblock superblock + frags []fragment } //NewWriter creates a new with the default options (Gzip compression and allow errors) @@ -68,10 +69,11 @@ type fileHolder struct { path string name string symLocation string - UID int + blockSizes []uint32 GUID int perm int - size uint32 + size uint64 + UID int folder bool symlink bool } @@ -164,7 +166,7 @@ func (w *Writer) AddFileTo(filepath string, file *os.File) error { //AddReaderTo adds the data from the given reader to the archive as a file located at the given filepath. //Data from the reader is not read until the squashfs archive is writen. //If the given reader implements io.Closer, it will be closed after it is fully read. -func (w *Writer) AddReaderTo(filepath string, reader io.Reader) error { +func (w *Writer) AddReaderTo(filepath string, reader io.Reader, size uint64) error { filepath = path.Clean(filepath) if !strings.HasPrefix(filepath, "/") { filepath = "/" + filepath @@ -175,6 +177,7 @@ func (w *Writer) AddReaderTo(filepath string, reader io.Reader) error { var holder fileHolder holder.path = path.Dir(filepath) holder.name = path.Base(filepath) + holder.size = size holder.reader = reader w.structure[holder.path] = append(w.structure[holder.path], &holder) return nil diff --git a/compress.go b/writer_compress.go similarity index 100% rename from compress.go rename to writer_compress.go diff --git a/writer_fragment.go b/writer_fragment.go new file mode 100644 index 0000000..165be64 --- /dev/null +++ b/writer_fragment.go @@ -0,0 +1,21 @@ +package squashfs + +type fragment struct { + w *Writer + files []*fileHolder + sizes []uint32 +} + +func (f *fragment) SizeLeft() uint32 { + totalSize := uint32(0) + for _, siz := range f.sizes { + totalSize += siz + } + return f.w.BlockSize - uint32(totalSize) +} + +func (f *fragment) AddFragment(fil *fileHolder) { + //SizeLeft should already be checked + f.files = append(f.files, fil) + f.sizes = append(f.sizes, fil.blockSizes[len(fil.blockSizes)-1]) +} diff --git a/writer_inodes.go b/writer_inodes.go new file mode 100644 index 0000000..685efbe --- /dev/null +++ b/writer_inodes.go @@ -0,0 +1,23 @@ +package squashfs + +func (w *Writer) countInodes() (out uint32) { + for _, files := range w.structure { + out++ + out += uint32(len(files)) + } + return +} + +//intilialize the block sizes. These values will be overwritten with their compressed sizes later. +func (w *Writer) calculateBlockSizes(fil *fileHolder) { + tmp := fil.size + for { + if tmp < uint64(w.BlockSize) { + fil.blockSizes = append(fil.blockSizes, uint32(tmp)) + break + } + tmp -= uint64(w.BlockSize) + fil.blockSizes = append(fil.blockSizes, w.BlockSize) + } + return +} diff --git a/writer_write.go b/writer_write.go index 5f3de19..db1a4e9 100644 --- a/writer_write.go +++ b/writer_write.go @@ -3,21 +3,32 @@ package squashfs import ( "errors" "io" + "io/fs" "math" - "path" + "time" ) func (w *Writer) fixFolders() error { for folder := range w.structure { - if folder == "/" { + if folder == "/" || w.Contains(folder) { continue } - dir, name := path.Dir(folder), path.Base(folder) + err := w.AddFolderTo(folder, fs.ModePerm) + if err != nil { + return err + } } + return nil } //WriteTo attempts to write the archive to the given io.Writer. +//Folder that aren't present (such as if you add a file at /folder/file, but not the folder /folder) +//are added with full permission (777). func (w *Writer) WriteTo(write io.Writer) (int64, error) { + err := w.fixFolders() + if err != nil { + return 0, err + } if w.BlockSize > 1048576 { w.BlockSize = 1048576 } else if w.BlockSize < 4096 { @@ -28,6 +39,8 @@ func (w *Writer) WriteTo(write io.Writer) (int64, error) { w.Flags.NoXattr = true w.superblock = superblock{ Magic: magic, + InodeCount: w.countInodes(), + CreationTime: uint32(time.Now().Unix()), BlockSize: w.BlockSize, BlockLog: uint16(math.Log2(float64(w.BlockSize))), CompressionType: uint16(w.compressionType),