|
|
|
|
@ -14,57 +14,58 @@ import ( |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
|
shareSetUsage = "share set <name> <path>" |
|
|
|
|
shareRenameUsage = "share rename <oldname> <newname>" |
|
|
|
|
shareRemoveUsage = "share remove <name>" |
|
|
|
|
shareListUsage = "share list" |
|
|
|
|
driveShareUsage = "drive share <name> <path>" |
|
|
|
|
driveRenameUsage = "drive rename <oldname> <newname>" |
|
|
|
|
driveUnshareUsage = "drive unshare <name>" |
|
|
|
|
driveListUsage = "drive list" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var shareCmd = &ffcli.Command{ |
|
|
|
|
Name: "share", |
|
|
|
|
var driveCmd = &ffcli.Command{ |
|
|
|
|
Name: "drive", |
|
|
|
|
ShortHelp: "Share a directory with your tailnet", |
|
|
|
|
ShortUsage: strings.Join([]string{ |
|
|
|
|
shareSetUsage, |
|
|
|
|
shareRemoveUsage, |
|
|
|
|
shareListUsage, |
|
|
|
|
driveShareUsage, |
|
|
|
|
driveRenameUsage, |
|
|
|
|
driveUnshareUsage, |
|
|
|
|
driveListUsage, |
|
|
|
|
}, "\n "), |
|
|
|
|
LongHelp: buildShareLongHelp(), |
|
|
|
|
UsageFunc: usageFuncNoDefaultValues, |
|
|
|
|
Subcommands: []*ffcli.Command{ |
|
|
|
|
{ |
|
|
|
|
Name: "set", |
|
|
|
|
Exec: runShareSet, |
|
|
|
|
ShortHelp: "[ALPHA] set a share", |
|
|
|
|
Name: "share", |
|
|
|
|
Exec: runDriveShare, |
|
|
|
|
ShortHelp: "[ALPHA] create or modify a share", |
|
|
|
|
UsageFunc: usageFunc, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Name: "rename", |
|
|
|
|
ShortHelp: "[ALPHA] rename a share", |
|
|
|
|
Exec: runShareRename, |
|
|
|
|
Exec: runDriveRename, |
|
|
|
|
UsageFunc: usageFunc, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Name: "remove", |
|
|
|
|
Name: "unshare", |
|
|
|
|
ShortHelp: "[ALPHA] remove a share", |
|
|
|
|
Exec: runShareRemove, |
|
|
|
|
Exec: runDriveUnshare, |
|
|
|
|
UsageFunc: usageFunc, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
Name: "list", |
|
|
|
|
ShortHelp: "[ALPHA] list current shares", |
|
|
|
|
Exec: runShareList, |
|
|
|
|
Exec: runDriveList, |
|
|
|
|
UsageFunc: usageFunc, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
Exec: func(context.Context, []string) error { |
|
|
|
|
return errors.New("share subcommand required; run 'tailscale share -h' for details") |
|
|
|
|
return errors.New("drive subcommand required; run 'tailscale drive -h' for details") |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// runShareSet is the entry point for the "tailscale share set" command.
|
|
|
|
|
func runShareSet(ctx context.Context, args []string) error { |
|
|
|
|
// runDriveShare is the entry point for the "tailscale drive share" command.
|
|
|
|
|
func runDriveShare(ctx context.Context, args []string) error { |
|
|
|
|
if len(args) != 2 { |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", shareSetUsage) |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", driveShareUsage) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
name, path := args[0], args[1] |
|
|
|
|
@ -74,29 +75,29 @@ func runShareSet(ctx context.Context, args []string) error { |
|
|
|
|
Path: path, |
|
|
|
|
}) |
|
|
|
|
if err == nil { |
|
|
|
|
fmt.Printf("Set share %q at %q\n", name, path) |
|
|
|
|
fmt.Printf("Sharing %q as %q\n", path, name) |
|
|
|
|
} |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// runShareRemove is the entry point for the "tailscale share remove" command.
|
|
|
|
|
func runShareRemove(ctx context.Context, args []string) error { |
|
|
|
|
// runDriveUnshare is the entry point for the "tailscale drive unshare" command.
|
|
|
|
|
func runDriveUnshare(ctx context.Context, args []string) error { |
|
|
|
|
if len(args) != 1 { |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", shareRemoveUsage) |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", driveUnshareUsage) |
|
|
|
|
} |
|
|
|
|
name := args[0] |
|
|
|
|
|
|
|
|
|
err := localClient.DriveShareRemove(ctx, name) |
|
|
|
|
if err == nil { |
|
|
|
|
fmt.Printf("Removed share %q\n", name) |
|
|
|
|
fmt.Printf("No longer sharing %q\n", name) |
|
|
|
|
} |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// runShareRename is the entry point for the "tailscale share rename" command.
|
|
|
|
|
func runShareRename(ctx context.Context, args []string) error { |
|
|
|
|
// runDriveRename is the entry point for the "tailscale drive rename" command.
|
|
|
|
|
func runDriveRename(ctx context.Context, args []string) error { |
|
|
|
|
if len(args) != 2 { |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", shareRenameUsage) |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", driveRenameUsage) |
|
|
|
|
} |
|
|
|
|
oldName := args[0] |
|
|
|
|
newName := args[1] |
|
|
|
|
@ -108,10 +109,10 @@ func runShareRename(ctx context.Context, args []string) error { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// runShareList is the entry point for the "tailscale share list" command.
|
|
|
|
|
func runShareList(ctx context.Context, args []string) error { |
|
|
|
|
// runDriveList is the entry point for the "tailscale drive list" command.
|
|
|
|
|
func runDriveList(ctx context.Context, args []string) error { |
|
|
|
|
if len(args) != 0 { |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", shareListUsage) |
|
|
|
|
return fmt.Errorf("usage: tailscale %v", driveListUsage) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
shares, err := localClient.DriveShareList(ctx) |
|
|
|
|
@ -151,7 +152,7 @@ func buildShareLongHelp() string { |
|
|
|
|
return fmt.Sprintf(shareLongHelpBase, longHelpAs) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var shareLongHelpBase = `Tailscale share allows you to share directories with other machines on your tailnet. |
|
|
|
|
var shareLongHelpBase = `Taildrive allows you to share directories with other machines on your tailnet. |
|
|
|
|
|
|
|
|
|
In order to share folders, your node needs to have the node attribute "drive:share". |
|
|
|
|
|
|
|
|
|
@ -170,7 +171,7 @@ For example, to enable sharing and accessing shares for all member nodes: |
|
|
|
|
|
|
|
|
|
Each share is identified by a name and points to a directory at a specific path. For example, to share the path /Users/me/Documents under the name "docs", you would run: |
|
|
|
|
|
|
|
|
|
$ tailscale share set docs /Users/me/Documents |
|
|
|
|
$ tailscale drive share docs /Users/me/Documents |
|
|
|
|
|
|
|
|
|
Note that the system forces share names to lowercase to avoid problems with clients that don't support case-sensitive filenames. |
|
|
|
|
|
|
|
|
|
@ -226,18 +227,18 @@ Whenever either you or anyone in the group "home" connects to the share, they co |
|
|
|
|
|
|
|
|
|
You can rename shares, for example you could rename the above share by running: |
|
|
|
|
|
|
|
|
|
$ tailscale share rename docs newdocs |
|
|
|
|
$ tailscale drive rename docs newdocs |
|
|
|
|
|
|
|
|
|
You can remove shares by name, for example you could remove the above share by running: |
|
|
|
|
|
|
|
|
|
$ tailscale share remove newdocs |
|
|
|
|
$ tailscale drive unshare newdocs |
|
|
|
|
|
|
|
|
|
You can get a list of currently published shares by running: |
|
|
|
|
|
|
|
|
|
$ tailscale share list` |
|
|
|
|
$ tailscale drive list` |
|
|
|
|
|
|
|
|
|
var shareLongHelpAs = ` |
|
|
|
|
|
|
|
|
|
If you want a share to be accessed as a different user, you can use sudo to accomplish this. For example, to create the aforementioned share as "theuser", you could run: |
|
|
|
|
|
|
|
|
|
$ sudo -u theuser tailscale share set docs /Users/theuser/Documents` |
|
|
|
|
$ sudo -u theuser tailscale drive share docs /Users/theuser/Documents` |
|
|
|
|
|