mirror of
https://github.com/HikariKnight/quickpassthrough
synced 2025-06-27 21:48:01 +02:00
Feat: conditional permissions behavior (#28)
* Fix: don't need sudo if we're root + other aesthetics
* Heavy refactoring, see PR #28
* Fix: avoid silent fatalities
demo: https://tcp.ac/i/JMSUc.gif
* Fix: Inverse check on `IsRoot`
* D.R.Y: check for permissions error in `common.ErrorCheck`
Reduce cognitive complexity.
* Fix: Issue with copying
* Resolve https://github.com/HikariKnight/quickpassthrough/pull/28#discussion_r1646535918
* Resolve https://github.com/HikariKnight/quickpassthrough/pull/28#discussion_r1646606680 and https://github.com/HikariKnight/quickpassthrough/pull/28#discussion_r1646594105
* Revert "Resolve https://github.com/HikariKnight/quickpassthrough/pull/28#discussion_r1646606680 and https://github.com/HikariKnight/quickpassthrough/pull/28#discussion_r1646594105"
This reverts commit ce15213009
.
* Resolve https://github.com/HikariKnight/quickpassthrough/pull/28#discussion_r1646730751
This commit is contained in:
parent
4d0086df41
commit
6c48a35180
21 changed files with 604 additions and 255 deletions
|
@ -1,16 +1,19 @@
|
|||
package configs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
||||
"github.com/klauspost/cpuid/v2"
|
||||
|
||||
"github.com/HikariKnight/quickpassthrough/internal/common"
|
||||
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
||||
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
||||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||
"github.com/klauspost/cpuid/v2"
|
||||
)
|
||||
|
||||
// This function just adds what bootloader the system has to our config.bootloader value
|
||||
|
@ -70,39 +73,32 @@ func Set_Cmdline(gpu_IDs []string) {
|
|||
fileio.AppendContent(fmt.Sprintf(" vfio_pci.ids=%s", strings.Join(gpu_IDs, ",")), config.Path.CMDLINE)
|
||||
}
|
||||
|
||||
// Configures systemd-boot using kernelstub
|
||||
func Set_KernelStub() string {
|
||||
// Set_KernelStub configures systemd-boot using kernelstub.
|
||||
func Set_KernelStub(isRoot bool) {
|
||||
// Get the config
|
||||
config := GetConfig()
|
||||
|
||||
// Get the kernel args
|
||||
kernel_args := fileio.ReadFile(config.Path.CMDLINE)
|
||||
|
||||
// Write to logger
|
||||
logger.Printf("Running command:\nsudo kernelstub -a \"%s\"\n", kernel_args)
|
||||
|
||||
// Run the command
|
||||
_, err := command.Run("sudo", "kernelstub", "-a", kernel_args)
|
||||
errorcheck.ErrorCheck(err, "Error, kernelstub command returned exit code 1")
|
||||
|
||||
// Return what we did
|
||||
return fmt.Sprintf("Executed: sudo kernelstub -a \"%s\"", kernel_args)
|
||||
// Run and log, check for errors
|
||||
common.ErrorCheck(
|
||||
command.ExecAndLogSudo(isRoot, true, "kernelstub", "-a", kernel_args),
|
||||
"Error, kernelstub command returned exit code 1",
|
||||
)
|
||||
}
|
||||
|
||||
// Configures grub2 and/or systemd-boot using grubby
|
||||
func Set_Grubby() string {
|
||||
// Set_Grubby configures grub2 and/or systemd-boot using grubby
|
||||
func Set_Grubby(isRoot bool) string {
|
||||
// Get the config
|
||||
config := GetConfig()
|
||||
|
||||
// Get the kernel args
|
||||
kernel_args := fileio.ReadFile(config.Path.CMDLINE)
|
||||
|
||||
// Write to logger
|
||||
logger.Printf("Running command:\nsudo grubby --update-kernel=ALL --args=\"%s\"\n", kernel_args)
|
||||
|
||||
// Run the command
|
||||
_, err := command.Run("sudo", "grubby", "--update-kernel=ALL", fmt.Sprintf("--args=%s", kernel_args))
|
||||
errorcheck.ErrorCheck(err, "Error, grubby command returned exit code 1")
|
||||
// Run and log, check for errors
|
||||
err := command.ExecAndLogSudo(isRoot, true, "grubby", "--update-kernel=ALL", fmt.Sprintf("--args=%s", kernel_args))
|
||||
common.ErrorCheck(err, "Error, grubby command returned exit code 1")
|
||||
|
||||
// Return what we did
|
||||
return fmt.Sprintf("Executed: sudo grubby --update-kernel=ALL --args=\"%s\"", kernel_args)
|
||||
|
@ -116,8 +112,8 @@ func Configure_Grub2() {
|
|||
conffile := fmt.Sprintf("%s/grub", config.Path.DEFAULT)
|
||||
|
||||
// Make sure we start from scratch by deleting any old file
|
||||
if fileio.FileExist(conffile) {
|
||||
os.Remove(conffile)
|
||||
if exists, _ := fileio.FileExist(conffile); exists {
|
||||
_ = os.Remove(conffile)
|
||||
}
|
||||
|
||||
// Make a regex to get the system path instead of the config path
|
||||
|
@ -201,8 +197,8 @@ func clean_Grub2_Args(old_kernel_args []string) []string {
|
|||
return clean_kernel_args
|
||||
}
|
||||
|
||||
// This function copies our config to /etc/default/grub and updates grub
|
||||
func Set_Grub2() ([]string, error) {
|
||||
// Set_Grub2 copies our config to /etc/default/grub and updates grub
|
||||
func Set_Grub2(isRoot bool) error {
|
||||
// Get the config
|
||||
config := GetConfig()
|
||||
|
||||
|
@ -213,38 +209,45 @@ func Set_Grub2() ([]string, error) {
|
|||
sysfile_re := regexp.MustCompile(`^config`)
|
||||
sysfile := sysfile_re.ReplaceAllString(conffile, "")
|
||||
|
||||
// Write to logger
|
||||
logger.Printf("Executing command:\nsudo cp -v \"%s\" %s\n", conffile, sysfile)
|
||||
// [CopyToSystem] will log the operation
|
||||
// logger.Printf("Executing command:\nsudo cp -v \"%s\" %s\n", conffile, sysfile)
|
||||
|
||||
// Make our output slice
|
||||
var output []string
|
||||
|
||||
// Copy files to system
|
||||
output = append(output, CopyToSystem(conffile, sysfile))
|
||||
// Copy files to system, logging and error checking is done in the function
|
||||
CopyToSystem(isRoot, conffile, sysfile)
|
||||
|
||||
// Set a variable for the mkconfig command
|
||||
mkconfig := "grub-mkconfig"
|
||||
var mkconfig string
|
||||
var grubPath = "/boot/grub/grub.cfg"
|
||||
var lpErr error
|
||||
|
||||
// Check for grub-mkconfig
|
||||
_, err := command.Run("which", "grub-mkconfig")
|
||||
if err == nil {
|
||||
// Set binary as grub-mkconfig
|
||||
mkconfig = "grub-mkconfig"
|
||||
} else {
|
||||
mkconfig = "grub2-mkconfig"
|
||||
mkconfig, lpErr = exec.LookPath("grub-mkconfig")
|
||||
switch {
|
||||
case errors.Is(lpErr, exec.ErrNotFound) || mkconfig == "":
|
||||
// Check for grub2-mkconfig
|
||||
mkconfig, lpErr = exec.LookPath("grub2-mkconfig")
|
||||
if lpErr == nil && mkconfig != "" {
|
||||
grubPath = "/boot/grub2/grub.cfg"
|
||||
break // skip below, we found grub2-mkconfig
|
||||
}
|
||||
if lpErr == nil {
|
||||
// we know mkconfig is empty despite no error;
|
||||
// so set an error for [common.ErrorCheck].
|
||||
lpErr = errors.New("neither grub-mkconfig or grub2-mkconfig found")
|
||||
}
|
||||
common.ErrorCheck(lpErr, lpErr.Error()+"\n")
|
||||
return lpErr // note: unreachable as [common.ErrorCheck] calls fatal
|
||||
default:
|
||||
}
|
||||
|
||||
// Update grub.cfg
|
||||
if fileio.FileExist("/boot/grub/grub.cfg") {
|
||||
output = append(output, fmt.Sprintf("Executed: sudo %s -o /boot/grub/grub.cfg\nSee debug.log for more detailed output", mkconfig))
|
||||
_, mklog, err := command.RunErr("sudo", mkconfig, "-o", "/boot/grub/grub.cfg")
|
||||
logger.Printf(strings.Join(mklog, "\n"))
|
||||
errorcheck.ErrorCheck(err, "Failed to update /boot/grub/grub.cfg")
|
||||
} else {
|
||||
output = append(output, fmt.Sprintf("Executed: sudo %s -o /boot/grub/grub.cfg\nSee debug.log for more detailed output", mkconfig))
|
||||
_, mklog, err := command.RunErr("sudo", mkconfig, "-o", "/boot/grub2/grub.cfg")
|
||||
logger.Printf(strings.Join(mklog, "\n"))
|
||||
errorcheck.ErrorCheck(err, "Failed to update /boot/grub/grub.cfg")
|
||||
}
|
||||
_, mklog, err := command.RunErrSudo(isRoot, mkconfig, "-o", grubPath)
|
||||
|
||||
return output, err
|
||||
// tabulate the output, [command.RunErrSudo] logged the execution.
|
||||
logger.Printf("\t" + strings.Join(mklog, "\n\t"))
|
||||
common.ErrorCheck(err, "Failed to update /boot/grub/grub.cfg")
|
||||
|
||||
// always returns nil as [common.ErrorCheck] calls fatal
|
||||
// keeping the ret signature, as we should consider passing down errors
|
||||
// but that's a massive rabbit hole to go down for this codebase as a whole
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||
)
|
||||
|
||||
// This function writes a dracut configuration file for /etc/dracut.conf.d/
|
||||
// Set_Dracut writes a dracut configuration file for `/etc/dracut.conf.d/`.
|
||||
func Set_Dracut() {
|
||||
config := GetConfig()
|
||||
|
||||
|
@ -17,8 +17,8 @@ func Set_Dracut() {
|
|||
dracutConf := fmt.Sprintf("%s/vfio.conf", config.Path.DRACUT)
|
||||
|
||||
// If the file already exists then delete it
|
||||
if fileio.FileExist(dracutConf) {
|
||||
os.Remove(dracutConf)
|
||||
if exists, _ := fileio.FileExist(dracutConf); exists {
|
||||
_ = os.Remove(dracutConf)
|
||||
}
|
||||
|
||||
// Write to logger
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
||||
"github.com/HikariKnight/quickpassthrough/internal/common"
|
||||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||
)
|
||||
|
||||
|
@ -15,7 +15,7 @@ import (
|
|||
func initramfs_readHeader(lines int, fileName string) string {
|
||||
// Open the file
|
||||
f, err := os.Open(fileName)
|
||||
errorcheck.ErrorCheck(err, fmt.Sprintf("Error opening %s", fileName))
|
||||
common.ErrorCheck(err, fmt.Sprintf("Error opening %s", fileName))
|
||||
defer f.Close()
|
||||
|
||||
header_re := regexp.MustCompile(`^#`)
|
||||
|
@ -50,7 +50,7 @@ func initramfs_addModules(conffile string) {
|
|||
|
||||
// Open the system file for reading
|
||||
sysfile, err := os.Open(syspath)
|
||||
errorcheck.ErrorCheck(err, fmt.Sprintf("Error opening file for reading %s", syspath))
|
||||
common.ErrorCheck(err, fmt.Sprintf("Error opening file for reading %s", syspath))
|
||||
defer sysfile.Close()
|
||||
|
||||
// Check if user has vendor-reset installed/enabled and make sure that is first
|
||||
|
|
|
@ -10,14 +10,14 @@ import (
|
|||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||
)
|
||||
|
||||
// This function copies the content of /etc/mkinitcpio.conf to the config folder and does an inline replace/insert on the MODULES=() line
|
||||
// Set_Mkinitcpio copies the content of /etc/mkinitcpio.conf to the config folder and does an inline replace/insert on the MODULES=() line
|
||||
func Set_Mkinitcpio() {
|
||||
// Get the config struct
|
||||
config := GetConfig()
|
||||
|
||||
// Make sure we start from scratch by deleting any old file
|
||||
if fileio.FileExist(config.Path.MKINITCPIO) {
|
||||
os.Remove(config.Path.MKINITCPIO)
|
||||
if exists, _ := fileio.FileExist(config.Path.MKINITCPIO); exists {
|
||||
_ = os.Remove(config.Path.MKINITCPIO)
|
||||
}
|
||||
|
||||
// Make a regex to get the system path instead of the config path
|
||||
|
|
|
@ -30,9 +30,9 @@ func Set_Modprobe(gpu_IDs []string) {
|
|||
conffile := fmt.Sprintf("%s/vfio.conf", config.Path.MODPROBE)
|
||||
|
||||
// If the file exists
|
||||
if fileio.FileExist(conffile) {
|
||||
if exists, _ := fileio.FileExist(conffile); exists {
|
||||
// Delete the old file
|
||||
os.Remove(conffile)
|
||||
_ = os.Remove(conffile)
|
||||
}
|
||||
|
||||
content := fmt.Sprint(
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
||||
"github.com/HikariKnight/quickpassthrough/internal/common"
|
||||
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
||||
)
|
||||
|
||||
|
@ -55,12 +55,12 @@ func GenerateVBIOSDumper(vbios_path string) {
|
|||
|
||||
// Make the script file
|
||||
scriptfile, err := os.Create("utils/dump_vbios.sh")
|
||||
errorcheck.ErrorCheck(err, "Cannot create file \"utils/dump_vbios.sh\"")
|
||||
common.ErrorCheck(err, "Cannot create file \"utils/dump_vbios.sh\"")
|
||||
defer scriptfile.Close()
|
||||
|
||||
// Make the script executable
|
||||
scriptfile.Chmod(0775)
|
||||
errorcheck.ErrorCheck(err, "Could not change permissions of \"utils/dump_vbios.sh\"")
|
||||
common.ErrorCheck(err, "Could not change permissions of \"utils/dump_vbios.sh\"")
|
||||
|
||||
// Write to logger
|
||||
logger.Printf("Writing utils/dump_vbios.sh\n")
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
||||
"github.com/HikariKnight/quickpassthrough/internal/common"
|
||||
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
||||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||
)
|
||||
|
@ -26,7 +26,7 @@ func DisableVFIOVideo(i int) {
|
|||
if strings.Contains(kernel_args, "vfio_pci.disable_vga") {
|
||||
// Remove the old file
|
||||
err := os.Remove(config.Path.CMDLINE)
|
||||
errorcheck.ErrorCheck(err, fmt.Sprintf("Could not rewrite %s", config.Path.CMDLINE))
|
||||
common.ErrorCheck(err, fmt.Sprintf("Could not rewrite %s", config.Path.CMDLINE))
|
||||
|
||||
// Enable or disable the VGA based on our given value
|
||||
if i == 0 {
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package configs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/HikariKnight/ls-iommu/pkg/errorcheck"
|
||||
"github.com/klauspost/cpuid/v2"
|
||||
|
||||
"github.com/HikariKnight/quickpassthrough/internal/common"
|
||||
"github.com/HikariKnight/quickpassthrough/internal/logger"
|
||||
"github.com/HikariKnight/quickpassthrough/pkg/command"
|
||||
"github.com/HikariKnight/quickpassthrough/pkg/fileio"
|
||||
"github.com/HikariKnight/quickpassthrough/pkg/uname"
|
||||
"github.com/klauspost/cpuid/v2"
|
||||
)
|
||||
|
||||
type Path struct {
|
||||
|
@ -30,9 +34,10 @@ type Config struct {
|
|||
Path *Path
|
||||
Gpu_Group string
|
||||
Gpu_IDs []string
|
||||
IsRoot bool
|
||||
}
|
||||
|
||||
// Gets the path to all the config files
|
||||
// GetConfigPaths retrieves the path to all the config files.
|
||||
func GetConfigPaths() *Path {
|
||||
Paths := &Path{
|
||||
CMDLINE: "config/kernel_args",
|
||||
|
@ -48,7 +53,7 @@ func GetConfigPaths() *Path {
|
|||
return Paths
|
||||
}
|
||||
|
||||
// Gets all the configs and returns the struct
|
||||
// GetConfig retrieves all the configs and returns the struct.
|
||||
func GetConfig() *Config {
|
||||
config := &Config{
|
||||
Bootloader: "unknown",
|
||||
|
@ -64,7 +69,7 @@ func GetConfig() *Config {
|
|||
return config
|
||||
}
|
||||
|
||||
// Constructs the empty config files and folders based on what exists on the system
|
||||
// InitConfigs constructs the empty config files and folders based on what exists on the system
|
||||
func InitConfigs() {
|
||||
config := GetConfig()
|
||||
|
||||
|
@ -77,10 +82,17 @@ func InitConfigs() {
|
|||
}
|
||||
|
||||
// Remove old config
|
||||
os.RemoveAll("config")
|
||||
if err := os.RemoveAll("config"); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
|
||||
// won't be called if the error is ErrNotExist
|
||||
common.ErrorCheck(err, "\nError removing old config")
|
||||
}
|
||||
|
||||
// Make the config folder
|
||||
os.Mkdir("config", os.ModePerm)
|
||||
if err := os.Mkdir("config", os.ModePerm); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
// won't be called if the error is ErrExist
|
||||
common.ErrorCheck(err, "\nError making config folder")
|
||||
}
|
||||
|
||||
// Make a regex to get the system path instead of the config path
|
||||
syspath_re := regexp.MustCompile(`^config`)
|
||||
|
@ -90,8 +102,16 @@ func InitConfigs() {
|
|||
// Get the system path
|
||||
syspath := syspath_re.ReplaceAllString(confpath, "")
|
||||
|
||||
exists, err := fileio.FileExist(syspath)
|
||||
|
||||
// If we received an error that is not ErrNotExist
|
||||
if err != nil {
|
||||
common.ErrorCheck(err, "\nError checking for directory: "+syspath)
|
||||
continue // note: unreachable due to ErrorCheck calling fatal
|
||||
}
|
||||
|
||||
// If the path exists
|
||||
if fileio.FileExist(syspath) {
|
||||
if exists {
|
||||
// Write to log
|
||||
logger.Printf(
|
||||
"%s found on the system\n"+
|
||||
|
@ -104,8 +124,10 @@ func InitConfigs() {
|
|||
makeBackupDir(syspath)
|
||||
|
||||
// Create the directories for our configs
|
||||
err := os.MkdirAll(confpath, os.ModePerm)
|
||||
errorcheck.ErrorCheck(err)
|
||||
if err = os.MkdirAll(confpath, os.ModePerm); err != nil && !errors.Is(err, os.ErrExist) {
|
||||
common.ErrorCheck(err, "\nError making directory: "+confpath)
|
||||
return // note: unreachable due to ErrorCheck calling fatal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +150,15 @@ func InitConfigs() {
|
|||
sysfile := syspath_re.ReplaceAllString(conffile, "")
|
||||
|
||||
// If the file exists
|
||||
if fileio.FileExist(sysfile) {
|
||||
exists, err := fileio.FileExist(sysfile)
|
||||
|
||||
// If we received an error that is not ErrNotExist
|
||||
if err != nil {
|
||||
common.ErrorCheck(err, "\nError checking for file: "+sysfile)
|
||||
continue // note: unreachable due to ErrorCheck calling fatal
|
||||
}
|
||||
|
||||
if exists {
|
||||
// Write to log
|
||||
logger.Printf(
|
||||
"%s found on the system\n"+
|
||||
|
@ -139,16 +169,22 @@ func InitConfigs() {
|
|||
|
||||
// Create the directories for our configs
|
||||
file, err := os.Create(conffile)
|
||||
errorcheck.ErrorCheck(err)
|
||||
common.ErrorCheck(err)
|
||||
// Close the file so we can edit it
|
||||
file.Close()
|
||||
_ = file.Close()
|
||||
|
||||
// Backup the sysfile if we do not have a backup
|
||||
backupFile(sysfile)
|
||||
}
|
||||
|
||||
exists, err = fileio.FileExist(conffile)
|
||||
if err != nil {
|
||||
common.ErrorCheck(err, "\nError checking for file: "+conffile)
|
||||
continue // note: unreachable
|
||||
}
|
||||
|
||||
// If we now have a config that exists
|
||||
if fileio.FileExist(conffile) {
|
||||
if exists {
|
||||
switch conffile {
|
||||
case config.Path.ETCMODULES:
|
||||
// Write to logger
|
||||
|
@ -204,14 +240,28 @@ func backupFile(source string) {
|
|||
// Make a destination path
|
||||
dest := fmt.Sprintf("backup%s", source)
|
||||
|
||||
configExists, configFileError := fileio.FileExist(fmt.Sprintf("config%s", source))
|
||||
sysExists, sysFileError := fileio.FileExist(source)
|
||||
destExists, destFileError := fileio.FileExist(dest)
|
||||
|
||||
// If we received an error that is not ErrNotExist on any of the files
|
||||
for _, err := range []error{configFileError, sysFileError, destFileError} {
|
||||
if err != nil {
|
||||
common.ErrorCheck(configFileError, "\nError checking for file: "+source)
|
||||
return // note: unreachable
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
// If the file exists in the config but not on the system it is a file we make
|
||||
if fileio.FileExist(fmt.Sprintf("config%s", source)) && !fileio.FileExist(source) {
|
||||
case configExists && !sysExists:
|
||||
// Create the blank file so that a copy of the backup folder to /etc
|
||||
file, err := os.Create(dest)
|
||||
errorcheck.ErrorCheck(err, "Error creating file %s\n", dest)
|
||||
file.Close()
|
||||
} else if !fileio.FileExist(dest) {
|
||||
common.ErrorCheck(err, "Error creating file %s\n", dest)
|
||||
_ = file.Close()
|
||||
|
||||
// If a backup of the file does not exist
|
||||
case sysExists && !destExists:
|
||||
// Write to the logger
|
||||
logger.Printf("No first time backup of %s detected.\nCreating a backup at %s\n", source, dest)
|
||||
|
||||
|
@ -223,29 +273,67 @@ func backupFile(source string) {
|
|||
|
||||
func makeBackupDir(dest string) {
|
||||
// If a backup directory does not exist
|
||||
if !fileio.FileExist("backup/") {
|
||||
exists, err := fileio.FileExist("backup/")
|
||||
if err != nil {
|
||||
// If we received an error that is not ErrNotExist
|
||||
common.ErrorCheck(err, "Error checking for backup/ folder")
|
||||
return // note: unreachable
|
||||
}
|
||||
|
||||
if !exists {
|
||||
// Write to the logger
|
||||
logger.Printf("Backup directory does not exist!\nCreating backup directory for first run backup")
|
||||
}
|
||||
|
||||
// Make the empty directories
|
||||
err := os.MkdirAll(fmt.Sprintf("backup/%s", dest), os.ModePerm)
|
||||
errorcheck.ErrorCheck(err, "Error making backup/ folder")
|
||||
if err = os.MkdirAll(fmt.Sprintf("backup/%s", dest), os.ModePerm); errors.Is(err, os.ErrExist) {
|
||||
// ignore if the directory already exists
|
||||
err = nil
|
||||
}
|
||||
// will return without incident if there's no error
|
||||
common.ErrorCheck(err, "Error making backup/ folder")
|
||||
}
|
||||
|
||||
// Copy a file to the system, make sure you have run command.Elevate() recently
|
||||
func CopyToSystem(conffile, sysfile string) string {
|
||||
// CopyToSystem copies a file to the system.
|
||||
func CopyToSystem(isRoot bool, conffile, sysfile string) {
|
||||
// Since we should be elevated with our sudo token we will copy with cp
|
||||
// (using built in functions will not work as we are running as the normal user)
|
||||
output, _ := command.Run("sudo", "cp", "-v", conffile, sysfile)
|
||||
|
||||
// Clean the output
|
||||
clean_re := regexp.MustCompile(`\n`)
|
||||
clean_output := clean_re.ReplaceAllString(output[0], "")
|
||||
// ExecAndLogSudo will write to the logger, so just print here
|
||||
fmt.Printf("Copying: %s to %s\n", conffile, sysfile)
|
||||
|
||||
// Write output to logger
|
||||
logger.Printf("%s\n", clean_output)
|
||||
if isRoot {
|
||||
logger.Printf("Copying %s to %s\n", conffile, sysfile)
|
||||
fmt.Printf("Copying %s to %s\n", conffile, sysfile)
|
||||
fDat, err := os.ReadFile(conffile)
|
||||
common.ErrorCheck(err, fmt.Sprintf("Failed to read %s", conffile))
|
||||
err = os.WriteFile(sysfile, fDat, 0644)
|
||||
common.ErrorCheck(err, fmt.Sprintf("Failed to write %s", sysfile))
|
||||
logger.Printf("Copied %s to %s\n", conffile, sysfile)
|
||||
return
|
||||
}
|
||||
|
||||
// Return the output
|
||||
return fmt.Sprintf("Copying: %s", clean_output)
|
||||
if !filepath.IsAbs(conffile) {
|
||||
conffile, _ = filepath.Abs(conffile)
|
||||
}
|
||||
|
||||
conffile = strings.ReplaceAll(conffile, " ", "\\ ")
|
||||
cmd := fmt.Sprintf("cp -v %s %s", conffile, sysfile)
|
||||
|
||||
err := command.ExecAndLogSudo(isRoot, false, cmd)
|
||||
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
|
||||
// [command.ExecAndLogSudo] will log the command's output
|
||||
common.ErrorCheck(err, fmt.Sprintf("Failed to copy %s to %s:\n%s", conffile, sysfile, errMsg))
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// note that if we failed the error check, the following will not appear in the log!
|
||||
// this is because the [common.ErrorCheck] function will call [log.Fatalf] and exit
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
logger.Printf("Copied %s to %s\n", conffile, sysfile)
|
||||
}
|
||||
|
|
33
internal/configs/configs_test.go
Normal file
33
internal/configs/configs_test.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package configs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCopyToSystem(t *testing.T) {
|
||||
if err := os.Mkdir("testdir", 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tFilePath := filepath.Join("testdir", "testfile")
|
||||
if err := os.WriteFile(tFilePath, []byte("test"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := os.RemoveAll("testdir"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
isRoot := os.Getuid() == 0
|
||||
switch isRoot {
|
||||
case true:
|
||||
t.Run("TestCopyToSystem_AsRoot", func(t *testing.T) {
|
||||
CopyToSystem(true, tFilePath, "/etc/testfile")
|
||||
})
|
||||
default:
|
||||
t.Run("TestCopyToSystem_AsUser", func(t *testing.T) {
|
||||
CopyToSystem(false, tFilePath, "/etc/testfile")
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue