Files
filepass/internal/services/commands.go
2026-04-06 03:12:19 +09:00

62 lines
1.6 KiB
Go

package services
import (
"os/exec"
"strings"
)
const defaultPort = "22"
const defaultStoragePath = "~/.filepass_storage"
// shellQuote wraps s in single quotes, escaping any single quotes within it.
// This is safe for use in remote shell commands passed over SSH.
func shellQuote(s string) string {
return "'" + strings.ReplaceAll(s, "'", "'\\''") + "'"
}
func serverPort(s Server) string {
if s.Port == "" {
return defaultPort
}
return s.Port
}
// SSHCmd returns an exec.Cmd for running a single command on the server.
func SSHCmd(s Server, remoteCmd string) *exec.Cmd {
return exec.Command(
"ssh",
"-i", s.PrivateKey,
"-p", serverPort(s),
"-o", "StrictHostKeyChecking=no",
"-o", "BatchMode=yes",
s.User+"@"+s.Host,
remoteCmd,
)
}
// RsyncCmd returns an exec.Cmd for an rsync transfer.
// src and dst follow standard rsync syntax (local path or user@host:path).
func RsyncCmd(s Server, src, dst string) *exec.Cmd {
sshFlag := "ssh -i " + s.PrivateKey + " -p " + serverPort(s) +
" -o StrictHostKeyChecking=no -o BatchMode=yes"
return exec.Command(
"rsync",
"-avz",
"--partial",
"-e", sshFlag,
src,
dst,
)
}
// RemotePath returns the full remote rsync path for a filename inside storage.
// Only the filename is shell-quoted so ~ expands correctly on the remote shell.
func RemotePath(s Server, filename string) string {
return s.User + "@" + s.Host + ":" + defaultStoragePath + "/" + shellQuote(filename)
}
// RemoteStorageRoot returns the remote storage root for rsync operations.
func RemoteStorageRoot(s Server) string {
return s.User + "@" + s.Host + ":" + defaultStoragePath + "/"
}