Files
go-dpkg/dpkg/writer.go
Matheus Sampaio Queiroga 8cf5fcbfc3
All checks were successful
Golang test / go-test (pull_request) Successful in 21s
Golang test / go-test (push) Successful in 21s
Refactor deb822 package: Remove deprecated files and implement new encoding/decoding logic
- 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>
2025-06-22 22:05:41 -03:00

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
}