From 4c54349b3929d7cc89e9fa051b89eaa6f4aeb6f0 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Tue, 13 Aug 2024 20:48:20 -0400 Subject: [PATCH] Assign error-specific exit codes to constants --- core/1globals.go | 26 ++++++++++----------- core/configParser.go | 8 +++---- core/copy.go | 6 ++--- core/copyDARWIN.go | 8 +++---- core/copyTERMUX.go | 8 +++---- core/copyUNIXGeneric.go | 12 +++++----- core/copyWIN.go | 8 +++---- core/gpg.go | 4 ++-- core/init.go | 8 +++---- core/utilitiesMisc.go | 14 +++++------ sync/client.go | 52 ++++++++++++++++++++--------------------- sync/common.go | 10 ++++---- sync/commonUNIX.go | 2 +- sync/commonWIN.go | 2 +- sync/init.go | 6 ++--- sync/oneOff.go | 6 ++--- sync/server.go | 2 +- 17 files changed, 90 insertions(+), 92 deletions(-) diff --git a/core/1globals.go b/core/1globals.go index 9734e0c..1a9e847 100644 --- a/core/1globals.go +++ b/core/1globals.go @@ -16,19 +16,17 @@ const ( AnsiError = "\033[38;5;9m" AnsiReset = "\033[0m" + ErrorRead = 101 + ErrorWrite = 102 + ErrorSyncProcess = 103 + ErrorServerConnection = 104 + ErrorTargetNotFound = 105 + ErrorTargetExists = 106 + ErrorTargetWrongType = 107 + ErrorDecryption = 108 + ErrorEncryption = 109 + ErrorClipboard = 110 + ErrorOther = 111 + LibmuttonVersion = "0.2.B" // untagged releases feature a letter suffix corresponding to the eventual release version, e.g "0.2.A" -> "0.2.0", "0.2.B" -> "0.2.1" ) - -// numeric error codes legend -// 0: no error -// 101: read error -// 102: write error -// 103: sync process error -// 104: server connection error -// 105: target not found -// 106: target already exists -// 107: target wrong type (file/directory) -// 108: decryption error -// 109: encryption error -// 110: clipboard error -// 111: other error diff --git a/core/configParser.go b/core/configParser.go index 2b07ecb..1a91579 100644 --- a/core/configParser.go +++ b/core/configParser.go @@ -14,7 +14,7 @@ func loadConfig() *ini.File { cfg, err := ini.Load(ConfigPath) if err != nil { fmt.Println(AnsiError+"Failed to load libmutton.ini:", err.Error()+AnsiReset) - os.Exit(101) + os.Exit(ErrorRead) } return cfg } @@ -41,7 +41,7 @@ func ParseConfig(valuesRequested [][2]string, missingValueError string) []string default: fmt.Println(AnsiError + missingValueError + AnsiReset) } - os.Exit(101) + os.Exit(ErrorRead) } config = append(config, value) @@ -58,7 +58,7 @@ func GenDeviceIDList(errorOnFail bool) *[]fs.DirEntry { if err != nil { if errorOnFail { fmt.Println(AnsiError+"Failed to read the devices directory:", err.Error()+AnsiReset) - os.Exit(101) + os.Exit(ErrorRead) } else { return nil // a nil return value indicates that the devices directory could not be read/does not exist } @@ -98,6 +98,6 @@ func WriteConfig(valuesToWrite [][3]string, append bool) { err := cfg.SaveTo(ConfigPath) if err != nil { fmt.Println(AnsiError+"Failed to save libmutton.ini:", err.Error()+AnsiReset) - os.Exit(102) + os.Exit(ErrorWrite) } } diff --git a/core/copy.go b/core/copy.go index 6ec278e..05743a3 100644 --- a/core/copy.go +++ b/core/copy.go @@ -24,7 +24,7 @@ func CopyArgument(executableName, targetLocation string, field int) { // ensure field is not empty if decryptedEntry[field] == "" { fmt.Println(AnsiError + "Field is empty" + AnsiReset) - os.Exit(105) + os.Exit(ErrorTargetNotFound) } if field != 2 { @@ -51,7 +51,7 @@ func CopyArgument(executableName, targetLocation string, field int) { } } else { fmt.Println(AnsiError + "Field does not exist in entry" + AnsiReset) - os.Exit(105) + os.Exit(ErrorTargetNotFound) } // copy field to clipboard, launch clipboard clearing process @@ -84,7 +84,7 @@ func GenTOTP(secret string, time time.Time, forSteam bool) string { if err != nil { fmt.Println(AnsiError + "Error generating TOTP code" + AnsiReset) - os.Exit(111) + os.Exit(ErrorOther) } return totpToken diff --git a/core/copyDARWIN.go b/core/copyDARWIN.go index e3fac23..d239070 100644 --- a/core/copyDARWIN.go +++ b/core/copyDARWIN.go @@ -17,7 +17,7 @@ func copyField(executableName, copySubject string) { err := cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to copy to clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } // launch clipboard clearing process if executableName is provided @@ -27,7 +27,7 @@ func copyField(executableName, copySubject string) { err = cmd.Start() if err != nil { fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - Does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } Exit(0) // only exit if clipboard clearing process is launched, otherwise assume continuous clipboard refresh } @@ -41,7 +41,7 @@ func clipClear(oldContents string) { newContents, err := cmd.Output() if err != nil { fmt.Println(AnsiError+"Failed to read clipboard contents:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } if oldContents == strings.TrimRight(string(newContents), "\r\n") { @@ -50,7 +50,7 @@ func clipClear(oldContents string) { err = cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to clear clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } } os.Exit(0) // use os.Exit instead of core.Exit, as this function runs out of a background subprocess that is invisible to the user (will never appear in GUI/TUI environment) diff --git a/core/copyTERMUX.go b/core/copyTERMUX.go index 904ffb1..e513817 100644 --- a/core/copyTERMUX.go +++ b/core/copyTERMUX.go @@ -17,7 +17,7 @@ func copyField(executableName, copySubject string) { err := cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to copy to clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } // launch clipboard clearing process if executableName is provided @@ -27,7 +27,7 @@ func copyField(executableName, copySubject string) { err = cmd.Start() if err != nil { fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - Does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } Exit(0) // only exit if clipboard clearing process is launched, otherwise assume continuous clipboard refresh } @@ -41,7 +41,7 @@ func clipClear(oldContents string) { newContents, err := cmd.Output() if err != nil { fmt.Println(AnsiError+"Failed to read clipboard contents:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } if oldContents == strings.TrimRight(string(newContents), "\r\n") { @@ -50,7 +50,7 @@ func clipClear(oldContents string) { err = cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to clear clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } } os.Exit(0) // use os.Exit instead of core.Exit, as this function runs out of a background subprocess that is invisible to the user (will never appear in GUI/TUI environment) diff --git a/core/copyUNIXGeneric.go b/core/copyUNIXGeneric.go index 6e51f38..2312ab2 100644 --- a/core/copyUNIXGeneric.go +++ b/core/copyUNIXGeneric.go @@ -21,14 +21,14 @@ func copyField(executableName, copySubject string) { cmd = exec.Command("xclip", "-sel", "c") } else { fmt.Println(AnsiError + "Clipboard platform could not be determined - Note that the clipboard does not function in a raw TTY" + AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } writeToStdin(cmd, copySubject) err := cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to copy to clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } // launch clipboard clearing process if executableName is provided @@ -38,7 +38,7 @@ func copyField(executableName, copySubject string) { err = cmd.Start() if err != nil { fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - Does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } Exit(0) // only exit if clipboard clearing process is launched, otherwise assume continuous clipboard refresh } @@ -59,14 +59,14 @@ func clipClear(oldContents string) { cmdPaste = exec.Command("xclip", "-o", "-sel", "c") } else { fmt.Println(AnsiError + "Clipboard platform could not be determined - Neither $WAYLAND_DISPLAY nor $DISPLAY are set" + AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } // read current clipboard contents newContents, err := cmdPaste.Output() if err != nil { fmt.Println(AnsiError+"Failed to read clipboard contents:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } // clear clipboard if contents have not been modified @@ -74,7 +74,7 @@ func clipClear(oldContents string) { err = cmdClear.Run() if err != nil { fmt.Println(AnsiError+"Failed to clear clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } } os.Exit(0) // use os.Exit instead of core.Exit, as this function runs out of a background subprocess that is invisible to the user (will never appear in GUI/TUI environment) diff --git a/core/copyWIN.go b/core/copyWIN.go index 096f3cf..f2f69d1 100644 --- a/core/copyWIN.go +++ b/core/copyWIN.go @@ -16,7 +16,7 @@ func copyField(executableName, copySubject string) { err := cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to copy to clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } // launch clipboard clearing process if executableName is provided @@ -26,7 +26,7 @@ func copyField(executableName, copySubject string) { err = cmd.Start() if err != nil { fmt.Println(AnsiError + "Failed to launch automated clipboard clearing process - Does this libmutton implementation support the \"clipclear\" argument?" + AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } Exit(0) // only exit if clipboard clearing process is launched, otherwise assume continuous clipboard refresh } @@ -40,7 +40,7 @@ func clipClear(oldContents string) { newContents, err := cmd.Output() if err != nil { fmt.Println(AnsiError+"Failed to read clipboard contents:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } if oldContents == strings.TrimRight(string(newContents), "\r\n") { @@ -48,7 +48,7 @@ func clipClear(oldContents string) { err = cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to clear clipboard:", err.Error()+AnsiReset) - os.Exit(110) + os.Exit(ErrorClipboard) } } os.Exit(0) // use os.Exit instead of core.Exit, as this function runs out of a background subprocess that is invisible to the user (will never appear in GUI/TUI environment) diff --git a/core/gpg.go b/core/gpg.go index 44a8b72..fac86a3 100644 --- a/core/gpg.go +++ b/core/gpg.go @@ -19,7 +19,7 @@ func DecryptGPG(targetLocation string) []string { if err != nil { fmt.Println(AnsiError + "Failed to decrypt \"" + targetLocation + "\" - Ensure it is a valid GPG-encrypted file and that you entered your passphrase correctly" + AnsiReset) - os.Exit(108) + os.Exit(ErrorDecryption) } outputSlice := strings.Split(string(output), "\n") @@ -33,7 +33,7 @@ func EncryptGPG(input []string) []byte { encryptedBytes, err := cmd.Output() if err != nil { fmt.Println(AnsiError + "Failed to encrypt data - Ensure that your GPG key is valid and that you have a valid GPG ID set in libmutton.ini" + AnsiReset) - os.Exit(109) + os.Exit(ErrorEncryption) } return encryptedBytes } diff --git a/core/init.go b/core/init.go index f3ee4e0..8cce7c5 100644 --- a/core/init.go +++ b/core/init.go @@ -46,7 +46,7 @@ func GpgKeyGen() string { err := cmd.Run() if err != nil { fmt.Println(AnsiError+"Failed to generate GPG key:", err.Error()+AnsiReset) - os.Exit(111) + os.Exit(ErrorOther) } return "libmutton-" + unixTime + " (gpg-libmutton) " @@ -59,7 +59,7 @@ func DirInit(preserveOldConfigDir bool) string { err := os.MkdirAll(EntryRoot, 0700) if err != nil { fmt.Println(AnsiError+"Failed to create \""+EntryRoot+"\":", err.Error()+AnsiReset) - os.Exit(102) + os.Exit(ErrorWrite) } // get old device ID before its potential removal @@ -78,7 +78,7 @@ func DirInit(preserveOldConfigDir bool) string { err = os.RemoveAll(ConfigDir) if err != nil { fmt.Println(AnsiError+"Failed to remove existing config directory:", err.Error()+AnsiReset) - os.Exit(102) + os.Exit(ErrorWrite) } } } @@ -87,7 +87,7 @@ func DirInit(preserveOldConfigDir bool) string { err = os.MkdirAll(ConfigDir+PathSeparator+"devices", 0700) if err != nil { fmt.Println(AnsiError+"Failed to create \""+ConfigDir+"\":", err.Error()+AnsiReset) - os.Exit(102) + os.Exit(ErrorWrite) } return oldDeviceID diff --git a/core/utilitiesMisc.go b/core/utilitiesMisc.go index 60b8b56..73ec35b 100644 --- a/core/utilitiesMisc.go +++ b/core/utilitiesMisc.go @@ -19,20 +19,20 @@ func TargetIsFile(targetLocation string, errorOnFail bool, failCondition uint8) if err != nil { if errorOnFail { fmt.Println(AnsiError + "Failed to access \"" + targetLocation + "\" - Ensure it exists and has the correct permissions" + AnsiReset) - os.Exit(105) + os.Exit(ErrorTargetNotFound) } return false, false } if targetInfo.IsDir() { if errorOnFail && failCondition == 2 { fmt.Println(AnsiError + "\"" + targetLocation + "\" is a directory" + AnsiReset) - os.Exit(107) + os.Exit(ErrorTargetWrongType) } return false, true } else { if errorOnFail && failCondition == 1 { fmt.Println(AnsiError + "\"" + targetLocation + "\" is a file" + AnsiReset) - os.Exit(107) + os.Exit(ErrorTargetWrongType) } return true, true } @@ -44,7 +44,7 @@ func WriteEntry(targetLocation string, entryData []string, verifyEntryDoesNotExi _, isAccessible := TargetIsFile(targetLocation, false, 0) if isAccessible { fmt.Println(AnsiError + "Target location already exists" + AnsiReset) - os.Exit(106) + os.Exit(ErrorTargetExists) } } @@ -52,7 +52,7 @@ func WriteEntry(targetLocation string, entryData []string, verifyEntryDoesNotExi err := os.WriteFile(targetLocation, encryptedBytes, 0600) if err != nil { fmt.Println(AnsiError+"Failed to write to file:", err.Error()+AnsiReset) - os.Exit(102) + os.Exit(ErrorWrite) } } @@ -61,7 +61,7 @@ func writeToStdin(cmd *exec.Cmd, input string) { stdin, err := cmd.StdinPipe() if err != nil { fmt.Println(AnsiError+"Failed to access stdin for system command:", err.Error()+AnsiReset) - os.Exit(111) + os.Exit(ErrorOther) } go func() { @@ -77,7 +77,7 @@ func CreateTempFile() *os.File { tempFile, err := os.CreateTemp("", "*.markdown") if err != nil { fmt.Println(AnsiError+"Failed to create temporary file:", err.Error()+AnsiReset) - os.Exit(102) + os.Exit(ErrorWrite) } return tempFile } diff --git a/sync/client.go b/sync/client.go index 20aeb87..3c7974a 100644 --- a/sync/client.go +++ b/sync/client.go @@ -54,7 +54,7 @@ func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) { isWindows, err = strconv.ParseBool(key) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to parse server OS type:", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } } } @@ -63,7 +63,7 @@ func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) { key, err := os.ReadFile(keyFile) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to read private key file:", keyFile+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } // parse private key @@ -75,7 +75,7 @@ func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) { } if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to parse private key:", keyFile+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } // read known hosts file @@ -83,7 +83,7 @@ func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) { hostKeyCallback, err = knownhosts.New(core.Home + core.PathSeparator + ".ssh" + core.PathSeparator + "known_hosts") if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to read known hosts file:", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } // configure SSH client @@ -99,7 +99,7 @@ func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) { sshClient, err := ssh.Dial("tcp", ip+":"+port, sshConfig) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to connect to remote server:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } return sshClient, entryRoot, isWindows @@ -111,7 +111,7 @@ func GetSSHOutput(sshClient *ssh.Client, cmd, stdin string) string { sshSession, err := sshClient.NewSession() if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to establish SSH session:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } // provide stdin data for session @@ -122,7 +122,7 @@ func GetSSHOutput(sshClient *ssh.Client, cmd, stdin string) string { output, err = sshSession.CombinedOutput(cmd) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to run SSH command:", err.Error()+core.AnsiReset) - os.Exit(103) + os.Exit(core.ErrorSyncProcess) } // convert the output to a string and remove leading/trailing whitespace @@ -139,7 +139,7 @@ func getRemoteDataFromClient(sshClient *ssh.Client, manualSync bool) (map[string if len(*deviceIDList) == 0 { if manualSync { fmt.Println(joinErrorWithEXE("Sync failed - No device ID found; run \"", " init\" to generate a device ID")) - os.Exit(105) + os.Exit(core.ErrorTargetNotFound) } else { core.Exit(0) // exit silently if the sync job was called automatically, as the user may just be in offline mode } @@ -153,12 +153,12 @@ func getRemoteDataFromClient(sshClient *ssh.Client, manualSync bool) (map[string // parse output/re-form lists if len(outputSlice) != 5 { // ensure information from server is complete fmt.Println(core.AnsiError + "Sync failed - Unable to fetch remote data; server returned an unexpected response" + core.AnsiReset) - os.Exit(103) + os.Exit(core.ErrorSyncProcess) } serverTime, err := strconv.ParseInt(outputSlice[0], 10, 64) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to parse server time:", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } entries := strings.Split(outputSlice[1], core.FSMisc)[1:] modsStrings := strings.Split(outputSlice[2], core.FSMisc)[1:] @@ -172,7 +172,7 @@ func getRemoteDataFromClient(sshClient *ssh.Client, manualSync bool) (map[string mod, err = strconv.ParseInt(modString, 10, 64) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to parse mod time:", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } mods = append(mods, mod) } @@ -219,13 +219,13 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow sftpClient, err := sftp.NewClient(sshClient) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to establish SFTP session:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } defer func(sftpClient *sftp.Client) { err = sftpClient.Close() if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to close SFTP client:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } }(sftpClient) @@ -244,7 +244,7 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow fileInfo, err = sftpClient.Stat(remoteEntryFullPath) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to get remote file info (mod time):", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } modTime := fileInfo.ModTime() @@ -253,7 +253,7 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow remoteFile, err = sftpClient.Open(remoteEntryFullPath) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to open remote file:", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } // store path to local entry @@ -264,14 +264,14 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow localFile, err = os.OpenFile(localEntryFullPath, os.O_CREATE|os.O_WRONLY, 0600) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to create local file:", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } // download the file _, err = remoteFile.WriteTo(localFile) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to download remote file:", err.Error()+core.AnsiReset) - os.Exit(103) + os.Exit(core.ErrorSyncProcess) } // close the files @@ -301,7 +301,7 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow fileInfo, err = os.Stat(localEntryFullPath) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to get local file info (mod time):", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } modTime := fileInfo.ModTime() @@ -310,7 +310,7 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow localFile, err = os.Open(localEntryFullPath) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to open local file:", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } // store path to remote entry @@ -321,14 +321,14 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow remoteFile, err = sftpClient.OpenFile(remoteEntryFullPath, os.O_CREATE|os.O_WRONLY) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to create remote file ("+remoteEntryFullPath+"):", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } // upload the file _, err = localFile.WriteTo(remoteFile) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to upload local file:", err.Error()+core.AnsiReset) - os.Exit(103) + os.Exit(core.ErrorSyncProcess) } // close the files @@ -339,7 +339,7 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow err = sftpClient.Chmod(remoteEntryFullPath, 0600) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to set permissions on remote file:", err.Error()+core.AnsiReset) - os.Exit(103) + os.Exit(core.ErrorSyncProcess) } // set the modification time of the remote file to match the value saved from the local file (from before the upload) @@ -404,7 +404,7 @@ func deletionSync(deletions []string) { err := os.RemoveAll(core.TargetLocationFormat(deletion)) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Failed to shear "+deletion+" locally:", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } } @@ -426,11 +426,11 @@ func folderSync(folders []string) { err := os.MkdirAll(folderFullPath, 0700) if err != nil { fmt.Println(core.AnsiError+"Sync failed - Failed to create folder \""+folder+"\":", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } } else if isFile { fmt.Println(core.AnsiError + "Sync failed - Failed to create folder \"" + folder + "\" - A file with the same name already exists" + core.AnsiReset) - os.Exit(106) + os.Exit(core.ErrorTargetExists) } } } @@ -444,7 +444,7 @@ func RunJob(manualSync bool) { err := sshClient.Close() if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to close SSH client:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } }(sshClient) diff --git a/sync/common.go b/sync/common.go index b74240b..dad09b7 100644 --- a/sync/common.go +++ b/sync/common.go @@ -40,7 +40,7 @@ func ShearLocal(targetLocationIncomplete, clientDeviceID string) string { if err != nil { // do not print error as there is currently no way of seeing server-side errors // failure to add the target to the deletions list will exit the program and result in a client re-uploading the target (non-critical) - os.Exit(102) + os.Exit(core.ErrorWrite) } _ = fileToClose.Close() // error ignored; if the file could be created, it can probably be closed } @@ -55,7 +55,7 @@ func ShearLocal(targetLocationIncomplete, clientDeviceID string) string { err := os.RemoveAll(targetLocationComplete) if err != nil { fmt.Println(core.AnsiError+"Failed to remove local target:", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } if !onServer && len(*deviceIDList) > 0 { // return the device ID if running on the client and a device ID exists (online mode) @@ -81,7 +81,7 @@ func RenameLocal(oldLocationIncomplete, newLocationIncomplete string, verifyOldL _, isAccessible := core.TargetIsFile(newLocation, false, 0) if isAccessible { fmt.Println(core.AnsiError + "\"" + newLocation + "\" already exists" + core.AnsiReset) - os.Exit(106) + os.Exit(core.ErrorTargetExists) } // rename oldLocation to newLocation @@ -102,10 +102,10 @@ func AddFolderLocal(targetLocationIncomplete string) { if err != nil { if os.IsExist(err) { fmt.Println(core.AnsiError + "Directory already exists" + core.AnsiReset) - os.Exit(106) + os.Exit(core.ErrorTargetExists) } else { fmt.Println(core.AnsiError+"Failed to create directory:", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } } diff --git a/sync/commonUNIX.go b/sync/commonUNIX.go index 9727b01..46aa735 100644 --- a/sync/commonUNIX.go +++ b/sync/commonUNIX.go @@ -30,7 +30,7 @@ func WalkEntryDir() ([]string, []string) { // otherwise, print the source of the error fmt.Println(core.AnsiError+"An unexpected error occurred while generating the entry list:", err.Error()+core.AnsiReset) } - os.Exit(111) + os.Exit(core.ErrorOther) } // trim root path from each path before storing diff --git a/sync/commonWIN.go b/sync/commonWIN.go index c26da70..ea7558b 100644 --- a/sync/commonWIN.go +++ b/sync/commonWIN.go @@ -31,7 +31,7 @@ func WalkEntryDir() ([]string, []string) { // otherwise, print the source of the error fmt.Println(core.AnsiError+"An unexpected error occurred while generating the entry list:", err.Error()+core.AnsiReset) } - os.Exit(111) + os.Exit(core.ErrorOther) } // trim root path from each path before storing and replace backslashes with forward slashes diff --git a/sync/init.go b/sync/init.go index fcdd3ec..109f262 100644 --- a/sync/init.go +++ b/sync/init.go @@ -25,7 +25,7 @@ func DeviceIDGen(oldDeviceID string) (string, string) { fileToClose, err := os.OpenFile(core.ConfigDir+core.PathSeparator+"devices"+core.PathSeparator+newDeviceID, os.O_CREATE|os.O_WRONLY, 0600) if err != nil { fmt.Println(core.AnsiError+"Failed to create local device ID file:", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } _ = fileToClose.Close() // error ignored; if the file could be created, it can probably be closed @@ -37,14 +37,14 @@ func DeviceIDGen(oldDeviceID string) (string, string) { err = sshClient.Close() if err != nil { fmt.Println(core.AnsiError+"Init failed - Unable to close SSH client:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } // remove old device ID file (locally; may not exist) err = os.RemoveAll(core.ConfigDir + core.PathSeparator + "devices" + core.PathSeparator + oldDeviceID) if err != nil { fmt.Println(core.AnsiError+"Failed to remove old device ID file (locally):", err.Error()+core.AnsiReset) - os.Exit(102) + os.Exit(core.ErrorWrite) } return sshEntryRootSSHIsWindows[0], sshEntryRootSSHIsWindows[1] diff --git a/sync/oneOff.go b/sync/oneOff.go index c18d089..f4103ea 100644 --- a/sync/oneOff.go +++ b/sync/oneOff.go @@ -24,7 +24,7 @@ func ShearRemoteFromClient(targetLocationIncomplete string) { err := sshClient.Close() if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to close SSH client:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } } @@ -51,7 +51,7 @@ func RenameRemoteFromClient(oldLocationIncomplete, newLocationIncomplete string) err := sshClient.Close() if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to close SSH client:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } } @@ -75,7 +75,7 @@ func AddFolderRemoteFromClient(targetLocationIncomplete string) { err := sshClient.Close() if err != nil { fmt.Println(core.AnsiError+"Sync failed - Unable to close SSH client:", err.Error()+core.AnsiReset) - os.Exit(104) + os.Exit(core.ErrorServerConnection) } } diff --git a/sync/server.go b/sync/server.go index 07e311b..1f9eb40 100644 --- a/sync/server.go +++ b/sync/server.go @@ -18,7 +18,7 @@ func GetRemoteDataFromServer(clientDeviceID string) { deletionsList, err := os.ReadDir(core.ConfigDir + core.PathSeparator + "deletions") if err != nil { fmt.Println(core.AnsiError+"Failed to read the deletions directory:", err.Error()+core.AnsiReset) - os.Exit(101) + os.Exit(core.ErrorRead) } // print the current UNIX timestamp to stdout