176 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package packets
 | 
						|
 | 
						|
import (
 | 
						|
	"archive/tar"
 | 
						|
	"bytes"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"packets/internal/build"
 | 
						|
	"packets/internal/utils"
 | 
						|
	"runtime"
 | 
						|
 | 
						|
	utils_lua "packets/internal/utils/lua"
 | 
						|
	"path/filepath"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/klauspost/compress/zstd"
 | 
						|
	lua "github.com/yuin/gopher-lua"
 | 
						|
	_ "modernc.org/sqlite"
 | 
						|
)
 | 
						|
 | 
						|
// Install exctract and fully install from a package file ( tar.zst )
 | 
						|
func InstallPackage(file []byte, destDir string) error {
 | 
						|
	manifest, err := utils.ReadManifest(bytes.NewReader(file))
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	zstdReader, err := zstd.NewReader(bytes.NewReader(file))
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	defer zstdReader.Close()
 | 
						|
 | 
						|
	tarReader := tar.NewReader(zstdReader)
 | 
						|
 | 
						|
	uid, err := utils.GetPacketsUID()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	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, 0775); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		if err := os.Chown(destDir, uid, 0); 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
 | 
						|
			}
 | 
						|
			if err := os.Chown(absPath, uid, 0); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
		case tar.TypeReg:
 | 
						|
 | 
						|
			err = os.MkdirAll(filepath.Dir(absPath), 0775)
 | 
						|
			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(0775))
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
 | 
						|
			if filepath.Base(hdr.Name) == "manifest.toml" || filepath.Base(hdr.Name) == manifest.Hooks.Install || filepath.Base(hdr.Name) == manifest.Hooks.Remove {
 | 
						|
				err = os.Chmod(absPath, os.FileMode(0755))
 | 
						|
				if err != nil {
 | 
						|
					return err
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				if err := os.Chown(absPath, uid, 0); err != nil {
 | 
						|
					return err
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	L, err := utils_lua.GetSandBox()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	L.SetGlobal("DATA_DIR", lua.LString(filepath.Join(destDir, "data")))
 | 
						|
	L.SetGlobal("script", lua.LString(manifest.Hooks.Build))
 | 
						|
 | 
						|
	container, err := build.NewContainer(filepath.Join(destDir, "data"), manifest)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	container.GetLuaState()
 | 
						|
 | 
						|
	L.SetGlobal("data_dir", lua.LString(filepath.Join(destDir, "data")))
 | 
						|
	L.SetGlobal("script", lua.LString(manifest.Hooks.Install))
 | 
						|
 | 
						|
	runtime.LockOSThread()
 | 
						|
	defer runtime.UnlockOSThread()
 | 
						|
 | 
						|
	if err := utils.ChangeToNoPermission(); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := L.DoFile(filepath.Join(destDir, manifest.Hooks.Install)); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := utils.ElevatePermission(); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// ExecuteRemoveScript executes the remove script from the package
 | 
						|
func ExecuteRemoveScript(path string) error {
 | 
						|
 | 
						|
	L, err := utils_lua.GetSandBox()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	L.SetGlobal("DATA_DIR", lua.LFalse)
 | 
						|
	L.SetGlobal("script", lua.LString(path))
 | 
						|
 | 
						|
	runtime.LockOSThread()
 | 
						|
	defer runtime.UnlockOSThread()
 | 
						|
 | 
						|
	if err := utils.ChangeToNoPermission(); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := L.DoFile(path); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	if err := utils.ElevatePermission(); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |