better file organization
This commit is contained in:
@@ -1,58 +1,25 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/tar"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"packets/internal"
|
"packets/configs"
|
||||||
|
"packets/internal/consts"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/klauspost/compress/zstd"
|
|
||||||
"github.com/pelletier/go-toml/v2"
|
"github.com/pelletier/go-toml/v2"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
_ "modernc.org/sqlite"
|
_ "modernc.org/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Consts
|
|
||||||
|
|
||||||
const DefaultLinux_d = "/etc/packets"
|
|
||||||
const LANDeadline = 2 * time.Second
|
|
||||||
|
|
||||||
// Errors
|
|
||||||
|
|
||||||
var ErrResponseNot200OK = errors.New("the request is not 200, download failed")
|
|
||||||
|
|
||||||
// Types
|
|
||||||
|
|
||||||
type ConfigTOML struct {
|
|
||||||
Config struct {
|
|
||||||
HttpPort int `toml:"httpPort"`
|
|
||||||
Cache_d string `toml:"cache_d"`
|
|
||||||
Data_d string `toml:"data_d"`
|
|
||||||
Bin_d string `toml:"bin_d"`
|
|
||||||
} `toml:"Config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Peer struct {
|
|
||||||
IP net.IP
|
|
||||||
Port int
|
|
||||||
}
|
|
||||||
|
|
||||||
// init is doing some verifications
|
// init is doing some verifications
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
_, err := os.Stat(DefaultLinux_d)
|
_, err := os.Stat(consts.DefaultLinux_d)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
err := os.Mkdir(DefaultLinux_d, 0644)
|
err := os.Mkdir(consts.DefaultLinux_d, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsPermission(err) {
|
if os.IsPermission(err) {
|
||||||
fmt.Println("can't create packets root directory, please run as root")
|
fmt.Println("can't create packets root directory, please run as root")
|
||||||
@@ -63,7 +30,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = os.Stat(filepath.Join(DefaultLinux_d, "index.db"))
|
_, err = os.Stat(filepath.Join(consts.DefaultLinux_d, "index.db"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
@@ -73,10 +40,10 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = os.Stat(filepath.Join(DefaultLinux_d, "installed.db"))
|
_, err = os.Stat(filepath.Join(consts.DefaultLinux_d, "installed.db"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
db, err := sql.Open("sqlite", filepath.Join(DefaultLinux_d, "installed.db"))
|
db, err := sql.Open("sqlite", filepath.Join(consts.DefaultLinux_d, "installed.db"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(db)
|
log.Fatal(db)
|
||||||
}
|
}
|
||||||
@@ -87,9 +54,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = os.Stat(filepath.Join(DefaultLinux_d, "config.toml"))
|
_, err = os.Stat(filepath.Join(consts.DefaultLinux_d, "config.toml"))
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
f, err := os.Create(filepath.Join(DefaultLinux_d, "config.toml"))
|
f, err := os.Create(filepath.Join(consts.DefaultLinux_d, "config.toml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -98,7 +65,7 @@ func init() {
|
|||||||
|
|
||||||
encoder := toml.NewEncoder(f)
|
encoder := toml.NewEncoder(f)
|
||||||
|
|
||||||
cfg, err := internal.DefaultConfigTOML()
|
cfg, err := configs.DefaultConfigTOML()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -109,143 +76,6 @@ 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
|
|
||||||
}
|
|
||||||
|
|
||||||
func AskLAN(filename string) ([]Peer, error) {
|
|
||||||
var peers []Peer
|
|
||||||
query := []byte("Q:" + filename)
|
|
||||||
|
|
||||||
pc, err := net.ListenPacket("udp", ":0")
|
|
||||||
if err != nil {
|
|
||||||
return []Peer{}, err
|
|
||||||
}
|
|
||||||
defer pc.Close()
|
|
||||||
|
|
||||||
if pconn := ipv4.NewPacketConn(pc); pconn != nil {
|
|
||||||
_ = pconn.SetTTL(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
ifaces, _ := net.Interfaces()
|
|
||||||
for _, ifc := range ifaces {
|
|
||||||
if ifc.Flags&net.FlagUp == 0 || ifc.Flags&net.FlagLoopback != 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs, _ := ifc.Addrs()
|
|
||||||
for _, a := range addrs {
|
|
||||||
ipnet, ok := a.(*net.IPNet)
|
|
||||||
if !ok || ipnet.IP.To4() == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
bcast := internal.BroadcastAddr(ipnet.IP.To4(), ipnet.Mask)
|
|
||||||
dst := &net.UDPAddr{IP: bcast, Port: 1333}
|
|
||||||
|
|
||||||
_, err = pc.WriteTo(query, dst)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf(":: (%s) can't send to %s: %s\n", ifc.Name, bcast, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ = pc.SetDeadline(time.Now().Add(LANDeadline))
|
|
||||||
buf := make([]byte, 1500)
|
|
||||||
|
|
||||||
for {
|
|
||||||
n, addr, err := pc.ReadFrom(buf)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
msg := string(buf[:n])
|
|
||||||
|
|
||||||
if strings.HasPrefix(msg, "H:"+filename) {
|
|
||||||
parts := strings.Split(msg, ":")
|
|
||||||
port, _ := strconv.Atoi(parts[2])
|
|
||||||
peers = append(peers, Peer{IP: addr.(*net.UDPAddr).IP, Port: port})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return peers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// COBRA CMDS
|
// COBRA CMDS
|
||||||
var rootCmd = &cobra.Command{Use: "packets"}
|
var rootCmd = &cobra.Command{Use: "packets"}
|
||||||
var installCmd = &cobra.Command{
|
var installCmd = &cobra.Command{
|
||||||
|
|||||||
58
configs/main.go
Normal file
58
configs/main.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package configs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"packets/internal/consts"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultConfigTOML returns configTOML struct with all default values and create all directorys
|
||||||
|
func DefaultConfigTOML() (*ConfigTOML, error) {
|
||||||
|
|
||||||
|
var config ConfigTOML
|
||||||
|
|
||||||
|
_, err := os.Stat(consts.DefaultCache_d)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err := os.MkdirAll(consts.DefaultCache_d, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = os.Stat(consts.DefaultCache_d)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
err := os.MkdirAll(consts.DefaultData_d, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Config.Cache_d = consts.DefaultCache_d
|
||||||
|
config.Config.Data_d = consts.DefaultData_d
|
||||||
|
config.Config.HttpPort = consts.DefaultHttpPort
|
||||||
|
|
||||||
|
return &config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfigTOML return settings values
|
||||||
|
func GetConfigTOML() (*ConfigTOML, error) {
|
||||||
|
f, err := os.Open(filepath.Join(consts.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
|
||||||
|
}
|
||||||
26
configs/structs.go
Normal file
26
configs/structs.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package configs
|
||||||
|
|
||||||
|
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 {
|
||||||
|
HttpPort int `toml:"httpPort"`
|
||||||
|
Cache_d string `toml:"cache_d"`
|
||||||
|
Data_d string `toml:"data_d"`
|
||||||
|
Bin_d string `toml:"bin_d"`
|
||||||
|
} `toml:"Config"`
|
||||||
|
}
|
||||||
11
internal/consts/consts.go
Normal file
11
internal/consts/consts.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package consts
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultLinux_d = "/etc/packets"
|
||||||
|
DefaultCache_d = "/var/cache/packets"
|
||||||
|
DefaultHttpPort = 9123
|
||||||
|
DefaultData_d = "/opt/packets"
|
||||||
|
LANDeadline = 2 * time.Second
|
||||||
|
)
|
||||||
8
internal/errors/errors.go
Normal file
8
internal/errors/errors.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package errors_packets
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrResponseNot200OK = errors.New("the request is not 200, download failed")
|
||||||
|
ErrCantFindManifestTOML = errors.New("can't find manifest.toml when trying to read the packagefile")
|
||||||
|
)
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/tar"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/klauspost/compress/zstd"
|
|
||||||
"github.com/pelletier/go-toml/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// const
|
|
||||||
|
|
||||||
const DefaultLinux_d = "/etc/packets"
|
|
||||||
const DefaultCache_d = "/var/cache/packets"
|
|
||||||
const DefaultHttpPort = 9123
|
|
||||||
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 {
|
|
||||||
HttpPort int `toml:"httpPort"`
|
|
||||||
Cache_d string `toml:"cache_d"`
|
|
||||||
Data_d string `toml:"data_d"`
|
|
||||||
Bin_d string `toml:"bin_d"`
|
|
||||||
} `toml:"Config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func DownloadPackageHTTP(url string) (*[]byte, error) {
|
|
||||||
|
|
||||||
resp, err := http.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, ErrResponseNot200OK
|
|
||||||
}
|
|
||||||
|
|
||||||
fileBytes, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &fileBytes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultConfigTOML generate a default toml and create the directorys
|
|
||||||
func DefaultConfigTOML() (*ConfigTOML, error) {
|
|
||||||
|
|
||||||
var config ConfigTOML
|
|
||||||
|
|
||||||
_, err := os.Stat(DefaultCache_d)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
err := os.MkdirAll(DefaultCache_d, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = os.Stat(DefaultCache_d)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
err := os.MkdirAll(DefaultData_d, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Config.Cache_d = DefaultCache_d
|
|
||||||
config.Config.Data_d = DefaultData_d
|
|
||||||
config.Config.HttpPort = DefaultHttpPort
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func BroadcastAddr(ip net.IP, mask net.IPMask) net.IP {
|
|
||||||
b := make(net.IP, len(ip))
|
|
||||||
for i := range ip {
|
|
||||||
b[i] = ip[i] | ^mask[i]
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
80
internal/utils/lan.go
Normal file
80
internal/utils/lan.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"packets/internal/consts"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Peer struct {
|
||||||
|
IP net.IP
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
|
||||||
|
func BroadcastAddr(ip net.IP, mask net.IPMask) net.IP {
|
||||||
|
b := make(net.IP, len(ip))
|
||||||
|
for i := range ip {
|
||||||
|
b[i] = ip[i] | ^mask[i]
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func AskLAN(filename string) ([]Peer, error) {
|
||||||
|
var peers []Peer
|
||||||
|
query := []byte("Q:" + filename)
|
||||||
|
|
||||||
|
pc, err := net.ListenPacket("udp", ":0")
|
||||||
|
if err != nil {
|
||||||
|
return []Peer{}, err
|
||||||
|
}
|
||||||
|
defer pc.Close()
|
||||||
|
|
||||||
|
if pconn := ipv4.NewPacketConn(pc); pconn != nil {
|
||||||
|
_ = pconn.SetTTL(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
ifaces, _ := net.Interfaces()
|
||||||
|
for _, ifc := range ifaces {
|
||||||
|
if ifc.Flags&net.FlagUp == 0 || ifc.Flags&net.FlagLoopback != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs, _ := ifc.Addrs()
|
||||||
|
for _, a := range addrs {
|
||||||
|
ipnet, ok := a.(*net.IPNet)
|
||||||
|
if !ok || ipnet.IP.To4() == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bcast := BroadcastAddr(ipnet.IP.To4(), ipnet.Mask)
|
||||||
|
dst := &net.UDPAddr{IP: bcast, Port: 1333}
|
||||||
|
|
||||||
|
_, err = pc.WriteTo(query, dst)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf(":: (%s) can't send to %s: %s\n", ifc.Name, bcast, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = pc.SetDeadline(time.Now().Add(consts.LANDeadline))
|
||||||
|
buf := make([]byte, 1500)
|
||||||
|
|
||||||
|
for {
|
||||||
|
n, addr, err := pc.ReadFrom(buf)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
msg := string(buf[:n])
|
||||||
|
|
||||||
|
if strings.HasPrefix(msg, "H:"+filename) {
|
||||||
|
parts := strings.Split(msg, ":")
|
||||||
|
port, _ := strconv.Atoi(parts[2])
|
||||||
|
peers = append(peers, Peer{IP: addr.(*net.UDPAddr).IP, Port: port})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return peers, nil
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"packets/configs"
|
||||||
|
"packets/internal/consts"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -36,9 +38,9 @@ func IsSafe(str string) bool {
|
|||||||
s = filepath.Clean(str)
|
s = filepath.Clean(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg ConfigTOML
|
var cfg configs.ConfigTOML
|
||||||
|
|
||||||
f, err := os.Open(filepath.Join(DefaultLinux_d, "config.toml"))
|
f, err := os.Open(filepath.Join(consts.DefaultLinux_d, "config.toml"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error here opening config.toml")
|
log.Println("error here opening config.toml")
|
||||||
return false
|
return false
|
||||||
68
internal/utils/utils.go
Normal file
68
internal/utils/utils.go
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"packets/configs"
|
||||||
|
errors_packets "packets/internal/errors"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/klauspost/compress/zstd"
|
||||||
|
"github.com/pelletier/go-toml/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DownloadPackageHTTP(url string) (*[]byte, error) {
|
||||||
|
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, errors_packets.ErrResponseNot200OK
|
||||||
|
}
|
||||||
|
|
||||||
|
fileBytes, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &fileBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadManifest is crucial to get package metadata it reads manifest.toml from a package file (tar.zst)
|
||||||
|
func ReadManifest(file *os.File) (*configs.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 configs.Manifest
|
||||||
|
|
||||||
|
if err := decoder.Decode(&manifest); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &manifest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil, errors_packets.ErrCantFindManifestTOML
|
||||||
|
}
|
||||||
95
pkg/packagefiles.go
Normal file
95
pkg/packagefiles.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package pkg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"packets/configs"
|
||||||
|
"packets/internal/utils"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/klauspost/compress/zstd"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Install exctract and install from a package file ( tar.zst )
|
||||||
|
func InstallPackage(file *os.File) error {
|
||||||
|
|
||||||
|
manifest, err := utils.ReadManifest(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
name := &manifest.Info.Name
|
||||||
|
|
||||||
|
configuration, err := configs.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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user