mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-28 12:56:31 -04:00
125 lines
4.4 KiB
Go
125 lines
4.4 KiB
Go
package sync
|
|
|
|
import (
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/rwinkhart/libmutton/core"
|
|
)
|
|
|
|
// getModTimes returns a list of all entry modification times
|
|
func getModTimes(entryList []string) []int64 {
|
|
var modList []int64
|
|
for _, file := range entryList {
|
|
modTime, _ := os.Stat(core.TargetLocationFormat(file))
|
|
modList = append(modList, modTime.ModTime().Unix())
|
|
}
|
|
|
|
return modList
|
|
}
|
|
|
|
// genDeviceIDList returns a pointer to a slice of all registered device IDs
|
|
func genDeviceIDList() *[]fs.DirEntry {
|
|
// create a slice of all registered devices
|
|
deviceIDList, err := os.ReadDir(core.ConfigDir + core.PathSeparator + "devices")
|
|
if err != nil {
|
|
fmt.Println(core.AnsiError + "Failed to read the devices directory: " + err.Error() + core.AnsiReset)
|
|
os.Exit(1)
|
|
}
|
|
return &deviceIDList
|
|
}
|
|
|
|
// ShearLocal removes the target file or directory from the local system
|
|
// returns: deviceID (on client), for use in ShearRemoteFromClient
|
|
// if the local system is a server, it will also add the target to the deletions list for all clients (except the requesting client)
|
|
// this function should only be used directly by the server binary
|
|
func ShearLocal(targetLocationIncomplete, clientDeviceID string) string {
|
|
// determine if running on a server
|
|
var onServer bool
|
|
if clientDeviceID != "" {
|
|
onServer = true
|
|
}
|
|
|
|
deviceIDList := genDeviceIDList()
|
|
|
|
// add the sheared target (incomplete, vanity) to the deletions list (if running on a server)
|
|
if onServer {
|
|
for _, device := range *deviceIDList {
|
|
if device.Name() != clientDeviceID {
|
|
_, err := os.Create(core.ConfigDir + core.PathSeparator + "deletions" + core.PathSeparator + device.Name() + FSSpace + strings.ReplaceAll(targetLocationIncomplete, "/", FSPath))
|
|
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(1)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// get the full targetLocation path and remove the target
|
|
targetLocationComplete := core.TargetLocationFormat(targetLocationIncomplete)
|
|
if !onServer { // error if target does not exist on client, needed because os.RemoveAll does not return an error if target does not exist
|
|
core.TargetIsFile(targetLocationComplete, true, 0)
|
|
}
|
|
err := os.RemoveAll(targetLocationComplete)
|
|
if err != nil {
|
|
fmt.Println(core.AnsiError + "Failed to remove local target: " + err.Error() + core.AnsiReset)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if !onServer && len(*deviceIDList) > 0 { // return the device ID if running on the client and a device ID exists (online mode)
|
|
return (*deviceIDList)[0].Name()
|
|
}
|
|
return ""
|
|
|
|
// do not exit program, as this function is used as part of ShearRemoteFromClient
|
|
}
|
|
|
|
// RenameLocal renames oldLocationIncomplete to newLocationIncomplete on the local system
|
|
// this function should only be used directly by the server binary
|
|
func RenameLocal(oldLocationIncomplete, newLocationIncomplete string, verifyOldLocationExists bool) {
|
|
// get full paths for both locations
|
|
oldLocation := core.TargetLocationFormat(oldLocationIncomplete)
|
|
newLocation := core.TargetLocationFormat(newLocationIncomplete)
|
|
|
|
if verifyOldLocationExists {
|
|
core.TargetIsFile(oldLocation, true, 0)
|
|
}
|
|
|
|
// ensure newLocation does not exist
|
|
_, isAccessible := core.TargetIsFile(newLocation, false, 0)
|
|
if isAccessible {
|
|
fmt.Println(core.AnsiError + "\"" + newLocation + "\" already exists" + core.AnsiReset)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// rename oldLocation to newLocation
|
|
err := os.Rename(oldLocation, newLocation)
|
|
if err != nil {
|
|
fmt.Println(core.AnsiError + "Failed to rename - does the target containing directory exist?" + core.AnsiReset)
|
|
}
|
|
|
|
// do not exit program, as this function is used as part of RenameRemoteFromClient
|
|
}
|
|
|
|
// AddFolderLocal creates a new entry-containing directory on the local system
|
|
// this function should only be used directly by the server binary
|
|
func AddFolderLocal(targetLocationIncomplete string) {
|
|
// get the full targetLocation path and create the target
|
|
targetLocationComplete := core.TargetLocationFormat(targetLocationIncomplete)
|
|
err := os.Mkdir(targetLocationComplete, 0700)
|
|
if err != nil {
|
|
if os.IsExist(err) {
|
|
fmt.Println(core.AnsiError + "Directory already exists" + core.AnsiReset)
|
|
os.Exit(1)
|
|
} else {
|
|
fmt.Println(core.AnsiError + "Failed to create directory: " + err.Error() + core.AnsiReset)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// do not exit program, as this function is used as part of AddFolderRemoteFromClient
|
|
}
|