better file organization
This commit is contained in:
		@@ -1,58 +1,25 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"archive/tar"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"packets/internal"
 | 
			
		||||
	"packets/configs"
 | 
			
		||||
	"packets/internal/consts"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/klauspost/compress/zstd"
 | 
			
		||||
	"github.com/pelletier/go-toml/v2"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"golang.org/x/net/ipv4"
 | 
			
		||||
	_ "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
 | 
			
		||||
func init() {
 | 
			
		||||
 | 
			
		||||
	_, err := os.Stat(DefaultLinux_d)
 | 
			
		||||
	_, err := os.Stat(consts.DefaultLinux_d)
 | 
			
		||||
	if os.IsNotExist(err) {
 | 
			
		||||
		err := os.Mkdir(DefaultLinux_d, 0644)
 | 
			
		||||
		err := os.Mkdir(consts.DefaultLinux_d, 0644)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if os.IsPermission(err) {
 | 
			
		||||
				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 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 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 {
 | 
			
		||||
				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) {
 | 
			
		||||
		f, err := os.Create(filepath.Join(DefaultLinux_d, "config.toml"))
 | 
			
		||||
		f, err := os.Create(filepath.Join(consts.DefaultLinux_d, "config.toml"))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -98,7 +65,7 @@ func init() {
 | 
			
		||||
 | 
			
		||||
		encoder := toml.NewEncoder(f)
 | 
			
		||||
 | 
			
		||||
		cfg, err := internal.DefaultConfigTOML()
 | 
			
		||||
		cfg, err := configs.DefaultConfigTOML()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			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
 | 
			
		||||
var rootCmd = &cobra.Command{Use: "packets"}
 | 
			
		||||
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 (
 | 
			
		||||
	"fmt"
 | 
			
		||||
@@ -6,6 +6,8 @@ import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"packets/configs"
 | 
			
		||||
	"packets/internal/consts"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
@@ -36,9 +38,9 @@ func IsSafe(str string) bool {
 | 
			
		||||
		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 {
 | 
			
		||||
		log.Println("error here opening config.toml")
 | 
			
		||||
		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