Reallow direct source package installation using 'bpm install'
This commit is contained in:
parent
d8146cb3f3
commit
9cdb3d29aa
6
Makefile
6
Makefile
@ -6,9 +6,13 @@ SYSCONFDIR := $(PREFIX)/etc
|
|||||||
# Compilers and tools
|
# Compilers and tools
|
||||||
GO ?= $(shell which go)
|
GO ?= $(shell which go)
|
||||||
|
|
||||||
|
# Build-time variables
|
||||||
|
ROOT_COMPILATION_UID ?= 65534
|
||||||
|
ROOT_COMPILATION_GID ?= 65534
|
||||||
|
|
||||||
build:
|
build:
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd src/bpm; $(GO) build -ldflags "-w" -o ../../build/bpm git.enumerated.dev/bubble-package-manager/bpm/src/bpm
|
cd src/bpm; $(GO) build -ldflags "-w -X 'git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib.rootCompilationUID=$(ROOT_COMPILATION_UID)' -X 'git.enumerated.dev/bubble-package-manager/bpm/src/bpmlib.rootCompilationGID=$(ROOT_COMPILATION_GID)'" -o ../../build/bpm git.enumerated.dev/bubble-package-manager/bpm/src/bpm
|
||||||
|
|
||||||
install: build/bpm config/
|
install: build/bpm config/
|
||||||
# Create directories
|
# Create directories
|
||||||
|
@ -9,8 +9,12 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var rootCompilationUID = "65534"
|
||||||
|
var rootCompilationGID = "65534"
|
||||||
|
|
||||||
func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks bool) (err error) {
|
func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks bool) (err error) {
|
||||||
// Read BPM archive
|
// Read BPM archive
|
||||||
bpmpkg, err := ReadPackage(archiveFilename)
|
bpmpkg, err := ReadPackage(archiveFilename)
|
||||||
@ -35,6 +39,24 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get UID and GID to use for compilation
|
||||||
|
var uid, gid int
|
||||||
|
if os.Getuid() == 0 {
|
||||||
|
_uid, err := strconv.ParseInt(rootCompilationUID, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not convert UID '%s' to int", rootCompilationUID)
|
||||||
|
}
|
||||||
|
_gid, err := strconv.ParseInt(rootCompilationGID, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not convert GID '%s' to int", rootCompilationGID)
|
||||||
|
}
|
||||||
|
uid = int(_uid)
|
||||||
|
gid = int(_gid)
|
||||||
|
} else {
|
||||||
|
uid = os.Getuid()
|
||||||
|
gid = os.Getgid()
|
||||||
|
}
|
||||||
|
|
||||||
tempDirectory := path.Join(homeDir, ".cache/bpm/compilation/", bpmpkg.PkgInfo.Name)
|
tempDirectory := path.Join(homeDir, ".cache/bpm/compilation/", bpmpkg.PkgInfo.Name)
|
||||||
|
|
||||||
// Ensure temporary directory does not exist
|
// Ensure temporary directory does not exist
|
||||||
@ -51,8 +73,14 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change temporary directory owner
|
||||||
|
err = os.Chown(tempDirectory, uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Extract source.sh file
|
// Extract source.sh file
|
||||||
err = extractTarballFile(archiveFilename, "source.sh", tempDirectory)
|
err = extractTarballFile(archiveFilename, "source.sh", tempDirectory, uid, gid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -60,14 +88,14 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
// Get package scripts and extract them
|
// Get package scripts and extract them
|
||||||
packageScripts := getPackageScripts(archiveFilename)
|
packageScripts := getPackageScripts(archiveFilename)
|
||||||
for _, script := range packageScripts {
|
for _, script := range packageScripts {
|
||||||
err = extractTarballFile(archiveFilename, script, tempDirectory)
|
err = extractTarballFile(archiveFilename, script, tempDirectory, uid, gid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract source files
|
// Extract source files
|
||||||
err = extractTarballDirectory(archiveFilename, "source-files", tempDirectory)
|
err = extractTarballDirectory(archiveFilename, "source-files", tempDirectory, uid, gid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -78,6 +106,12 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change source directory owner
|
||||||
|
err = os.Chown(path.Join(tempDirectory, "source"), uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Setup environment for commands
|
// Setup environment for commands
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
env = append(env, "HOME="+tempDirectory)
|
env = append(env, "HOME="+tempDirectory)
|
||||||
@ -107,6 +141,8 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -124,13 +160,15 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove 'output' directory if it already exists
|
// Remove output directory if it already exists
|
||||||
if _, err := os.Stat(path.Join(tempDirectory, "output")); err == nil {
|
if _, err := os.Stat(path.Join(tempDirectory, "output")); err == nil {
|
||||||
err := os.RemoveAll(path.Join(tempDirectory, "output"))
|
err := os.RemoveAll(path.Join(tempDirectory, "output"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -138,12 +176,18 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new 'output' directory
|
// Create new output directory
|
||||||
err = os.Mkdir(path.Join(tempDirectory, "output"), 0755)
|
err = os.Mkdir(path.Join(tempDirectory, "output"), 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change output directory owner
|
||||||
|
err = os.Chown(path.Join(tempDirectory, "output"), uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Execute package function in source.sh script and generate package file list
|
// Execute package function in source.sh script and generate package file list
|
||||||
cmd = exec.Command("bash", "-c",
|
cmd = exec.Command("bash", "-c",
|
||||||
"set -a\n"+ // Source and export functions and variables in source.sh script
|
"set -a\n"+ // Source and export functions and variables in source.sh script
|
||||||
@ -156,6 +200,8 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -167,6 +213,8 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.Env = env
|
cmd.Env = env
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("files.tar.gz archive could not be created: %s", err)
|
return fmt.Errorf("files.tar.gz archive could not be created: %s", err)
|
||||||
@ -198,13 +246,19 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change pkg.info file owner
|
||||||
|
err = os.Chown(path.Join(tempDirectory, "pkg.info"), uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Get files to include in BPM archive
|
// Get files to include in BPM archive
|
||||||
bpmArchiveFiles := make([]string, 0)
|
bpmArchiveFiles := make([]string, 0)
|
||||||
bpmArchiveFiles = append(bpmArchiveFiles, "pkg.info", "pkg.files", "files.tar.gz") // Base files
|
bpmArchiveFiles = append(bpmArchiveFiles, "pkg.info", "pkg.files", "files.tar.gz") // Base files
|
||||||
bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts
|
bpmArchiveFiles = append(bpmArchiveFiles, packageScripts...) // Package scripts
|
||||||
|
|
||||||
// Create final BPM archive
|
// Create final BPM archive
|
||||||
cmd = exec.Command("bash", "-c", "tar -cf "+outputFilename+" --owner=0 --group=0 -C \"$BPM_WORKDIR\" "+strings.Join(bpmArchiveFiles, " "))
|
cmd = exec.Command("bash", "-c", "tar -cf final-archive.bpm --owner=0 --group=0 -C \"$BPM_WORKDIR\" "+strings.Join(bpmArchiveFiles, " "))
|
||||||
cmd.Dir = tempDirectory
|
cmd.Dir = tempDirectory
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
@ -213,11 +267,25 @@ func CompileSourcePackage(archiveFilename, outputFilename string, skipChecks boo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmd.Env = append(env, "CURRENT_DIR="+currentDir)
|
cmd.Env = append(env, "CURRENT_DIR="+currentDir)
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("BPM archive could not be created: %s", err)
|
return fmt.Errorf("BPM archive could not be created: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move final BPM archive
|
||||||
|
err = os.Rename(path.Join(tempDirectory, "final-archive.bpm"), outputFilename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set final BPM archive owner
|
||||||
|
err = os.Chown(outputFilename, os.Getuid(), os.Getgid())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,13 +466,43 @@ func (operation *BPMOperation) Execute(verbose, force bool) error {
|
|||||||
}
|
}
|
||||||
} else if action.GetActionType() == "install" {
|
} else if action.GetActionType() == "install" {
|
||||||
value := action.(*InstallPackageAction)
|
value := action.(*InstallPackageAction)
|
||||||
|
fileToInstall := value.File
|
||||||
bpmpkg := value.BpmPackage
|
bpmpkg := value.BpmPackage
|
||||||
isReinstall := IsPackageInstalled(bpmpkg.PkgInfo.Name, operation.RootDir)
|
isReinstall := IsPackageInstalled(bpmpkg.PkgInfo.Name, operation.RootDir)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
// Compile package if type is 'source'
|
||||||
|
if bpmpkg.PkgInfo.Type == "source" {
|
||||||
|
// Get path to compiled package directory and output filename
|
||||||
|
compiledDir := path.Join(operation.RootDir, "/var/lib/bpm/compiled/")
|
||||||
|
outputFilename := path.Join(compiledDir, fmt.Sprintf("%s-%s-%d.bpm", bpmpkg.PkgInfo.Name, bpmpkg.PkgInfo.Version, bpmpkg.PkgInfo.Revision))
|
||||||
|
|
||||||
|
// Create compiled package directory if not exists
|
||||||
|
if _, err := os.Stat(compiledDir); err != nil {
|
||||||
|
err := os.MkdirAll(compiledDir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile source package
|
||||||
|
err = CompileSourcePackage(value.File, outputFilename, false)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not compile source package (%s): %s\n", value.File, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set values
|
||||||
|
fileToInstall = outputFilename
|
||||||
|
bpmpkg, err = ReadPackage(outputFilename)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not read package (%s): %s\n", fileToInstall, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if value.IsDependency {
|
if value.IsDependency {
|
||||||
err = installPackage(value.File, operation.RootDir, verbose, true)
|
err = installPackage(fileToInstall, operation.RootDir, verbose, true)
|
||||||
} else {
|
} else {
|
||||||
err = installPackage(value.File, operation.RootDir, verbose, force)
|
err = installPackage(fileToInstall, operation.RootDir, verbose, force)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err))
|
return errors.New(fmt.Sprintf("could not install package (%s): %s\n", bpmpkg.PkgInfo.Name, err))
|
||||||
|
@ -607,6 +607,12 @@ func installPackage(filename, rootDir string, verbose, force bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure package type is 'binary'
|
||||||
|
if bpmpkg.PkgInfo.Type != "binary" {
|
||||||
|
return fmt.Errorf("can only extract binary packages")
|
||||||
|
}
|
||||||
|
|
||||||
packageInstalled := IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir)
|
packageInstalled := IsPackageInstalled(bpmpkg.PkgInfo.Name, rootDir)
|
||||||
// Check if package is installed and remove current files
|
// Check if package is installed and remove current files
|
||||||
if packageInstalled {
|
if packageInstalled {
|
||||||
@ -712,15 +718,10 @@ func installPackage(filename, rootDir string, verbose, force bool) error {
|
|||||||
fmt.Printf("Extracting files for package (%s)...\n", bpmpkg.PkgInfo.Name)
|
fmt.Printf("Extracting files for package (%s)...\n", bpmpkg.PkgInfo.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if bpmpkg.PkgInfo.Type == "binary" {
|
// Extract package files into rootDir
|
||||||
err := extractPackage(bpmpkg, verbose, filename, rootDir)
|
err = extractPackage(bpmpkg, verbose, filename, rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
} else if bpmpkg.PkgInfo.Type == "source" {
|
|
||||||
return errors.New("direct source package compilation in BPM has been temporarily removed and is being reworked on")
|
|
||||||
} else {
|
|
||||||
return errors.New("unknown package type: " + bpmpkg.PkgInfo.Type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
installedDir := path.Join(rootDir, "var/lib/bpm/installed/")
|
||||||
|
@ -72,7 +72,7 @@ func readTarballFile(tarballPath, fileToExtract string) (*tarballFileReader, err
|
|||||||
return nil, errors.New("could not file in tarball")
|
return nil, errors.New("could not file in tarball")
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTarballFile(tarballPath, fileToExtract string, workingDirectory string) (err error) {
|
func extractTarballFile(tarballPath, fileToExtract string, workingDirectory string, uid, gid int) (err error) {
|
||||||
file, err := os.Open(tarballPath)
|
file, err := os.Open(tarballPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -109,6 +109,12 @@ func extractTarballFile(tarballPath, fileToExtract string, workingDirectory stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if uid >= 0 && gid >= 0 {
|
||||||
|
err = file.Chown(uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Copy data to file
|
// Copy data to file
|
||||||
_, err = io.Copy(file, tr)
|
_, err = io.Copy(file, tr)
|
||||||
@ -126,7 +132,7 @@ func extractTarballFile(tarballPath, fileToExtract string, workingDirectory stri
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTarballDirectory(tarballPath, directoryToExtract, workingDirectory string) (err error) {
|
func extractTarballDirectory(tarballPath, directoryToExtract, workingDirectory string, uid, gid int) (err error) {
|
||||||
file, err := os.Open(tarballPath)
|
file, err := os.Open(tarballPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -160,6 +166,14 @@ func extractTarballDirectory(tarballPath, directoryToExtract, workingDirectory s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set directory owner
|
||||||
|
if uid >= 0 && gid >= 0 {
|
||||||
|
err = os.Chown(outputPath, uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
case tar.TypeReg:
|
case tar.TypeReg:
|
||||||
// Create file and set permissions
|
// Create file and set permissions
|
||||||
file, err = os.Create(outputPath)
|
file, err = os.Create(outputPath)
|
||||||
@ -170,6 +184,12 @@ func extractTarballDirectory(tarballPath, directoryToExtract, workingDirectory s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if uid >= 0 && gid >= 0 {
|
||||||
|
err = file.Chown(uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Copy data to file
|
// Copy data to file
|
||||||
_, err = io.Copy(file, tr)
|
_, err = io.Copy(file, tr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user