feat: add --remote-dir flag and use ssh alias as mount label
Update PKGBUILD version / update-pkgver (push) Successful in 3s
Update PKGBUILD version / update-pkgver (push) Successful in 3s
- New `-r` / `--remote-dir` flag to mount a specific remote subdirectory; empty default preserves prior home-dir behaviour. - Validate the flag value via a dedicated `rxRemoteDir` allowlist before it reaches the sshfs argv. - Use the ssh_config alias (not the resolved HostName) as the local mountpoint name and as the sshfs source. File managers now show the human-readable label instead of the raw IP. - Validate `args[0]` against `rxHostUser` since it now flows into argv. - Rename `verify_mount_dir` parameter `hostname -> name` and `mount_sshfs` first parameter `hostname -> alias` for clarity.
This commit is contained in:
@@ -20,13 +20,20 @@ import (
|
||||
var (
|
||||
rxHostUser = regexp.MustCompile(`^[A-Za-z0-9_][A-Za-z0-9._-]*$`)
|
||||
rxIdentityFile = regexp.MustCompile(`^[A-Za-z0-9/~][A-Za-z0-9._@/:+=~%-]*$`)
|
||||
rxRemoteDir = regexp.MustCompile(`^[A-Za-z0-9/~][A-Za-z0-9._/~-]*$`)
|
||||
)
|
||||
|
||||
var (
|
||||
eFlag = flag.Bool("e", false, "open mountpoint in your editor")
|
||||
vFlag = flag.Bool("v", false, "verbose: print resolved ssh_config fields")
|
||||
rDir string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&rDir, "r", "", "remote directory to mount (default: remote home)")
|
||||
flag.StringVar(&rDir, "remote-dir", "", "remote directory to mount (default: remote home)")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
@@ -43,6 +50,12 @@ func main() {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
alias := args[0]
|
||||
if err := validate_ssh_field("alias", alias, rxHostUser); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
hostname, err := lookup_ssh_field(args[0], "HostName")
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
@@ -96,8 +109,14 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, "ssh config Port %q is not a valid port number\n", port)
|
||||
os.Exit(3)
|
||||
}
|
||||
if rDir != "" {
|
||||
if err := validate_ssh_field("remote-dir", rDir, rxRemoteDir); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(3)
|
||||
}
|
||||
}
|
||||
|
||||
mount, err := verify_mount_dir(hostname)
|
||||
mount, err := verify_mount_dir(alias)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "verify_mount_dir() failed:", err)
|
||||
os.Exit(4)
|
||||
@@ -109,6 +128,9 @@ func main() {
|
||||
fmt.Println("Port: ", port)
|
||||
fmt.Println("Ifile: ", ifile)
|
||||
fmt.Println("Mount: ", mount)
|
||||
if rDir != "" {
|
||||
fmt.Println("Remote: ", rDir)
|
||||
}
|
||||
fmt.Println("---")
|
||||
} else {
|
||||
fmt.Println("Mount: ", mount)
|
||||
@@ -120,7 +142,7 @@ func main() {
|
||||
os.Exit(5)
|
||||
}
|
||||
if !chkmount {
|
||||
if err := mount_sshfs(hostname, user, ifile, port, mount); err != nil {
|
||||
if err := mount_sshfs(alias, user, ifile, port, mount, rDir); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "mount_sshfs() failed:", err)
|
||||
os.Exit(6)
|
||||
}
|
||||
@@ -160,7 +182,7 @@ func run_editor(mount string) error {
|
||||
return cmd.Start()
|
||||
}
|
||||
|
||||
func verify_mount_dir(hostname string) (string, error) {
|
||||
func verify_mount_dir(name string) (string, error) {
|
||||
homedir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve home dir: %w", err)
|
||||
@@ -173,9 +195,9 @@ func verify_mount_dir(hostname string) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("resolve base %q: %w", base, err)
|
||||
}
|
||||
mount := filepath.Clean(filepath.Join(realBase, hostname))
|
||||
mount := filepath.Clean(filepath.Join(realBase, name))
|
||||
if !strings.HasPrefix(mount, realBase+string(os.PathSeparator)) {
|
||||
return "", fmt.Errorf("hostname %q escapes mount base %q", hostname, realBase)
|
||||
return "", fmt.Errorf("name %q escapes mount base %q", name, realBase)
|
||||
}
|
||||
if info, err := os.Lstat(mount); err == nil && info.Mode()&os.ModeSymlink != 0 {
|
||||
return "", fmt.Errorf("mount path %q is a symlink", mount)
|
||||
@@ -186,7 +208,7 @@ func verify_mount_dir(hostname string) (string, error) {
|
||||
return mount, nil
|
||||
}
|
||||
|
||||
func mount_sshfs(hostname string, user string, ifile string, port string, mount string) error {
|
||||
func mount_sshfs(alias string, user string, ifile string, port string, mount string, remoteDir string) error {
|
||||
cmd := exec.Command("sshfs", "-p", port,
|
||||
"-o", "IdentityFile="+ifile,
|
||||
"-o", "idmap=user",
|
||||
@@ -201,7 +223,7 @@ func mount_sshfs(hostname string, user string, ifile string, port string, mount
|
||||
"-o", "StrictHostKeyChecking=accept-new",
|
||||
"-o", "ServerAliveInterval=15",
|
||||
"-o", "ServerAliveCountMax=3",
|
||||
user+"@"+hostname+":", mount)
|
||||
user+"@"+alias+":"+remoteDir, mount)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
|
||||
Reference in New Issue
Block a user