From f3ccd6d68310769a881099c6fe3e700033730db4 Mon Sep 17 00:00:00 2001 From: roboogg133 Date: Sat, 13 Sep 2025 22:57:52 -0300 Subject: [PATCH] Clean Install function and Download function --- cmd/packets/main.go | 86 ++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ internal/internal.go | 73 +++++++++++++++++++++++++++++++++++++ 4 files changed, 162 insertions(+) diff --git a/cmd/packets/main.go b/cmd/packets/main.go index 7b9ddcf..c14322c 100644 --- a/cmd/packets/main.go +++ b/cmd/packets/main.go @@ -1,15 +1,19 @@ package main import ( + "archive/tar" "database/sql" "errors" "fmt" + "io" "log" "os" "packets/internal" "path/filepath" + "strings" "time" + "github.com/klauspost/compress/zstd" "github.com/pelletier/go-toml/v2" "github.com/spf13/cobra" _ "modernc.org/sqlite" @@ -97,6 +101,88 @@ func init() { } } +// Install exctract and install from a package file +func Install(file *os.File) error { + + manifest, err := internal.ReadManifest(file) + if err != nil { + return err + } + + name := &manifest.Info.Name + + configuration, err := internal.GetConfigTOML() + if err != nil { + return err + } + + destDir := filepath.Join(configuration.Config.Data_d, *name) + + zstdReader, err := zstd.NewReader(file) + if err != nil { + return err + } + defer zstdReader.Close() + + tarReader := tar.NewReader(zstdReader) + + for { + hdr, err := tarReader.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + rel := filepath.Clean(hdr.Name) + + if rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) { + continue + } + + if err := os.MkdirAll(destDir, 0755); err != nil { + return err + } + + absPath := filepath.Join(destDir, rel) + + switch hdr.Typeflag { + + case tar.TypeDir: + err = os.MkdirAll(absPath, os.FileMode(hdr.Mode)) + + if err != nil { + return err + } + + case tar.TypeReg: + err = os.MkdirAll(filepath.Dir(absPath), 0755) + if err != nil { + return err + } + + out, err := os.Create(absPath) + if err != nil { + return err + } + + _, err = io.Copy(out, tarReader) + out.Close() + if err != nil { + return err + } + + err = os.Chmod(absPath, os.FileMode(hdr.Mode)) + if err != nil { + return err + } + } + } + + return nil +} + // COBRA CMDS var rootCmd = &cobra.Command{Use: "packets"} diff --git a/go.mod b/go.mod index 371f8c3..d0f9cd2 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module packets go 1.25.1 require ( + github.com/klauspost/compress v1.18.0 github.com/pelletier/go-toml/v2 v2.2.4 github.com/spf13/cobra v1.10.1 github.com/yuin/gopher-lua v1.1.1 diff --git a/go.sum b/go.sum index 11a25b1..587d32a 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= diff --git a/internal/internal.go b/internal/internal.go index da86e33..6adf057 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -1,11 +1,16 @@ package internal import ( + "archive/tar" "errors" "io" "log" "net/http" "os" + "path/filepath" + + "github.com/klauspost/compress/zstd" + "github.com/pelletier/go-toml/v2" ) // const @@ -17,6 +22,25 @@ const DefaultData_d = "/opt/packets" // errors var ErrResponseNot200OK = errors.New("the request is not 200, download failed") +var ErrCantFindManifestTOML = errors.New("can't find manifest.toml when trying to read the packagefile") + +// toml files + +type Manifest struct { + Info struct { + Name string `toml:"name"` + Version string `toml:"version"` + Description string `toml:"description"` + Dependencies []string `toml:"dependencies"` + Author string `toml:"author"` + Family string `toml:"family"` + Serial uint `toml:"serial"` + } `toml:"Info"` + Hooks struct { + Install string `toml:"install"` + Remove string `toml:"remove"` + } `toml:"Hooks"` +} type ConfigTOML struct { Config struct { @@ -77,3 +101,52 @@ func DefaultConfigTOML() (*ConfigTOML, error) { return &config, nil } + +func ReadManifest(file *os.File) (*Manifest, error) { + zstdReader, err := zstd.NewReader(file) + if err != nil { + return nil, err + } + defer zstdReader.Close() + + tarReader := tar.NewReader(zstdReader) + for { + header, err := tarReader.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + + if filepath.Base(header.Name) == "manifest.toml" { + decoder := toml.NewDecoder(tarReader) + + var manifest Manifest + + if err := decoder.Decode(&manifest); err != nil { + log.Fatal(err) + } + + return &manifest, nil + } + + } + return nil, ErrCantFindManifestTOML +} + +func GetConfigTOML() (*ConfigTOML, error) { + f, err := os.Open(filepath.Join(DefaultLinux_d, "config.toml")) + if err != nil { + return nil, err + } + + decoder := toml.NewDecoder(f) + + var config ConfigTOML + if err := decoder.Decode(&config); err != nil { + return nil, err + } + + return &config, nil +}