diff --git a/clip/copy_UNIX.go b/clip/copy_UNIX.go index 5deee8e..a7dfbf5 100644 --- a/clip/copy_UNIX.go +++ b/clip/copy_UNIX.go @@ -54,7 +54,6 @@ func isWayland() (bool, error) { return true, nil } else if _, envSet = os.LookupEnv("DISPLAY"); envSet { return false, nil - } else { - return false, errors.New("unable to detect Wayland or X11 session") } + return false, errors.New("unable to detect Wayland or X11 session") } diff --git a/cfg/cfg.go b/config/cfg.go similarity index 82% rename from cfg/cfg.go rename to config/cfg.go index e412b55..218b6a9 100644 --- a/cfg/cfg.go +++ b/config/cfg.go @@ -1,4 +1,4 @@ -package cfg +package config import ( "encoding/json" @@ -9,7 +9,7 @@ import ( "github.com/rwinkhart/libmutton/global" ) -type ConfigT struct { +type CfgT struct { Libmutton struct { OfflineMode *bool `json:"offlineMode"` SSHUser *string `json:"sshUser"` @@ -24,13 +24,13 @@ type ConfigT struct { ThirdParty *map[string]any `json:"thirdParty"` } -// LoadConfig loads libmuttoncfg.json and returns the configuration. -func LoadConfig() (*ConfigT, error) { - cfgBytes, err := os.ReadFile(global.ConfigPath) +// Load loads libmuttoncfg.json and returns the configuration. +func Load() (*CfgT, error) { + cfgBytes, err := os.ReadFile(global.CfgPath) if err != nil { return nil, errors.New("unable to load libmuttoncfg.json: " + err.Error()) } - var cfg ConfigT + var cfg CfgT err = json.Unmarshal(cfgBytes, &cfg) if err != nil { return nil, errors.New("unable to unmarshal libmuttoncfg.json: " + err.Error()) @@ -38,10 +38,10 @@ func LoadConfig() (*ConfigT, error) { return &cfg, nil } -// WriteConfig writes cfg to libmuttoncfg.json. +// Write writes cfg to libmuttoncfg.json. // If used in append mode, any nil values in the // input cfg will be substituted with the existing values. -func WriteConfig(cfg *ConfigT, appendMode bool) error { +func Write(cfg *CfgT, appendMode bool) error { start: if appendMode { // check if any fields are nil @@ -57,7 +57,7 @@ start: // load old cfg and copy nil fields if hasNilFields { - oldCfg, err := LoadConfig() + oldCfg, err := Load() if err != nil { // failed to load config, leave append mode appendMode = false @@ -76,7 +76,7 @@ start: if err != nil { return errors.New("unable to marshal new/updated cfg: " + err.Error()) } - err = os.WriteFile(global.ConfigPath, cfgBytes, 0600) + err = os.WriteFile(global.CfgPath, cfgBytes, 0600) if err != nil { return errors.New("unable to write new/updated cfg to libmuttoncfg.json: " + err.Error()) } diff --git a/core/init.go b/core/init.go index ebb74fc..588ca58 100644 --- a/core/init.go +++ b/core/init.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/rwinkhart/go-boilerplate/back" - "github.com/rwinkhart/libmutton/cfg" + "github.com/rwinkhart/libmutton/config" "github.com/rwinkhart/libmutton/global" "github.com/rwinkhart/libmutton/syncclient" "github.com/rwinkhart/rcw/wrappers" @@ -15,9 +15,9 @@ import ( // LibmuttonInit creates the libmutton config structure based on user input. // rcwPassword and clientSpecificIniData can be left blank if not needed. -func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map[string]any, rcwPassword []byte, preserveOldConfigDir bool, forceOfflineMode bool) error { +func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map[string]any, rcwPassword []byte, preserveOldCfgDir bool, forceOfflineMode bool) error { // handle clientSpecificIniData - newCfg := &cfg.ConfigT{} + newCfg := &config.CfgT{} if clientSpecificIniData != nil { newThirdPartyMap := make(map[string]any) maps.Copy(newThirdPartyMap, clientSpecificIniData) @@ -32,7 +32,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map } if len(r) > 0 && r[0] == 'n' { // initialize libmutton directories - _, err := global.DirInit(preserveOldConfigDir) + _, err := global.DirInit(preserveOldCfgDir) if err != nil { return errors.New("unable to initialize libmutton directories: " + err.Error()) } @@ -40,7 +40,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map // write config file offlineMode := true newCfg.Libmutton.OfflineMode = &offlineMode - err = cfg.WriteConfig(newCfg, false) + err = config.Write(newCfg, false) if err != nil { return err } @@ -65,7 +65,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map // perform operations based on collected user input //// initialize libmutton directories - oldDeviceID, err := global.DirInit(preserveOldConfigDir) + oldDeviceID, err := global.DirInit(preserveOldCfgDir) if err != nil { return errors.New("unable to initialize libmutton directories: " + err.Error()) } @@ -77,7 +77,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map newCfg.Libmutton.SSHPort = &sshPort newCfg.Libmutton.SSHKeyPath = &sshKeyPath newCfg.Libmutton.SSHKeyProtected = &sshKeyProtected - err = cfg.WriteConfig(newCfg, false) + err = config.Write(newCfg, false) if err != nil { return err } @@ -90,7 +90,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map newCfg.Libmutton.SSHEntryRootPath = &sshEntryRoot newCfg.Libmutton.SSHAgeDirPath = &sshAgeDir newCfg.Libmutton.SSHIsWindows = &sshIsWindows - err = cfg.WriteConfig(newCfg, true) + err = config.Write(newCfg, true) if err != nil { return err } @@ -107,7 +107,7 @@ func LibmuttonInit(inputCB func(prompt string) string, clientSpecificIniData map // RCWSanityCheckGen generates the RCW sanity check file for libmutton. func RCWSanityCheckGen(password []byte) error { - err := wrappers.GenSanityCheck(global.ConfigDir+global.PathSeparator+"sanity.rcw", password) + err := wrappers.GenSanityCheck(global.CfgDir+global.PathSeparator+"sanity.rcw", password) if err != nil { return errors.New("unable to generate sanity check file: " + err.Error()) } diff --git a/crypt/rcw.go b/crypt/rcw.go index 8f02cd7..86e98bc 100644 --- a/crypt/rcw.go +++ b/crypt/rcw.go @@ -71,7 +71,7 @@ func launchRCWDProcess() []byte { if RetryPassword { for { password = global.GetPassword("RCW Password:") - err := wrappers.RunSanityCheck(global.ConfigDir+global.PathSeparator+"sanity.rcw", password) + err := wrappers.RunSanityCheck(global.CfgDir+global.PathSeparator+"sanity.rcw", password) if err == nil { break } diff --git a/global/2globals_UNIX.go b/global/2globals_UNIX.go index cae30d4..4afaac0 100644 --- a/global/2globals_UNIX.go +++ b/global/2globals_UNIX.go @@ -5,10 +5,10 @@ package global import "github.com/rwinkhart/go-boilerplate/back" var ( - EntryRoot = back.Home + "/.local/share/libmutton" // Path to libmutton entry directory - ConfigDir = back.Home + "/.config/libmutton" // Path to libmutton configuration directory - ConfigPath = ConfigDir + "/libmuttoncfg.json" // Path to libmutton configuration file - AgeDir = ConfigDir + "/age" // Path to libmutton password age directory + EntryRoot = back.Home + "/.local/share/libmutton" // Path to libmutton entry directory + CfgDir = back.Home + "/.config/libmutton" // Path to libmutton configuration directory + CfgPath = CfgDir + "/libmuttoncfg.json" // Path to libmutton configuration file + AgeDir = CfgDir + "/age" // Path to libmutton password age directory ) const ( diff --git a/global/2globals_WIN.go b/global/2globals_WIN.go index 8a3f678..641f858 100644 --- a/global/2globals_WIN.go +++ b/global/2globals_WIN.go @@ -5,10 +5,10 @@ package global import "github.com/rwinkhart/go-boilerplate/back" var ( - EntryRoot = back.Home + "\\AppData\\Local\\libmutton\\entries" // Path to libmutton entry directory - ConfigDir = back.Home + "\\AppData\\Local\\libmutton\\config" // Path to libmutton configuration directory - ConfigPath = ConfigDir + "\\libmuttoncfg.json" // Path to libmutton configuration file - AgeDir = ConfigDir + "\\age" // Path to libmutton password age directory + EntryRoot = back.Home + "\\AppData\\Local\\libmutton\\entries" // Path to libmutton entry directory + CfgDir = back.Home + "\\AppData\\Local\\libmutton\\config" // Path to libmutton configuration directory + CfgPath = CfgDir + "\\libmuttoncfg.json" // Path to libmutton configuration file + AgeDir = CfgDir + "\\age" // Path to libmutton password age directory ) const ( diff --git a/global/deviceIDs.go b/global/deviceIDs.go index 8e82ad9..c4f32cf 100644 --- a/global/deviceIDs.go +++ b/global/deviceIDs.go @@ -26,7 +26,7 @@ func GetCurrentDeviceID() (string, error) { // Requires: errorOnFail (set to true to throw an error if the devices directory cannot be read/does not exist) func GenDeviceIDList() ([]fs.DirEntry, error) { // create a slice of all registered devices - deviceIDList, err := os.ReadDir(ConfigDir + PathSeparator + "devices") + deviceIDList, err := os.ReadDir(CfgDir + PathSeparator + "devices") if err != nil { return nil, errors.New("unable to read devices directory: " + err.Error()) } diff --git a/global/init.go b/global/init.go index dccc4ad..3ac9913 100644 --- a/global/init.go +++ b/global/init.go @@ -9,7 +9,7 @@ import ( // DirInit creates the libmutton directories. // Returns: oldDeviceID (from before the directory reset; will be FSMisc if there is no pre-existing ID). -func DirInit(preserveOldConfigDir bool) (string, error) { +func DirInit(preserveOldCfgDir bool) (string, error) { // create EntryRoot err := os.MkdirAll(EntryRoot, 0700) if err != nil { @@ -23,10 +23,10 @@ func DirInit(preserveOldConfigDir bool) (string, error) { } // remove existing config directory (if it exists and not in append mode) - if !preserveOldConfigDir { - isAccessible, _ := back.TargetIsFile(ConfigDir, false) // error is ignored because dir/file status is irrelevant + if !preserveOldCfgDir { + isAccessible, _ := back.TargetIsFile(CfgDir, false) // error is ignored because dir/file status is irrelevant if isAccessible { - err = os.RemoveAll(ConfigDir) + err = os.RemoveAll(CfgDir) if err != nil { return "", errors.New("unable to remove existing config directory: " + err.Error()) } @@ -34,9 +34,9 @@ func DirInit(preserveOldConfigDir bool) (string, error) { } // create config directory w/devices subdirectory - err = os.MkdirAll(ConfigDir+PathSeparator+"devices", 0700) + err = os.MkdirAll(CfgDir+PathSeparator+"devices", 0700) if err != nil { - return "", errors.New("unable to create \"" + ConfigDir + "\": " + err.Error()) + return "", errors.New("unable to create \"" + CfgDir + "\": " + err.Error()) } // create password age directory diff --git a/libmuttonserver.go b/libmuttonserver.go index a372fba..1c84933 100644 --- a/libmuttonserver.go +++ b/libmuttonserver.go @@ -97,7 +97,7 @@ func main() { // register a new device ID // stdin[0] is expected to be the device ID // stdin[1] is expected to be the old device ID (for removal) - f, err := os.OpenFile(global.ConfigDir+global.PathSeparator+"devices"+global.PathSeparator+stdin[0], os.O_CREATE|os.O_WRONLY, 0600) + f, err := os.OpenFile(global.CfgDir+global.PathSeparator+"devices"+global.PathSeparator+stdin[0], os.O_CREATE|os.O_WRONLY, 0600) if err != nil { fmt.Printf("{\"errMsg\":\"%s\"}", err.Error()) return @@ -105,13 +105,13 @@ func main() { _ = f.Close() if stdin[1] != global.FSMisc { // FSMisc is used to indicate that no device ID is being replaced // remove the old device ID file - err = os.RemoveAll(global.ConfigDir + global.PathSeparator + "devices" + global.PathSeparator + stdin[1]) + err = os.RemoveAll(global.CfgDir + global.PathSeparator + "devices" + global.PathSeparator + stdin[1]) if err != nil { fmt.Printf("{\"errMsg\":\"%s\"}", err.Error()) return } // carry over deletions from the old device ID to the new one - deletionsDirRoot := global.ConfigDir + global.PathSeparator + "deletions" + global.PathSeparator + deletionsDirRoot := global.CfgDir + global.PathSeparator + "deletions" + global.PathSeparator deletionsList, err := os.ReadDir(deletionsDirRoot) if err != nil { fmt.Printf("{\"errMsg\":\"%s\"}", err.Error()) @@ -143,7 +143,7 @@ func main() { if err != nil { other.PrintError("Failed to initialize libmuttonserver directories: "+err.Error(), back.ErrorWrite) } - _ = os.MkdirAll(global.ConfigDir+global.PathSeparator+"deletions", 0700) // error ignored; failure would have occurred by this point in core.DirInit + _ = os.MkdirAll(global.CfgDir+global.PathSeparator+"deletions", 0700) // error ignored; failure would have occurred by this point in core.DirInit fmt.Println("libmuttonserver directories initialized") case "version": versionServer() diff --git a/syncclient/client.go b/syncclient/client.go index f01514d..0fea42b 100644 --- a/syncclient/client.go +++ b/syncclient/client.go @@ -10,7 +10,7 @@ import ( "github.com/pkg/sftp" "github.com/rwinkhart/go-boilerplate/back" - "github.com/rwinkhart/libmutton/cfg" + "github.com/rwinkhart/libmutton/config" "github.com/rwinkhart/libmutton/global" "github.com/rwinkhart/libmutton/synccommon" "golang.org/x/crypto/ssh" @@ -27,29 +27,29 @@ import ( // Only supports key-based authentication (passwords are supported for CLI-based implementations). func GetSSHClient() (*ssh.Client, bool, *bool, *string, *string, error) { // get SSH config info - config, err := cfg.LoadConfig() + cfg, err := config.Load() if err != nil { return nil, false, nil, nil, nil, errors.New("unable to parse SSH config: " + err.Error()) } - if *config.Libmutton.OfflineMode { + if *cfg.Libmutton.OfflineMode { return nil, true, nil, nil, nil, nil } // read private key - key, err := os.ReadFile(*config.Libmutton.SSHKeyPath) + key, err := os.ReadFile(*cfg.Libmutton.SSHKeyPath) if err != nil { - return nil, false, nil, nil, nil, errors.New("unable to read private key: " + *config.Libmutton.SSHKeyPath) + return nil, false, nil, nil, nil, errors.New("unable to read private key: " + *cfg.Libmutton.SSHKeyPath) } // parse private key var parsedKey ssh.Signer - if !*config.Libmutton.SSHKeyProtected { + if !*cfg.Libmutton.SSHKeyProtected { parsedKey, err = ssh.ParsePrivateKey(key) } else { parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, global.GetPassword("Enter password for your SSH keyfile:")) } if err != nil { - return nil, false, nil, nil, nil, errors.New("unable to parse private key: " + *config.Libmutton.SSHKeyPath) + return nil, false, nil, nil, nil, errors.New("unable to parse private key: " + *cfg.Libmutton.SSHKeyPath) } // read known hosts file @@ -60,8 +60,8 @@ func GetSSHClient() (*ssh.Client, bool, *bool, *string, *string, error) { } // configure SSH client - sshConfig := &ssh.ClientConfig{ - User: *config.Libmutton.SSHUser, + sshCfg := &ssh.ClientConfig{ + User: *cfg.Libmutton.SSHUser, Auth: []ssh.AuthMethod{ ssh.PublicKeys(parsedKey), }, @@ -70,12 +70,12 @@ func GetSSHClient() (*ssh.Client, bool, *bool, *string, *string, error) { } // connect to SSH server - sshClient, err := ssh.Dial("tcp", *config.Libmutton.SSHIP+":"+*config.Libmutton.SSHPort, sshConfig) + sshClient, err := ssh.Dial("tcp", *cfg.Libmutton.SSHIP+":"+*cfg.Libmutton.SSHPort, sshCfg) if err != nil { return nil, false, nil, nil, nil, errors.New("unable to connect to remote server: " + err.Error()) } - return sshClient, false, config.Libmutton.SSHIsWindows, config.Libmutton.SSHEntryRootPath, config.Libmutton.SSHAgeDirPath, nil + return sshClient, false, cfg.Libmutton.SSHIsWindows, cfg.Libmutton.SSHEntryRootPath, cfg.Libmutton.SSHAgeDirPath, nil } // GetSSHOutput runs a command over SSH and returns the output as a string. diff --git a/syncclient/oneOff.go b/syncclient/oneOff.go index 516323c..d1f95cc 100644 --- a/syncclient/oneOff.go +++ b/syncclient/oneOff.go @@ -175,8 +175,8 @@ func GenDeviceID(oldDeviceID, prefix string) (string, string, bool, error) { newDeviceID := prefix + "-" + stringy.StringGen(rand.Intn(32)+48, 0.2, 1) + "-" + strconv.FormatInt(time.Now().Unix(), 10) // create new device ID file (locally) - newDeviceIDPath := global.ConfigDir + global.PathSeparator + "devices" + global.PathSeparator + newDeviceID - oldDeviceIDPath := global.ConfigDir + global.PathSeparator + "devices" + global.PathSeparator + oldDeviceID + newDeviceIDPath := global.CfgDir + global.PathSeparator + "devices" + global.PathSeparator + newDeviceID + oldDeviceIDPath := global.CfgDir + global.PathSeparator + "devices" + global.PathSeparator + oldDeviceID f, err := os.OpenFile(newDeviceIDPath, os.O_CREATE|os.O_WRONLY, 0600) if err != nil { return "", "", false, errors.New("unable to create local device ID file: " + err.Error()) diff --git a/synccommon/common.go b/synccommon/common.go index cdfbc48..539973d 100644 --- a/synccommon/common.go +++ b/synccommon/common.go @@ -74,14 +74,14 @@ func ShearLocal(vanityPath, clientDeviceID string, onlyShearAgeFile bool) (strin for _, device := range deviceIDList { if device.Name() != clientDeviceID { if !onlyShearAgeFile { - f, err := os.OpenFile(global.ConfigDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"entry"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600) + f, err := os.OpenFile(global.CfgDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"entry"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600) if err != nil { // failure to add the target to the deletions list will exit the program and result in a client re-uploading the target (non-critical) return "", false, err } _ = f.Close() // error ignored; if the file could be created, it can probably be closed } - f, err := os.OpenFile(global.ConfigDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"age"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600) + f, err := os.OpenFile(global.CfgDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"age"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600) if err != nil { // failure to add the target to the deletions list will exit the program and result in a client re-uploading the target (non-critical) return "", false, err diff --git a/syncserver/server.go b/syncserver/server.go index 86dbe6c..aec7705 100644 --- a/syncserver/server.go +++ b/syncserver/server.go @@ -21,7 +21,7 @@ func GetRemoteDataFromServer(clientDeviceID string) { return } modList := synccommon.GetModTimes(entryList) - deletionsList, err := os.ReadDir(global.ConfigDir + global.PathSeparator + "deletions") + deletionsList, err := os.ReadDir(global.CfgDir + global.PathSeparator + "deletions") if err != nil { fmt.Printf("{\"errMsg\":\"%s\"}", err.Error()) return @@ -67,7 +67,7 @@ func GetRemoteDataFromServer(clientDeviceID string) { fetchResp.Deletions = append(fetchResp.Deletions, synccommon.Deletion{VanityPath: strings.ReplaceAll(affectedIDVanityPath[2], global.FSPath, "/"), IsAgeFile: isAgeFile}) // assume successful client deletion and remove deletions file (if assumption is somehow false, worst case scenario is that the client will re-upload the deleted entry) - err = os.RemoveAll(global.ConfigDir + global.PathSeparator + "deletions" + global.PathSeparator + deletion.Name()) // error ignored; function not run from a user-facing argument and thus the error would not be visible + err = os.RemoveAll(global.CfgDir + global.PathSeparator + "deletions" + global.PathSeparator + deletion.Name()) // error ignored; function not run from a user-facing argument and thus the error would not be visible if err != nil { fmt.Printf("{\"errMsg\":\"%s\"}", err.Error()) return