mirror of
https://github.com/tailscale/tailscale.git
synced 2025-12-24 01:26:39 +00:00
feature/taildrop: move rest of Taildrop out of LocalBackend
Updates #12614 Change-Id: If451dec1d796f6a4216fe485975c87f0c62a53e5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Co-authored-by: Nick Khyl <nickk@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
cf6a593196
commit
068d5ab655
131
feature/taildrop/paths.go
Normal file
131
feature/taildrop/paths.go
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package taildrop
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"tailscale.com/version/distro"
|
||||
)
|
||||
|
||||
// SetDirectFileRoot sets the directory where received files are written.
|
||||
//
|
||||
// This must be called before Tailscale is started.
|
||||
func (e *Extension) SetDirectFileRoot(root string) {
|
||||
e.directFileRoot = root
|
||||
}
|
||||
|
||||
func (e *Extension) setPlatformDefaultDirectFileRoot() {
|
||||
dg := distro.Get()
|
||||
|
||||
switch dg {
|
||||
case distro.Synology, distro.TrueNAS, distro.QNAP, distro.Unraid:
|
||||
// See if they have a "Taildrop" share.
|
||||
// See https://github.com/tailscale/tailscale/issues/2179#issuecomment-982821319
|
||||
path, err := findTaildropDir(dg)
|
||||
if err != nil {
|
||||
e.logf("%s Taildrop support: %v", dg, err)
|
||||
} else {
|
||||
e.logf("%s Taildrop: using %v", dg, path)
|
||||
e.directFileRoot = path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func findTaildropDir(dg distro.Distro) (string, error) {
|
||||
const name = "Taildrop"
|
||||
switch dg {
|
||||
case distro.Synology:
|
||||
return findSynologyTaildropDir(name)
|
||||
case distro.TrueNAS:
|
||||
return findTrueNASTaildropDir(name)
|
||||
case distro.QNAP:
|
||||
return findQnapTaildropDir(name)
|
||||
case distro.Unraid:
|
||||
return findUnraidTaildropDir(name)
|
||||
}
|
||||
return "", fmt.Errorf("%s is an unsupported distro for Taildrop dir", dg)
|
||||
}
|
||||
|
||||
// findSynologyTaildropDir looks for the first volume containing a
|
||||
// "Taildrop" directory. We'd run "synoshare --get Taildrop" command
|
||||
// but on DSM7 at least, we lack permissions to run that.
|
||||
func findSynologyTaildropDir(name string) (dir string, err error) {
|
||||
for i := 1; i <= 16; i++ {
|
||||
dir = fmt.Sprintf("/volume%v/%s", i, name)
|
||||
if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
|
||||
return dir, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("shared folder %q not found", name)
|
||||
}
|
||||
|
||||
// findTrueNASTaildropDir returns the first matching directory of
|
||||
// /mnt/{name} or /mnt/*/{name}
|
||||
func findTrueNASTaildropDir(name string) (dir string, err error) {
|
||||
// If we're running in a jail, a mount point could just be added at /mnt/Taildrop
|
||||
dir = fmt.Sprintf("/mnt/%s", name)
|
||||
if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
// but if running on the host, it may be something like /mnt/Primary/Taildrop
|
||||
fis, err := os.ReadDir("/mnt")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error reading /mnt: %w", err)
|
||||
}
|
||||
for _, fi := range fis {
|
||||
dir = fmt.Sprintf("/mnt/%s/%s", fi.Name(), name)
|
||||
if fi, err := os.Stat(dir); err == nil && fi.IsDir() {
|
||||
return dir, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("shared folder %q not found", name)
|
||||
}
|
||||
|
||||
// findQnapTaildropDir checks if a Shared Folder named "Taildrop" exists.
|
||||
func findQnapTaildropDir(name string) (string, error) {
|
||||
dir := fmt.Sprintf("/share/%s", name)
|
||||
fi, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("shared folder %q not found", name)
|
||||
}
|
||||
if fi.IsDir() {
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
// share/Taildrop is usually a symlink to CACHEDEV1_DATA/Taildrop/ or some such.
|
||||
fullpath, err := filepath.EvalSymlinks(dir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("symlink to shared folder %q not found", name)
|
||||
}
|
||||
if fi, err = os.Stat(fullpath); err == nil && fi.IsDir() {
|
||||
return dir, nil // return the symlink, how QNAP set it up
|
||||
}
|
||||
return "", fmt.Errorf("shared folder %q not found", name)
|
||||
}
|
||||
|
||||
// findUnraidTaildropDir looks for a directory linked at
|
||||
// /var/lib/tailscale/Taildrop. This is a symlink to the
|
||||
// path specified by the user in the Unraid Web UI
|
||||
func findUnraidTaildropDir(name string) (string, error) {
|
||||
dir := fmt.Sprintf("/var/lib/tailscale/%s", name)
|
||||
_, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("symlink %q not found", name)
|
||||
}
|
||||
|
||||
fullpath, err := filepath.EvalSymlinks(dir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("symlink %q to shared folder not valid", name)
|
||||
}
|
||||
|
||||
fi, err := os.Stat(fullpath)
|
||||
if err == nil && fi.IsDir() {
|
||||
return dir, nil // return the symlink
|
||||
}
|
||||
return "", fmt.Errorf("shared folder %q not found", name)
|
||||
}
|
||||
Reference in New Issue
Block a user