- Deleted old deb822_encode.go and deb822_types.go files. - Introduced new deb822_encode.go with improved Marshall function and Writer struct for encoding. - Added deb822_decode.go for decoding functionality with enhanced error handling. - Created deb822_rawdata.go to define RawData type for handling raw deb822 values. - Implemented Description type in deb822/datatype/description.go for structured description handling. - Updated Package struct in dpkg/header.go to use new Description type. - Refactored UnmarshalBinary method in dpkg/header.go to utilize new deb822 decoding logic. - Added comprehensive tests for encoding and decoding in deb822_encode_test.go and deb822_decode_test.go. - Removed internal scanner package as it was no longer needed. Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
116 lines
3.1 KiB
Go
116 lines
3.1 KiB
Go
package dpkg
|
|
|
|
import (
|
|
"archive/tar"
|
|
"compress/gzip"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
|
|
"sirherobrine23.com.br/sirherobrine23/go-dpkg/ar"
|
|
)
|
|
|
|
// Package info
|
|
type WriteInfo struct {
|
|
Pkg *Package // Package info
|
|
ExtraFile map[string]func() (fs.File, error) // file info to add to control.tar
|
|
DataExt string // Data extension, exp: `.gz`
|
|
DataSize int64 // Data size
|
|
}
|
|
|
|
// Writer to data.tar
|
|
type DpkgWriter struct {
|
|
Info *WriteInfo
|
|
ar *ar.Writer
|
|
}
|
|
|
|
func (w *DpkgWriter) Write(p []byte) (n int, err error) { return w.ar.Write(p) }
|
|
|
|
// NewWrite creates a new DpkgWriter that writes a Debian package archive to the provided io.Writer.
|
|
// It constructs the control archive (control.tar.gz) with the package control information and any extra files,
|
|
// then writes the required ar archive members ("debian-binary", "control.tar.gz", and "data.tar.*").
|
|
// The Info parameter must not be nil and should contain all necessary package metadata and data.
|
|
// Returns a pointer to the created DpkgWriter or an error if any step fails.
|
|
func NewWrite(w io.Writer, Info *WriteInfo) (*DpkgWriter, error) {
|
|
if Info == nil {
|
|
return nil, fmt.Errorf("info is nil, set package info to write dpkg package")
|
|
}
|
|
|
|
tmpControl, err := os.CreateTemp("", "control*.tgz")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer os.Remove(tmpControl.Name())
|
|
defer tmpControl.Close()
|
|
|
|
gz := gzip.NewWriter(tmpControl)
|
|
defer gz.Close()
|
|
|
|
controlTar := tar.NewWriter(gz)
|
|
defer controlTar.Close()
|
|
|
|
if err := controlTar.WriteHeader(&tar.Header{Name: "control", Size: Info.Pkg.Sizeof(), Mode: 0644}); err != nil {
|
|
return nil, err
|
|
} else if _, err := Info.Pkg.WriteTo(controlTar); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for name, fileOpen := range Info.ExtraFile {
|
|
if strings.ToLower(path.Base(name)) == "control" {
|
|
continue
|
|
}
|
|
|
|
f, err := fileOpen()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
|
|
info, err := f.Stat()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tarHead, err := tar.FileInfoHeader(info, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tarHead.Name = name
|
|
|
|
if err := controlTar.WriteHeader(tarHead); err != nil {
|
|
return nil, err
|
|
} else if _, err := io.Copy(controlTar, f); err != nil {
|
|
return nil, err
|
|
}
|
|
f.Close()
|
|
}
|
|
|
|
if err := controlTar.Close(); err != nil {
|
|
return nil, err
|
|
} else if err := gz.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
tmpControl.Seek(0, 0)
|
|
stat, err := tmpControl.Stat()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
arw := ar.NewWriter(w)
|
|
if _, err = arw.WriteFile([]byte("2.0\n"), &ar.Header{Filename: "debian-binary", Mode: 0644, Size: 4}); err != nil {
|
|
return nil, err
|
|
} else if _, err = arw.WriteHeader(&ar.Header{Filename: "control.tar.gz", Mode: 0644, Size: stat.Size()}); err != nil {
|
|
return nil, err
|
|
} else if _, err = io.Copy(arw, tmpControl); err != nil {
|
|
return nil, err
|
|
}
|
|
tmpControl.Close()
|
|
os.Remove(tmpControl.Name())
|
|
if _, err = arw.WriteHeader(&ar.Header{Filename: fmt.Sprintf("data.tar%s", Info.DataExt), Mode: 0644, Size: Info.DataSize}); err != nil {
|
|
return nil, err
|
|
}
|
|
return &DpkgWriter{ar: arw, Info: Info}, nil
|
|
}
|