diff --git a/cmd/http/httpsocket.go b/cmd/http/httpsocket.go new file mode 100644 index 0000000..1fbff15 --- /dev/null +++ b/cmd/http/httpsocket.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "os" + + "github.com/BurntSushi/toml" +) + +type ConfigTOML struct { + Config struct { + DefaultHttpPort int `toml:"httpPort"` + DefaultCacheDir string `toml:"cacheDir"` + } `toml:"Config"` +} + +func main() { + var cfg ConfigTOML + toml.Decode("opt/packets/packets/config.toml", &cfg) + + pid := os.Getpid() + if err := os.WriteFile("./http.pid", []byte(fmt.Sprint(pid)), 0644); err != nil { + fmt.Println("error saving subprocess pid", err) + } + + fs := http.FileServer(http.Dir(cfg.Config.DefaultCacheDir)) + http.Handle("/", fs) + + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.Config.DefaultHttpPort), nil)) +} diff --git a/cmd/packets/main.go b/cmd/packets/main.go new file mode 100644 index 0000000..e208c1a --- /dev/null +++ b/cmd/packets/main.go @@ -0,0 +1,1267 @@ +//go:build linux + +package main + +import ( + "archive/tar" + "bufio" + "crypto/sha256" + "database/sql" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "log" + "net" + "net/http" + "net/url" + "os" + "os/exec" + "path" + "path/filepath" + "strconv" + "strings" + "syscall" + "time" + + "github.com/BurntSushi/toml" + "github.com/schollz/progressbar/v3" + "golang.org/x/net/ipv4" + _ "modernc.org/sqlite" + + "github.com/ulikunitz/xz" +) + +type ConfigTOML struct { + Config struct { + HttpPort int `toml:"httpPort"` + CacheDir string `toml:"cacheDir"` + AutoDeleteCacheDir bool `toml:"dayToDeleteCacheDir"` + DaysToDelete int `toml:"daysToDelete"` + DataDir string `toml:"dataDir"` + } `toml:"Config"` +} + +type IndexTOML struct { + Name string `toml:"name"` + Version string `toml:"version"` + Author string `toml:"author"` + Description string `toml:"description"` + CreatedAt time.Time `toml:"createdAt"` +} + +type CountingReader struct { + R io.Reader + Total int64 +} + +func (c *CountingReader) Read(p []byte) (int, error) { + n, err := c.R.Read(p) + c.Total += int64(n) + return n, err +} + +type Installed struct { + Realname string + Version string + Dependencies []string + Family string + Serial uint +} + +type Peer struct { + IP net.IP + Port int +} + +type Quer1 struct { + Realname string + Version string + Description string +} + +type Manifest struct { + Name string `json:"name"` + Version string `json:"version"` + Description string `json:"description"` + Dependencies []string `json:"dependencies"` + Author string `json:"author"` + Family string `json:"family"` + Serial uint `json:"serial"` +} + +var serialPass uint +var cfg ConfigTOML +var PacketsDir string + +func main() { + + out, _ := exec.Command("uname", "-s").Output() + if uname := strings.TrimSpace(string(out)); uname == "OpenTTY" { + PacketsDir = "/mnt/packets" + } else { + PacketsDir = "/etc/packets" + } + _, err := os.Stat(filepath.Join(PacketsDir, "config.toml")) + if os.IsNotExist(err) { + fmt.Println("can't find config.toml, generating a default one") + + cfg.Config.HttpPort = 9123 + cfg.Config.AutoDeleteCacheDir = false + cfg.Config.CacheDir = "/var/cache/packets" + cfg.Config.DataDir = "/opt/packets" + cfg.Config.DaysToDelete = -1 + + os.MkdirAll(PacketsDir, 0644) + file, err := os.Create(filepath.Join(PacketsDir, "config.toml")) + if err != nil { + + log.Fatal(err) + } + defer file.Close() + + encoder := toml.NewEncoder(file) + + if err := encoder.Encode(cfg); err != nil { + + log.Fatal(err) + } + fmt.Println("Operation Sucess!") + } + + _, err = toml.DecodeFile(filepath.Join(PacketsDir, "config.toml"), &cfg) + if err != nil { + log.Fatal(err) + } + + if len(os.Args) < 2 { + fmt.Println("invalid syntax") + return + } + + cmd := os.Args[1] + + switch cmd { + case "install": + if os.Getuid() != 0 { + fmt.Println("please, run as root") + return + } + + if len(os.Args) < 3 { + fmt.Println("usage: packets install ") + return + } + + db, err := sql.Open("sqlite", filepath.Join(PacketsDir, "index.db")) + if err != nil { + log.Fatal(err) + return + } + defer db.Close() + + nameToQuery := os.Args[2] + var exist bool + db.QueryRow("SELECT EXISTS(SELECT 1 FROM packages WHERE realname = ? LIMIT 1)", nameToQuery).Scan(&exist) + if exist { + QueryInstall(nameToQuery) + return + } + + rows, err := db.Query("SELECT realname, version, description FROM packages WHERE name = ?", nameToQuery) + if err != nil { + if strings.Contains(err.Error(), "file is not a database (26)") { + fmt.Println("index.db corrupted") + return + } + log.Panic(err) + return + } + + defer rows.Close() + + var pkgs []Quer1 + for rows.Next() { + var q Quer1 + if err := rows.Scan(&q.Realname, &q.Version, &q.Description); err != nil { + log.Fatal(err) + } + pkgs = append(pkgs, q) + } + switch len(pkgs) { + case 0: + fmt.Printf("can't find any results for %s\n", nameToQuery) + return + case 1: + fmt.Printf("Founded 1 package for %s \n", nameToQuery) + + fmt.Printf("Downloading %s \n", pkgs[0].Realname) + QueryInstall(pkgs[0].Realname) + return + + default: + fmt.Printf("Found %d versions of %s\n Select 1\n", len(pkgs), nameToQuery) + for i, q := range pkgs { + fmt.Printf("[%d] %s : %s\n %s\n", i, q.Realname, q.Version, q.Description) + } + var choice int + + fmt.Fscan(bufio.NewReader(os.Stdin), &choice) + if choice > len(pkgs) || choice < 0 { + fmt.Println("invalid option") + return + } + + QueryInstall(pkgs[choice].Realname) + return + } + + case "serve": + if os.Getuid() != 0 { + fmt.Println("please, run as root") + return + } + + if len(os.Args) < 3 { + fmt.Println("usage: packets serve