Compare commits

..

10 Commits

3 changed files with 255 additions and 199 deletions

View File

@@ -1,17 +1,19 @@
package main package main
import ( import (
"bufio"
"database/sql" "database/sql"
_ "embed" _ "embed"
"fmt" "fmt"
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings"
"sync" "sync"
"packets/configs" "packets/configs"
"packets/internal/consts" "packets/internal/consts"
errors_packets "packets/internal/errors"
"packets/internal/utils" "packets/internal/utils"
packets "packets/pkg" packets "packets/pkg"
@@ -85,6 +87,8 @@ func init() {
log.Fatal(err) log.Fatal(err)
} }
} }
_ = os.MkdirAll("/var/lib/packets", 0777)
} }
// COBRA CMDS // COBRA CMDS
@@ -101,11 +105,10 @@ var syncCmd = &cobra.Command{
log.Fatal("index.db does not exist, try to use \"packets sync\"") log.Fatal("index.db does not exist, try to use \"packets sync\"")
} }
} }
f, err := os.OpenFile(consts.IndexDB, os.O_WRONLY, 0)
if err != nil { if os.Getuid() != 0 {
log.Fatalf("can't open to write [ %s ]. Are you running packets as root?\n", consts.IndexDB) log.Fatal("are you running packets as root?")
} }
f.Close()
syncUrl := consts.DefaultSyncUrl syncUrl := consts.DefaultSyncUrl
if len(args) > 0 { if len(args) > 0 {
@@ -160,13 +163,12 @@ var installCmd = &cobra.Command{
} }
for _, inputName := range args { for _, inputName := range args {
runtime.GC()
var exist bool var exist bool = false
err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM packages WHERE name = ?)", inputName).Scan(&exist) err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM packages WHERE id = ?)", inputName).Scan(&exist)
if err != nil { if err != nil {
if err != sql.ErrNoRows { log.Fatal(err)
log.Panic(err)
}
} }
if exist { if exist {
installed, err := utils.CheckIfPackageInstalled(inputName) installed, err := utils.CheckIfPackageInstalled(inputName)
@@ -174,7 +176,7 @@ var installCmd = &cobra.Command{
log.Fatal(err) log.Fatal(err)
} }
if installed { if installed {
log.Printf("package %s is already installed\n", inputName) fmt.Printf("Package %s is already installed\n", inputName)
continue continue
} }
fmt.Printf("Checking dependencies of (%s)\n", inputName) fmt.Printf("Checking dependencies of (%s)\n", inputName)
@@ -201,7 +203,7 @@ var installCmd = &cobra.Command{
} }
for _, depn := range dependencies { for _, depn := range dependencies {
wg.Add(1) wg.Add(1)
go AyncFullInstall(depn, cfg.Config.StorePackages, filepath.Join(cfg.Config.Data_d, inputName), &wg, &mu) go AyncFullInstall(depn, cfg.Config.StorePackages, filepath.Join(cfg.Config.Data_d, depn), &wg, &mu)
} }
wg.Wait() wg.Wait()
@@ -237,193 +239,92 @@ var installCmd = &cobra.Command{
continue continue
} }
var id string
err = db.QueryRow("SELECT id FROM packages WHERE query_name = ? ORDER BY serial DESC LIMIT 1", inputName).Scan(&id)
if err != nil {
if err == sql.ErrNoRows {
log.Panicf("can't find any results for (%s)\n", inputName)
}
log.Fatal(err)
}
rows, err := db.Query("SELECT id, version, description FROM packages WHERE query_name = ?", inputName) installed, err := utils.CheckIfPackageInstalled(inputName)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer rows.Close() if installed {
fmt.Printf(":: Package %s is already installed, searching for upgrades...\n", inputName)
var pkgs []Quer1 var wg sync.WaitGroup
for rows.Next() { wg.Add(1)
var q Quer1 go AsyncFullyUpgrade(inputName, cfg.Config.StorePackages, filepath.Join(cfg.Config.Data_d, id), &wg, db)
if err := rows.Scan(&q.Name, &q.Version, &q.Description); err != nil { wg.Done()
log.Panic(err)
}
pkgs = append(pkgs, q)
}
switch len(pkgs) {
case 0:
log.Fatalf("can't find any results for (%s)\n", inputName)
case 1:
fmt.Printf(":: Founded 1 package for %s \n", inputName)
installed, err := utils.CheckIfPackageInstalled(pkgs[0].Name)
if err != nil {
log.Fatal(err)
}
if installed {
log.Printf("Package %s is already installed\n", pkgs[0].Name)
continue
}
fmt.Printf("Checking dependencies of (%s)\n", pkgs[0].Name)
dependenciesRaw, err := utils.GetDependencies(db, inputName)
if err != nil {
log.Fatal(err)
}
dependencies, err := utils.ResolvDependencies(dependenciesRaw)
if err != nil {
log.Fatal(err)
}
if len(dependencies) > 0 {
var wg sync.WaitGroup
var mu sync.Mutex
fmt.Printf(":: Packets will install %s and %d dependencies\nPackages to install:\n", pkgs[0].Name, len(dependencies))
fmt.Println(dependencies)
fmt.Println("Are you sure? (y/N)")
var a string
fmt.Scanf("%s", &a)
if a != "y" && a != "Y" {
os.Exit(1)
}
for _, depn := range dependencies {
wg.Add(1)
go AyncFullInstall(depn, cfg.Config.StorePackages, filepath.Join(cfg.Config.Data_d, inputName), &wg, &mu)
}
wg.Wait()
}
fmt.Printf("Downloading %s \n", pkgs[0].Name)
p, err := utils.GetPackage(pkgs[0].Name)
if err != nil {
log.Fatal(err)
}
cfg, err := configs.GetConfigTOML()
if err != nil {
log.Fatal(err)
}
fmt.Printf(":: Installing %s \n", pkgs[0].Name)
if err := packets.InstallPackage(p.PackageF, filepath.Join(cfg.Config.Data_d, pkgs[0].Name)); err != nil {
log.Fatal(err)
}
if cfg.Config.StorePackages {
_, err := p.Write()
if err != nil {
log.Fatal(err)
}
err = p.AddToInstalledDB(1, filepath.Join(cfg.Config.Data_d, pkgs[0].Name))
if err != nil {
log.Fatal(err)
}
} else {
err := p.AddToInstalledDB(0, filepath.Join(cfg.Config.Data_d, pkgs[0].Name))
if err != nil {
log.Fatal(err)
}
}
continue
default:
fmt.Printf(":: Founded %d packages for (%s)\n Select 1 to install\n", len(pkgs), inputName)
for i, q := range pkgs {
fmt.Printf("[%d] %s : %s\n %s\n", i, q.Name, q.Version, q.Description)
}
var choice int
optionagain:
fmt.Print(">> ")
fmt.Fscan(bufio.NewReader(os.Stdin), &choice)
if choice > len(pkgs) || choice < 0 {
fmt.Println("invalid option")
goto optionagain
}
installed, err := utils.CheckIfPackageInstalled(pkgs[choice].Name)
if err != nil {
log.Fatal(err)
}
if installed {
log.Printf("package %s is already installed\n", pkgs[choice].Name)
continue
}
fmt.Printf("Checking dependencies of (%s)\n", pkgs[choice].Name)
dependenciesRaw, err := utils.GetDependencies(db, inputName)
if err != nil {
log.Fatal(err)
}
dependencies, err := utils.ResolvDependencies(dependenciesRaw)
if err != nil {
log.Fatal(err)
}
if len(dependencies) > 0 {
var wg sync.WaitGroup
var mu sync.Mutex
fmt.Printf(":: Packets will install %s and %d dependencies\nPackages to install:\n", pkgs[choice].Name, len(dependencies))
fmt.Println(dependencies)
fmt.Println("Are you sure? (y/N)")
var a string
fmt.Scanf("%s", &a)
if a != "y" && a != "Y" {
os.Exit(1)
}
for _, depn := range dependencies {
wg.Add(1)
go AyncFullInstall(depn, cfg.Config.StorePackages, filepath.Join(cfg.Config.Data_d, pkgs[choice].Name), &wg, &mu)
}
wg.Wait()
}
fmt.Printf("Downloading %s \n", pkgs[choice].Name)
p, err := utils.GetPackage(pkgs[choice].Name)
if err != nil {
log.Fatal(err)
}
cfg, err := configs.GetConfigTOML()
if err != nil {
log.Fatal(err)
}
fmt.Printf(":: Installing (%s) \n", pkgs[choice].Name)
if err := packets.InstallPackage(p.PackageF, filepath.Join(cfg.Config.Data_d, pkgs[choice].Name)); err != nil {
log.Fatal(err)
}
if cfg.Config.StorePackages {
_, err := p.Write()
if err != nil {
log.Fatal(err)
}
err = p.AddToInstalledDB(1, filepath.Join(cfg.Config.Data_d, pkgs[choice].Name))
if err != nil {
log.Fatal(err)
}
} else {
err := p.AddToInstalledDB(0, filepath.Join(cfg.Config.Data_d, pkgs[choice].Name))
if err != nil {
log.Fatal(err)
}
}
continue continue
} }
fmt.Printf("Checking dependencies of (%s)\n", inputName)
dependenciesRaw, err := utils.GetDependencies(db, id)
if err != nil {
log.Fatal(err)
}
dependencies, err := utils.ResolvDependencies(dependenciesRaw)
if err != nil {
log.Fatal(err)
}
if len(dependencies) > 0 {
var wg sync.WaitGroup
var mu sync.Mutex
fmt.Printf(":: Packets will install %s and %d dependencies\nPackages to install:\n", id, len(dependencies))
fmt.Println(dependencies)
fmt.Println("Are you sure? (y/N)")
var a string
fmt.Scanf("%s", &a)
if a != "y" && a != "Y" {
os.Exit(1)
}
for _, depn := range dependencies {
wg.Add(1)
go AyncFullInstall(depn, cfg.Config.StorePackages, filepath.Join(cfg.Config.Data_d, depn), &wg, &mu)
}
wg.Wait()
}
fmt.Printf("Downloading %s \n", inputName)
p, err := utils.GetPackage(id)
if err != nil {
log.Fatal(err)
}
cfg, err := configs.GetConfigTOML()
if err != nil {
log.Fatal(err)
}
fmt.Printf(":: Installing %s \n", inputName)
if err := packets.InstallPackage(p.PackageF, filepath.Join(cfg.Config.Data_d, id)); err != nil {
log.Fatal(err)
}
if cfg.Config.StorePackages {
_, err := p.Write()
if err != nil {
log.Fatal(err)
}
err = p.AddToInstalledDB(1, filepath.Join(cfg.Config.Data_d, id))
if err != nil {
log.Fatal(err)
}
} else {
err := p.AddToInstalledDB(0, filepath.Join(cfg.Config.Data_d, id))
if err != nil {
log.Fatal(err)
}
}
continue
} }
}, },
} }
@@ -483,11 +384,12 @@ var removeCmd = &cobra.Command{
} }
fmt.Println("Sucessifully removed") fmt.Println("Sucessifully removed")
continue
os.Exit(0)
} }
log.Fatalf("%s not installed", pkgName) log.Fatalf("%s not installed", pkgName)
} }
os.Exit(0)
}, },
} }
@@ -570,12 +472,60 @@ var searchCmd = &cobra.Command{
}, },
} }
var upgradeCmd = &cobra.Command{
Use: "upgrade",
Args: cobra.NoArgs,
Short: "upgrade all installed packages",
Run: func(cmd *cobra.Command, args []string) {
if os.Getuid() != 0 {
log.Fatal("you must run this command as root")
}
cfg, err := configs.GetConfigTOML()
if err != nil {
log.Fatal(err)
}
db, err := sql.Open("sqlite", consts.InstalledDB)
if err != nil {
log.Fatal(err)
}
defer db.Close()
rows, err := db.Query("SELECT query_name FROM packages")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
var installedPackagesQName []string
for rows.Next() {
var queryName string
if err := rows.Scan(&queryName); err != nil {
log.Fatal(err)
}
installedPackagesQName = append(installedPackagesQName, queryName)
}
var wg sync.WaitGroup
for _, v := range installedPackagesQName {
wg.Add(1)
go AsyncFullyUpgrade(v, cfg.Config.StorePackages, cfg.Config.Data_d, &wg, db)
}
wg.Wait()
},
}
func main() { func main() {
rootCmd.AddCommand(installCmd) rootCmd.AddCommand(installCmd)
rootCmd.AddCommand(removeCmd) rootCmd.AddCommand(removeCmd)
rootCmd.AddCommand(syncCmd) rootCmd.AddCommand(syncCmd)
rootCmd.AddCommand(listCmd) rootCmd.AddCommand(listCmd)
rootCmd.AddCommand(searchCmd) rootCmd.AddCommand(searchCmd)
rootCmd.AddCommand(upgradeCmd)
rootCmd.Execute() rootCmd.Execute()
} }
@@ -619,3 +569,99 @@ func AyncFullInstall(dep string, storePackages bool, installPath string, wg *syn
} }
} }
} }
func AsyncFullyUpgrade(queryName string, storePackages bool, installDir string, wg *sync.WaitGroup, db *sql.DB) {
defer wg.Done()
installed, err := utils.CheckIfPackageInstalled(queryName)
if err != nil {
log.Println(err)
return
}
if !installed {
log.Println(errors_packets.ErrNotInstalled)
return
}
idb, err := sql.Open("sqlite", consts.InstalledDB)
if err != nil {
log.Panic(err)
return
}
var oldSerial int
if err := idb.QueryRow("SELECT serial FROM packages WHERE query_name = ?", queryName).Scan(&oldSerial); err != nil {
log.Println(err)
return
}
var newSerial int
var id string
if err := db.QueryRow("SELECT serial, id FROM packages WHERE query_name = ? ORDER BY serial DESC LIMIT 1", queryName).Scan(&newSerial, &id); err != nil {
log.Println(err)
return
}
installPath := filepath.Join(installDir, id)
if oldSerial == newSerial {
log.Println(errors_packets.ErrAlredyUpToDate)
return
}
var v int
if storePackages {
v = 1
} else {
v = 0
}
if err := UpgradeToThis(id, installPath, idb, v); err != nil {
log.Println(err)
return
}
}
func UpgradeToThis(id string, installPath string, installedDB *sql.DB, storePkgFile int) error {
p, err := utils.GetPackage(id)
if err != nil {
return err
}
query_name := strings.SplitN(id, "@", 2)[0]
var oldPath string
if err := installedDB.QueryRow("SELECT package_d FROM packages WHERE query_name = ?", query_name).Scan(&oldPath); err != nil {
return err
}
if err := os.Rename(oldPath, installPath); err != nil {
return err
}
if err := packets.InstallPackage(p.PackageF, installPath); err != nil {
if err := os.Rename(installPath, oldPath); err != nil {
return err
}
return err
}
_, err = installedDB.Exec(`
UPDATE packages
SET query_name = ?, id = ?, version = ?, description = ?,
serial = ?, package_d = ?, filename = ?, os = ?, arch = ?, in_cache = ?
`,
p.QueryName,
p.Manifest.Info.Id,
p.Version,
p.Description,
p.Serial,
installPath,
p.Filename,
p.OS,
p.Arch,
storePkgFile,
)
if err != nil {
return err
}
return nil
}

View File

@@ -6,4 +6,6 @@ var (
ErrResponseNot200OK = errors.New("the request is not 200, download failed") ErrResponseNot200OK = errors.New("the request is not 200, download failed")
ErrCantFindManifestTOML = errors.New("can't find manifest.toml when trying to read the packagefile") ErrCantFindManifestTOML = errors.New("can't find manifest.toml when trying to read the packagefile")
ErrInvalidSignature = errors.New("the signature is invalid") ErrInvalidSignature = errors.New("the signature is invalid")
ErrNotInstalled = errors.New("the package isn't installed")
ErrAlredyUpToDate = errors.New("alredy up to date")
) )

View File

@@ -252,8 +252,12 @@ func CheckIfPackageInstalled(name string) (bool, error) {
} }
defer db.Close() defer db.Close()
if strings.Contains(name, "@") {
name = strings.SplitN(name, "@", 2)[0]
}
var exists bool var exists bool
err = db.QueryRow("SELECT EXISTS(SELECT 1 FROM packages WHERE id = ? OR query_name = ?)", name, name).Scan(&exists) err = db.QueryRow("SELECT EXISTS(SELECT 1 FROM packages WHERE query_name = ?)", name).Scan(&exists)
if err != nil { if err != nil {
return false, err return false, err
} }
@@ -284,6 +288,7 @@ func GetDependencies(db *sql.DB, id string) (map[string]string, error) {
} }
func ResolvDependencies(depnList map[string]string) ([]string, error) { func ResolvDependencies(depnList map[string]string) ([]string, error) {
db, err := sql.Open("sqlite", consts.IndexDB) db, err := sql.Open("sqlite", consts.IndexDB)
if err != nil { if err != nil {
return []string{}, err return []string{}, err
@@ -299,13 +304,13 @@ func ResolvDependencies(depnList map[string]string) ([]string, error) {
switch { switch {
case strings.HasPrefix(constraint, ">"): case strings.HasPrefix(constraint, ">"):
filter = fmt.Sprintf("AND serial > %s", value) filter = fmt.Sprintf("AND serial > %s", value)
order = "ORDER BY serial ASC LIMIT 1" order = "ORDER BY serial DESC LIMIT 1"
case strings.HasPrefix(constraint, "<="): case strings.HasPrefix(constraint, "<="):
filter = fmt.Sprintf("AND serial <= %s", value) filter = fmt.Sprintf("AND serial <= %s", value)
order = "ORDER BY serial DESC LIMIT 1" order = "ORDER BY serial ASC LIMIT 1"
case strings.HasPrefix(constraint, "<"): case strings.HasPrefix(constraint, "<"):
filter = fmt.Sprintf("AND serial < %s", value) filter = fmt.Sprintf("AND serial < %s", value)
order = "ORDER BY serial DESC LIMIT 1" order = "ORDER BY serial ASC LIMIT 1"
case strings.HasPrefix(constraint, "="): case strings.HasPrefix(constraint, "="):
filter = fmt.Sprintf("AND serial = %s", value) filter = fmt.Sprintf("AND serial = %s", value)
order = "" order = ""
@@ -322,7 +327,6 @@ func ResolvDependencies(depnList map[string]string) ([]string, error) {
} }
resolved = append(resolved, packageId) resolved = append(resolved, packageId)
dp, err := GetDependencies(db, packageId) dp, err := GetDependencies(db, packageId)
if err != nil { if err != nil {
return resolved, err return resolved, err
@@ -368,6 +372,7 @@ func RemoveFromInstalledDB(id string) error {
func GetPackage(id string) (Package, error) { func GetPackage(id string) (Package, error) {
var this Package var this Package
this.Dependencies = make(map[string]string)
var peers []Peer var peers []Peer
db, err := sql.Open("sqlite", consts.IndexDB) db, err := sql.Open("sqlite", consts.IndexDB)
@@ -437,6 +442,7 @@ func GetPackage(id string) (Package, error) {
} }
if len(peers) == 0 { if len(peers) == 0 {
fmt.Printf(":: Pulling from %s\n", packageUrl)
this.PackageF, err = GetFileHTTP(packageUrl) this.PackageF, err = GetFileHTTP(packageUrl)
if err != nil { if err != nil {
return Package{}, err return Package{}, err
@@ -444,6 +450,7 @@ func GetPackage(id string) (Package, error) {
} else { } else {
var totalerrors int = 0 var totalerrors int = 0
for _, peer := range peers { for _, peer := range peers {
fmt.Printf(":: Pulling from local network (%s)\n", peer.IP)
this.PackageF, err = GetFileHTTP(fmt.Sprintf("http://%s:%d/%s", peer.IP, peer.Port, filename)) this.PackageF, err = GetFileHTTP(fmt.Sprintf("http://%s:%d/%s", peer.IP, peer.Port, filename))
if err == nil { if err == nil {
break break
@@ -475,7 +482,7 @@ skipping:
} }
func GetPacketsUID() (int, error) { func GetPacketsUID() (int, error) {
_ = exec.Command("useradd", "-M", "-N", "-r", "packets").Run() _ = exec.Command("useradd", "-M", "-N", "-r", "-s", "/bin/false", "-d", "/var/lib/packets", "packets").Run()
cmd := exec.Command("id", "-u", "packets") cmd := exec.Command("id", "-u", "packets")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
@@ -496,6 +503,7 @@ func ChangeToNoPermission() error {
if err != nil { if err != nil {
return err return err
} }
_ = os.Chown("/var/lib/packets", uid, 0)
return syscall.Setresuid(0, uid, 0) return syscall.Setresuid(0, uid, 0)