mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
* initial auto-update * working link, update, and testing docker container and scripts * refactor packages/folders * move files to proper folders * fix typos Closes #421 * optimize rpm imports * optimize channel imports * Refactor split command to allow testing of split operations Closes #338 * modify split and test for folder changes * remove alias * fix docker warning about FROM and AS being in different letter case Closes #422 * QClient Account Command * Display transaction details and confirmation prompts for transfer and merge commands * build qclient docker improvements * update build args for mpfr.so.6 * update install and node commands * remove NodeConfig check for qclient node commands * udpate * working node commands * update commands * move utils and rename package --------- Co-authored-by: Vasyl Tretiakov <vasyl.tretiakov@gmail.com> Co-authored-by: littleblackcloud <163544315+littleblackcloud@users.noreply.github.com> Co-authored-by: 0xOzgur <29779769+0xOzgur@users.noreply.github.com> Co-authored-by: Cassandra Heart <7929478+CassOnMars@users.noreply.github.com>
238 lines
6.7 KiB
Go
238 lines
6.7 KiB
Go
package utils
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"os/exec"
|
|
"os/user"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
var ClientInstallPath = filepath.Join("/opt/quilibrium/", string(ReleaseTypeQClient))
|
|
var RootQuilibriumPath = filepath.Join("/var/quilibrium/")
|
|
var BinaryPath = filepath.Join(RootQuilibriumPath, "bin")
|
|
var ClientDataPath = filepath.Join(BinaryPath, string(ReleaseTypeQClient))
|
|
var NodeDataPath = filepath.Join(BinaryPath, string(ReleaseTypeNode))
|
|
var DefaultSymlinkDir = "/usr/local/bin"
|
|
var DefaultNodeSymlinkPath = filepath.Join(DefaultSymlinkDir, string(ReleaseTypeNode))
|
|
var DefaultQClientSymlinkPath = filepath.Join(DefaultSymlinkDir, string(ReleaseTypeQClient))
|
|
var osType = runtime.GOOS
|
|
var arch = runtime.GOARCH
|
|
|
|
// CalculateFileHashes calculates SHA256 and MD5 hashes for a file
|
|
func CalculateFileHashes(filePath string) (string, string, error) {
|
|
file, err := os.Open(filePath)
|
|
if err != nil {
|
|
return "", "", fmt.Errorf("error opening file: %w", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
// Calculate SHA256
|
|
sha256Hash := sha256.New()
|
|
if _, err := io.Copy(sha256Hash, file); err != nil {
|
|
return "", "", fmt.Errorf("error calculating SHA256: %w", err)
|
|
}
|
|
|
|
// Reset file position to beginning for MD5 calculation
|
|
if _, err := file.Seek(0, 0); err != nil {
|
|
return "", "", fmt.Errorf("error seeking file: %w", err)
|
|
}
|
|
|
|
// Calculate MD5
|
|
md5Hash := md5.New()
|
|
if _, err := io.Copy(md5Hash, file); err != nil {
|
|
return "", "", fmt.Errorf("error calculating MD5: %w", err)
|
|
}
|
|
|
|
return hex.EncodeToString(sha256Hash.Sum(nil)), hex.EncodeToString(md5Hash.Sum(nil)), nil
|
|
}
|
|
|
|
// CreateSymlink creates a symlink, handling the case where it already exists
|
|
func CreateSymlink(execPath, targetPath string) error {
|
|
// Check if the symlink already exists
|
|
if _, err := os.Lstat(targetPath); err == nil {
|
|
// Symlink exists, ask if user wants to overwrite
|
|
if !ConfirmSymlinkOverwrite(targetPath) {
|
|
fmt.Println("Operation cancelled.")
|
|
return nil
|
|
}
|
|
|
|
// Remove existing symlink
|
|
if err := os.Remove(targetPath); err != nil {
|
|
return fmt.Errorf("failed to remove existing symlink: %w", err)
|
|
}
|
|
}
|
|
|
|
fmt.Printf("Creating symlink %s -> %s\n", targetPath, execPath)
|
|
|
|
// Create the symlink
|
|
if err := os.Symlink(execPath, targetPath); err != nil {
|
|
return fmt.Errorf("failed to create symlink: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ValidateAndCreateDir validates a directory path and creates it if it doesn't exist
|
|
func ValidateAndCreateDir(path string, user *user.User) error {
|
|
// Check if the directory exists
|
|
info, err := os.Stat(path)
|
|
if err == nil {
|
|
// Path exists, check if it's a directory
|
|
if !info.IsDir() {
|
|
return fmt.Errorf("%s exists but is not a directory", path)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Directory doesn't exist, try to create it
|
|
if os.IsNotExist(err) {
|
|
fmt.Printf("Creating directory %s\n", path)
|
|
if err := os.MkdirAll(path, 0755); err != nil {
|
|
return fmt.Errorf("failed to create directory %s: %v", path, err)
|
|
}
|
|
if user != nil {
|
|
ChownPath(path, user, false)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Some other error occurred
|
|
return fmt.Errorf("error checking directory %s: %v", path, err)
|
|
}
|
|
|
|
// IsWritable checks if a directory is writable
|
|
func IsWritable(dir string) bool {
|
|
// Check if directory exists
|
|
info, err := os.Stat(dir)
|
|
if err != nil || !info.IsDir() {
|
|
return false
|
|
}
|
|
|
|
// Check if directory is writable by creating a temporary file
|
|
tempFile := filepath.Join(dir, ".quilibrium_write_test")
|
|
file, err := os.Create(tempFile)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
file.Close()
|
|
os.Remove(tempFile)
|
|
return true
|
|
}
|
|
|
|
// CanCreateAndWrite checks if we can create and write to a directory
|
|
func CanCreateAndWrite(dir string) bool {
|
|
// Try to create the directory
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return false
|
|
}
|
|
|
|
// Check if we can write to it
|
|
return IsWritable(dir)
|
|
}
|
|
|
|
// FileExists checks if a file exists
|
|
func FileExists(path string) bool {
|
|
_, err := os.Stat(path)
|
|
return !os.IsNotExist(err)
|
|
}
|
|
|
|
func IsSudo() bool {
|
|
user, err := user.Current()
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return user.Username == "root"
|
|
}
|
|
|
|
// ChownPath changes the owner of a file or directory to the specified user
|
|
func ChownPath(path string, user *user.User, isRecursive bool) error {
|
|
// Change ownership of the path
|
|
if isRecursive {
|
|
fmt.Printf("Changing ownership of %s (recursive) to %s\n", path, user.Username)
|
|
if err := exec.Command("chown", "-R", user.Uid+":"+user.Gid, path).Run(); err != nil {
|
|
return fmt.Errorf("failed to change ownership of %s to %s (requires sudo): %v", path, user.Uid, err)
|
|
}
|
|
} else {
|
|
fmt.Printf("Changing ownership of %s to %s\n", path, user.Username)
|
|
if err := exec.Command("chown", user.Uid+":"+user.Gid, path).Run(); err != nil {
|
|
return fmt.Errorf("failed to change ownership of %s to %s (requires sudo): %v", path, user.Uid, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ChmodPath(path string, mode os.FileMode, description string) error {
|
|
fmt.Printf("Changing path: %s to %s (%s)\n", path, mode, description)
|
|
return os.Chmod(path, mode)
|
|
}
|
|
|
|
func WriteFile(path string, content string) error {
|
|
return os.WriteFile(path, []byte(content), 0644)
|
|
}
|
|
|
|
// WriteFileAuto writes content to a file, automatically using sudo only if necessary
|
|
func WriteFileAuto(path string, content string) error {
|
|
// First check if file exists and is writable
|
|
if FileExists(path) {
|
|
// Try to open the file for writing to check permissions
|
|
file, err := os.OpenFile(path, os.O_WRONLY, 0)
|
|
if err == nil {
|
|
// File is writable, close it and write normally
|
|
file.Close()
|
|
fmt.Printf("Writing to file %s using normal permissions\n", path)
|
|
return os.WriteFile(path, []byte(content), 0644)
|
|
}
|
|
} else {
|
|
// Check if parent directory is writable
|
|
dir := filepath.Dir(path)
|
|
if IsWritable(dir) {
|
|
fmt.Printf("Writing to file %s using normal permissions\n", path)
|
|
return os.WriteFile(path, []byte(content), 0644)
|
|
}
|
|
}
|
|
|
|
// If we reach here, sudo is needed
|
|
fmt.Printf("Writing to file %s using sudo\n", path)
|
|
cmd := exec.Command("sudo", "tee", path)
|
|
stdin, err := cmd.StdinPipe()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get stdin pipe: %w", err)
|
|
}
|
|
|
|
// Start the command
|
|
if err := cmd.Start(); err != nil {
|
|
return fmt.Errorf("failed to start sudo command: %w", err)
|
|
}
|
|
|
|
// Write content to stdin
|
|
if _, err := io.WriteString(stdin, content); err != nil {
|
|
return fmt.Errorf("failed to write to stdin: %w", err)
|
|
}
|
|
stdin.Close()
|
|
|
|
// Wait for the command to finish
|
|
if err := cmd.Wait(); err != nil {
|
|
return fmt.Errorf("sudo tee command failed: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CopyFile copies a file from src to dst
|
|
func CopyFile(src, dst string) error {
|
|
fmt.Printf("Copying file from %s to %s\n", src, dst)
|
|
sourceData, err := os.ReadFile(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(dst, sourceData, 0600)
|
|
}
|