diff --git a/src/bpmlib/compilation.go b/src/bpmlib/compilation.go index 08f26d4..ccc6beb 100644 --- a/src/bpmlib/compilation.go +++ b/src/bpmlib/compilation.go @@ -4,11 +4,11 @@ import ( "errors" "fmt" "gopkg.in/yaml.v3" - "io" "os" "os/exec" "path" "strconv" + "strings" ) func CompileSourcePackage(archiveFilename, outputFilename string) (err error) { @@ -46,25 +46,18 @@ func CompileSourcePackage(archiveFilename, outputFilename string) (err error) { } // Extract source.sh file - content, err := readTarballContent(archiveFilename, "source.sh") + err = extractTarballFile(archiveFilename, "source.sh", tempDirectory) if err != nil { return err } - sourceFile, err := os.Create(path.Join(tempDirectory, "source.sh")) - if err != nil { - return err - } - _, err = io.Copy(sourceFile, content.tarReader) - if err != nil { - return err - } - err = sourceFile.Close() - if err != nil { - return err - } - err = content.file.Close() - if err != nil { - return err + + // Get package scripts and extract them + packageScripts := getPackageScripts(archiveFilename) + for _, script := range packageScripts { + err = extractTarballFile(archiveFilename, script, tempDirectory) + if err != nil { + return err + } } // Extract source files @@ -167,8 +160,13 @@ func CompileSourcePackage(archiveFilename, outputFilename string) (err error) { return err } + // Get files to include in BPM archive + bpmArchiveFiles := make([]string, 0) + bpmArchiveFiles = append(bpmArchiveFiles, "pkg.info", "pkg.files", "files.tar.gz") // Base files + bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts + // Create final BPM archive - cmd = exec.Command("bash", "-c", "tar -cf "+outputFilename+" --owner=0 --group=0 -C \"$BPM_WORKDIR\" pkg.info pkg.files ${PACKAGE_SCRIPTS[@]} files.tar.gz") + cmd = exec.Command("bash", "-c", "tar -cf "+outputFilename+" --owner=0 --group=0 -C \"$BPM_WORKDIR\" "+strings.Join(bpmArchiveFiles, " ")) cmd.Dir = tempDirectory cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/src/bpmlib/packages.go b/src/bpmlib/packages.go index da57201..ec0df7a 100644 --- a/src/bpmlib/packages.go +++ b/src/bpmlib/packages.go @@ -218,6 +218,31 @@ func ReadPackage(filename string) (*BPMPackage, error) { }, nil } +func getPackageScripts(filename string) (packageScripts []string) { + content, err := listTarballContent(filename) + if err != nil { + return + } + + for _, file := range content { + if file == "pre_install.sh" { + packageScripts = append(packageScripts, "pre_install.sh") + } else if file == "post_install.sh" { + packageScripts = append(packageScripts, "post_install.sh") + } else if file == "pre_update.sh" { + packageScripts = append(packageScripts, "pre_update.sh") + } else if file == "post_update.sh" { + packageScripts = append(packageScripts, "post_update.sh") + } else if file == "pre_remove.sh" { + packageScripts = append(packageScripts, "pre_remove.sh") + } else if file == "post_remove.sh" { + packageScripts = append(packageScripts, "post_remove.sh") + } + } + + return packageScripts +} + func ReadPackageScripts(filename string) (map[string]string, error) { if _, err := os.Stat(filename); os.IsNotExist(err) { return nil, err @@ -480,7 +505,7 @@ func extractPackage(bpmpkg *BPMPackage, verbose bool, filename, rootDir string) return err } - tarballFile, err := readTarballContent(filename, "files.tar.gz") + tarballFile, err := readTarballFile(filename, "files.tar.gz") if err != nil { return err } @@ -738,7 +763,7 @@ func installPackage(filename, rootDir string, verbose, force bool) error { return err } - tarballFile, err := readTarballContent(filename, "pkg.files") + tarballFile, err := readTarballFile(filename, "pkg.files") if err != nil { return err } diff --git a/src/bpmlib/tarball.go b/src/bpmlib/tarball.go index a6ef764..f60f96a 100644 --- a/src/bpmlib/tarball.go +++ b/src/bpmlib/tarball.go @@ -14,7 +14,35 @@ type tarballFileReader struct { file *os.File } -func readTarballContent(tarballPath, fileToExtract string) (*tarballFileReader, error) { +func listTarballContent(tarballPath string) (content []string, err error) { + file, err := os.Open(tarballPath) + if err != nil { + return nil, err + } + defer file.Close() + + tr := tar.NewReader(file) + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + + switch header.Typeflag { + case tar.TypeDir: + continue + default: + content = append(content, header.Name) + } + } + + return content, nil +} + +func readTarballFile(tarballPath, fileToExtract string) (*tarballFileReader, error) { file, err := os.Open(tarballPath) if err != nil { return nil, err @@ -44,6 +72,60 @@ func readTarballContent(tarballPath, fileToExtract string) (*tarballFileReader, return nil, errors.New("could not file in tarball") } +func extractTarballFile(tarballPath, fileToExtract string, workingDirectory string) (err error) { + file, err := os.Open(tarballPath) + if err != nil { + return err + } + defer file.Close() + + tr := tar.NewReader(file) + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + // Skip if filename does not match + if header.Name != fileToExtract { + continue + } + + // Trim directory name from header name + header.Name = strings.Split(header.Name, "/")[len(strings.Split(header.Name, "/"))-1] + outputPath := path.Join(workingDirectory, header.Name) + + switch header.Typeflag { + case tar.TypeReg: + // Create file and set permissions + file, err = os.Create(outputPath) + if err != nil { + return err + } + err := file.Chmod(header.FileInfo().Mode()) + if err != nil { + return err + } + + // Copy data to file + _, err = io.Copy(file, tr) + if err != nil { + return err + } + + // Close file + file.Close() + default: + continue + } + } + + return nil +} + func extractTarballDirectory(tarballPath, directoryToExtract, workingDirectory string) (err error) { file, err := os.Open(tarballPath) if err != nil {