mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
clientupdate, ipn/localapi: don't use google/uuid, thin iOS deps
We were using google/uuid in two places and that brought in database/sql/driver. We didn't need it in either place. Updates #13760 Updates tailscale/corp#20099 Change-Id: Ieed32f1bebe35d35f47ec5a2a429268f24f11f1f Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
fb420be176
commit
2531065d10
@ -27,11 +27,9 @@
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"tailscale.com/clientupdate/distsign"
|
"tailscale.com/clientupdate/distsign"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/cmpver"
|
"tailscale.com/util/cmpver"
|
||||||
"tailscale.com/util/winutil"
|
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
"tailscale.com/version/distro"
|
"tailscale.com/version/distro"
|
||||||
)
|
)
|
||||||
@ -756,164 +754,6 @@ func (up *Updater) updateMacAppStore() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
// winMSIEnv is the environment variable that, if set, is the MSI file for
|
|
||||||
// the update command to install. It's passed like this so we can stop the
|
|
||||||
// tailscale.exe process from running before the msiexec process runs and
|
|
||||||
// tries to overwrite ourselves.
|
|
||||||
winMSIEnv = "TS_UPDATE_WIN_MSI"
|
|
||||||
// winExePathEnv is the environment variable that is set along with
|
|
||||||
// winMSIEnv and carries the full path of the calling tailscale.exe binary.
|
|
||||||
// It is used to re-launch the GUI process (tailscale-ipn.exe) after
|
|
||||||
// install is complete.
|
|
||||||
winExePathEnv = "TS_UPDATE_WIN_EXE_PATH"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
verifyAuthenticode func(string) error // set non-nil only on Windows
|
|
||||||
markTempFileFunc func(string) error // set non-nil only on Windows
|
|
||||||
)
|
|
||||||
|
|
||||||
func (up *Updater) updateWindows() error {
|
|
||||||
if msi := os.Getenv(winMSIEnv); msi != "" {
|
|
||||||
// stdout/stderr from this part of the install could be lost since the
|
|
||||||
// parent tailscaled is replaced. Create a temp log file to have some
|
|
||||||
// output to debug with in case update fails.
|
|
||||||
close, err := up.switchOutputToFile()
|
|
||||||
if err != nil {
|
|
||||||
up.Logf("failed to create log file for installation: %v; proceeding with existing outputs", err)
|
|
||||||
} else {
|
|
||||||
defer close.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
up.Logf("installing %v ...", msi)
|
|
||||||
if err := up.installMSI(msi); err != nil {
|
|
||||||
up.Logf("MSI install failed: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
up.Logf("success.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !winutil.IsCurrentProcessElevated() {
|
|
||||||
return errors.New(`update must be run as Administrator
|
|
||||||
|
|
||||||
you can run the command prompt as Administrator one of these ways:
|
|
||||||
* right-click cmd.exe, select 'Run as administrator'
|
|
||||||
* press Windows+x, then press a
|
|
||||||
* press Windows+r, type in "cmd", then press Ctrl+Shift+Enter`)
|
|
||||||
}
|
|
||||||
ver, err := requestedTailscaleVersion(up.Version, up.Track)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
arch := runtime.GOARCH
|
|
||||||
if arch == "386" {
|
|
||||||
arch = "x86"
|
|
||||||
}
|
|
||||||
if !up.confirm(ver) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
tsDir := filepath.Join(os.Getenv("ProgramData"), "Tailscale")
|
|
||||||
msiDir := filepath.Join(tsDir, "MSICache")
|
|
||||||
if fi, err := os.Stat(tsDir); err != nil {
|
|
||||||
return fmt.Errorf("expected %s to exist, got stat error: %w", tsDir, err)
|
|
||||||
} else if !fi.IsDir() {
|
|
||||||
return fmt.Errorf("expected %s to be a directory; got %v", tsDir, fi.Mode())
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(msiDir, 0700); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
up.cleanupOldDownloads(filepath.Join(msiDir, "*.msi"))
|
|
||||||
pkgsPath := fmt.Sprintf("%s/tailscale-setup-%s-%s.msi", up.Track, ver, arch)
|
|
||||||
msiTarget := filepath.Join(msiDir, path.Base(pkgsPath))
|
|
||||||
if err := up.downloadURLToFile(pkgsPath, msiTarget); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
up.Logf("verifying MSI authenticode...")
|
|
||||||
if err := verifyAuthenticode(msiTarget); err != nil {
|
|
||||||
return fmt.Errorf("authenticode verification of %s failed: %w", msiTarget, err)
|
|
||||||
}
|
|
||||||
up.Logf("authenticode verification succeeded")
|
|
||||||
|
|
||||||
up.Logf("making tailscale.exe copy to switch to...")
|
|
||||||
up.cleanupOldDownloads(filepath.Join(os.TempDir(), "tailscale-updater-*.exe"))
|
|
||||||
selfOrig, selfCopy, err := makeSelfCopy()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer os.Remove(selfCopy)
|
|
||||||
up.Logf("running tailscale.exe copy for final install...")
|
|
||||||
|
|
||||||
cmd := exec.Command(selfCopy, "update")
|
|
||||||
cmd.Env = append(os.Environ(), winMSIEnv+"="+msiTarget, winExePathEnv+"="+selfOrig)
|
|
||||||
cmd.Stdout = up.Stderr
|
|
||||||
cmd.Stderr = up.Stderr
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Once it's started, exit ourselves, so the binary is free
|
|
||||||
// to be replaced.
|
|
||||||
os.Exit(0)
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (up *Updater) switchOutputToFile() (io.Closer, error) {
|
|
||||||
var logFilePath string
|
|
||||||
exePath, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
logFilePath = filepath.Join(os.TempDir(), "tailscale-updater.log")
|
|
||||||
} else {
|
|
||||||
logFilePath = strings.TrimSuffix(exePath, ".exe") + ".log"
|
|
||||||
}
|
|
||||||
|
|
||||||
up.Logf("writing update output to %q", logFilePath)
|
|
||||||
logFile, err := os.Create(logFilePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
up.Logf = func(m string, args ...any) {
|
|
||||||
fmt.Fprintf(logFile, m+"\n", args...)
|
|
||||||
}
|
|
||||||
up.Stdout = logFile
|
|
||||||
up.Stderr = logFile
|
|
||||||
return logFile, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (up *Updater) installMSI(msi string) error {
|
|
||||||
var err error
|
|
||||||
for tries := 0; tries < 2; tries++ {
|
|
||||||
cmd := exec.Command("msiexec.exe", "/i", filepath.Base(msi), "/quiet", "/norestart", "/qn")
|
|
||||||
cmd.Dir = filepath.Dir(msi)
|
|
||||||
cmd.Stdout = up.Stdout
|
|
||||||
cmd.Stderr = up.Stderr
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
err = cmd.Run()
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
up.Logf("Install attempt failed: %v", err)
|
|
||||||
uninstallVersion := up.currentVersion
|
|
||||||
if v := os.Getenv("TS_DEBUG_UNINSTALL_VERSION"); v != "" {
|
|
||||||
uninstallVersion = v
|
|
||||||
}
|
|
||||||
// Assume it's a downgrade, which msiexec won't permit. Uninstall our current version first.
|
|
||||||
up.Logf("Uninstalling current version %q for downgrade...", uninstallVersion)
|
|
||||||
cmd = exec.Command("msiexec.exe", "/x", msiUUIDForVersion(uninstallVersion), "/norestart", "/qn")
|
|
||||||
cmd.Stdout = up.Stdout
|
|
||||||
cmd.Stderr = up.Stderr
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
err = cmd.Run()
|
|
||||||
up.Logf("msiexec uninstall: %v", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanupOldDownloads removes all files matching glob (see filepath.Glob).
|
// cleanupOldDownloads removes all files matching glob (see filepath.Glob).
|
||||||
// Only regular files are removed, so the glob must match specific files and
|
// Only regular files are removed, so the glob must match specific files and
|
||||||
// not directories.
|
// not directories.
|
||||||
@ -938,45 +778,6 @@ func (up *Updater) cleanupOldDownloads(glob string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func msiUUIDForVersion(ver string) string {
|
|
||||||
arch := runtime.GOARCH
|
|
||||||
if arch == "386" {
|
|
||||||
arch = "x86"
|
|
||||||
}
|
|
||||||
track, err := versionToTrack(ver)
|
|
||||||
if err != nil {
|
|
||||||
track = UnstableTrack
|
|
||||||
}
|
|
||||||
msiURL := fmt.Sprintf("https://pkgs.tailscale.com/%s/tailscale-setup-%s-%s.msi", track, ver, arch)
|
|
||||||
return "{" + strings.ToUpper(uuid.NewSHA1(uuid.NameSpaceURL, []byte(msiURL)).String()) + "}"
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeSelfCopy() (origPathExe, tmpPathExe string, err error) {
|
|
||||||
selfExe, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
f, err := os.Open(selfExe)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
f2, err := os.CreateTemp("", "tailscale-updater-*.exe")
|
|
||||||
if err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
if f := markTempFileFunc; f != nil {
|
|
||||||
if err := f(f2.Name()); err != nil {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := io.Copy(f2, f); err != nil {
|
|
||||||
f2.Close()
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
return selfExe, f2.Name(), f2.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (up *Updater) downloadURLToFile(pathSrc, fileDst string) (ret error) {
|
func (up *Updater) downloadURLToFile(pathSrc, fileDst string) (ret error) {
|
||||||
c, err := distsign.NewClient(up.Logf, up.PkgsAddr)
|
c, err := distsign.NewClient(up.Logf, up.PkgsAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
10
clientupdate/clientupdate_notwindows.go
Normal file
10
clientupdate/clientupdate_notwindows.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package clientupdate
|
||||||
|
|
||||||
|
func (up *Updater) updateWindows() error {
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
@ -7,13 +7,57 @@
|
|||||||
package clientupdate
|
package clientupdate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
|
"tailscale.com/util/winutil"
|
||||||
"tailscale.com/util/winutil/authenticode"
|
"tailscale.com/util/winutil/authenticode"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
const (
|
||||||
markTempFileFunc = markTempFileWindows
|
// winMSIEnv is the environment variable that, if set, is the MSI file for
|
||||||
verifyAuthenticode = verifyTailscale
|
// the update command to install. It's passed like this so we can stop the
|
||||||
|
// tailscale.exe process from running before the msiexec process runs and
|
||||||
|
// tries to overwrite ourselves.
|
||||||
|
winMSIEnv = "TS_UPDATE_WIN_MSI"
|
||||||
|
// winExePathEnv is the environment variable that is set along with
|
||||||
|
// winMSIEnv and carries the full path of the calling tailscale.exe binary.
|
||||||
|
// It is used to re-launch the GUI process (tailscale-ipn.exe) after
|
||||||
|
// install is complete.
|
||||||
|
winExePathEnv = "TS_UPDATE_WIN_EXE_PATH"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeSelfCopy() (origPathExe, tmpPathExe string, err error) {
|
||||||
|
selfExe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
f, err := os.Open(selfExe)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
f2, err := os.CreateTemp("", "tailscale-updater-*.exe")
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
if err := markTempFileWindows(f2.Name()); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(f2, f); err != nil {
|
||||||
|
f2.Close()
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return selfExe, f2.Name(), f2.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func markTempFileWindows(name string) error {
|
func markTempFileWindows(name string) error {
|
||||||
@ -23,6 +67,159 @@ func markTempFileWindows(name string) error {
|
|||||||
|
|
||||||
const certSubjectTailscale = "Tailscale Inc."
|
const certSubjectTailscale = "Tailscale Inc."
|
||||||
|
|
||||||
func verifyTailscale(path string) error {
|
func verifyAuthenticode(path string) error {
|
||||||
return authenticode.Verify(path, certSubjectTailscale)
|
return authenticode.Verify(path, certSubjectTailscale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (up *Updater) updateWindows() error {
|
||||||
|
if msi := os.Getenv(winMSIEnv); msi != "" {
|
||||||
|
// stdout/stderr from this part of the install could be lost since the
|
||||||
|
// parent tailscaled is replaced. Create a temp log file to have some
|
||||||
|
// output to debug with in case update fails.
|
||||||
|
close, err := up.switchOutputToFile()
|
||||||
|
if err != nil {
|
||||||
|
up.Logf("failed to create log file for installation: %v; proceeding with existing outputs", err)
|
||||||
|
} else {
|
||||||
|
defer close.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
up.Logf("installing %v ...", msi)
|
||||||
|
if err := up.installMSI(msi); err != nil {
|
||||||
|
up.Logf("MSI install failed: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
up.Logf("success.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !winutil.IsCurrentProcessElevated() {
|
||||||
|
return errors.New(`update must be run as Administrator
|
||||||
|
|
||||||
|
you can run the command prompt as Administrator one of these ways:
|
||||||
|
* right-click cmd.exe, select 'Run as administrator'
|
||||||
|
* press Windows+x, then press a
|
||||||
|
* press Windows+r, type in "cmd", then press Ctrl+Shift+Enter`)
|
||||||
|
}
|
||||||
|
ver, err := requestedTailscaleVersion(up.Version, up.Track)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
arch := runtime.GOARCH
|
||||||
|
if arch == "386" {
|
||||||
|
arch = "x86"
|
||||||
|
}
|
||||||
|
if !up.confirm(ver) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tsDir := filepath.Join(os.Getenv("ProgramData"), "Tailscale")
|
||||||
|
msiDir := filepath.Join(tsDir, "MSICache")
|
||||||
|
if fi, err := os.Stat(tsDir); err != nil {
|
||||||
|
return fmt.Errorf("expected %s to exist, got stat error: %w", tsDir, err)
|
||||||
|
} else if !fi.IsDir() {
|
||||||
|
return fmt.Errorf("expected %s to be a directory; got %v", tsDir, fi.Mode())
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(msiDir, 0700); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
up.cleanupOldDownloads(filepath.Join(msiDir, "*.msi"))
|
||||||
|
pkgsPath := fmt.Sprintf("%s/tailscale-setup-%s-%s.msi", up.Track, ver, arch)
|
||||||
|
msiTarget := filepath.Join(msiDir, path.Base(pkgsPath))
|
||||||
|
if err := up.downloadURLToFile(pkgsPath, msiTarget); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
up.Logf("verifying MSI authenticode...")
|
||||||
|
if err := verifyAuthenticode(msiTarget); err != nil {
|
||||||
|
return fmt.Errorf("authenticode verification of %s failed: %w", msiTarget, err)
|
||||||
|
}
|
||||||
|
up.Logf("authenticode verification succeeded")
|
||||||
|
|
||||||
|
up.Logf("making tailscale.exe copy to switch to...")
|
||||||
|
up.cleanupOldDownloads(filepath.Join(os.TempDir(), "tailscale-updater-*.exe"))
|
||||||
|
selfOrig, selfCopy, err := makeSelfCopy()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer os.Remove(selfCopy)
|
||||||
|
up.Logf("running tailscale.exe copy for final install...")
|
||||||
|
|
||||||
|
cmd := exec.Command(selfCopy, "update")
|
||||||
|
cmd.Env = append(os.Environ(), winMSIEnv+"="+msiTarget, winExePathEnv+"="+selfOrig)
|
||||||
|
cmd.Stdout = up.Stderr
|
||||||
|
cmd.Stderr = up.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Once it's started, exit ourselves, so the binary is free
|
||||||
|
// to be replaced.
|
||||||
|
os.Exit(0)
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (up *Updater) installMSI(msi string) error {
|
||||||
|
var err error
|
||||||
|
for tries := 0; tries < 2; tries++ {
|
||||||
|
cmd := exec.Command("msiexec.exe", "/i", filepath.Base(msi), "/quiet", "/norestart", "/qn")
|
||||||
|
cmd.Dir = filepath.Dir(msi)
|
||||||
|
cmd.Stdout = up.Stdout
|
||||||
|
cmd.Stderr = up.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
err = cmd.Run()
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
up.Logf("Install attempt failed: %v", err)
|
||||||
|
uninstallVersion := up.currentVersion
|
||||||
|
if v := os.Getenv("TS_DEBUG_UNINSTALL_VERSION"); v != "" {
|
||||||
|
uninstallVersion = v
|
||||||
|
}
|
||||||
|
// Assume it's a downgrade, which msiexec won't permit. Uninstall our current version first.
|
||||||
|
up.Logf("Uninstalling current version %q for downgrade...", uninstallVersion)
|
||||||
|
cmd = exec.Command("msiexec.exe", "/x", msiUUIDForVersion(uninstallVersion), "/norestart", "/qn")
|
||||||
|
cmd.Stdout = up.Stdout
|
||||||
|
cmd.Stderr = up.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
err = cmd.Run()
|
||||||
|
up.Logf("msiexec uninstall: %v", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func msiUUIDForVersion(ver string) string {
|
||||||
|
arch := runtime.GOARCH
|
||||||
|
if arch == "386" {
|
||||||
|
arch = "x86"
|
||||||
|
}
|
||||||
|
track, err := versionToTrack(ver)
|
||||||
|
if err != nil {
|
||||||
|
track = UnstableTrack
|
||||||
|
}
|
||||||
|
msiURL := fmt.Sprintf("https://pkgs.tailscale.com/%s/tailscale-setup-%s-%s.msi", track, ver, arch)
|
||||||
|
return "{" + strings.ToUpper(uuid.NewSHA1(uuid.NameSpaceURL, []byte(msiURL)).String()) + "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (up *Updater) switchOutputToFile() (io.Closer, error) {
|
||||||
|
var logFilePath string
|
||||||
|
exePath, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
logFilePath = filepath.Join(os.TempDir(), "tailscale-updater.log")
|
||||||
|
} else {
|
||||||
|
logFilePath = strings.TrimSuffix(exePath, ".exe") + ".log"
|
||||||
|
}
|
||||||
|
|
||||||
|
up.Logf("writing update output to %q", logFilePath)
|
||||||
|
logFile, err := os.Create(logFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
up.Logf = func(m string, args ...any) {
|
||||||
|
fmt.Fprintf(logFile, m+"\n", args...)
|
||||||
|
}
|
||||||
|
up.Stdout = logFile
|
||||||
|
up.Stderr = logFile
|
||||||
|
return logFile, nil
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
L github.com/google/nftables/expr from github.com/google/nftables+
|
L github.com/google/nftables/expr from github.com/google/nftables+
|
||||||
L github.com/google/nftables/internal/parseexprfunc from github.com/google/nftables+
|
L github.com/google/nftables/internal/parseexprfunc from github.com/google/nftables+
|
||||||
L github.com/google/nftables/xt from github.com/google/nftables/expr+
|
L github.com/google/nftables/xt from github.com/google/nftables/expr+
|
||||||
github.com/google/uuid from tailscale.com/clientupdate+
|
DW github.com/google/uuid from tailscale.com/clientupdate+
|
||||||
github.com/gorilla/csrf from tailscale.com/client/web
|
github.com/gorilla/csrf from tailscale.com/client/web
|
||||||
github.com/gorilla/securecookie from github.com/gorilla/csrf
|
github.com/gorilla/securecookie from github.com/gorilla/csrf
|
||||||
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign+
|
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign+
|
||||||
@ -178,7 +178,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
tailscale.com/util/truncate from tailscale.com/cmd/tailscale/cli
|
tailscale.com/util/truncate from tailscale.com/cmd/tailscale/cli
|
||||||
tailscale.com/util/usermetric from tailscale.com/health
|
tailscale.com/util/usermetric from tailscale.com/health
|
||||||
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
tailscale.com/util/vizerror from tailscale.com/tailcfg+
|
||||||
💣 tailscale.com/util/winutil from tailscale.com/clientupdate+
|
W 💣 tailscale.com/util/winutil from tailscale.com/clientupdate+
|
||||||
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/clientupdate
|
W 💣 tailscale.com/util/winutil/authenticode from tailscale.com/clientupdate
|
||||||
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
W 💣 tailscale.com/util/winutil/winenv from tailscale.com/hostinfo+
|
||||||
tailscale.com/version from tailscale.com/client/web+
|
tailscale.com/version from tailscale.com/client/web+
|
||||||
@ -258,7 +258,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
crypto/tls from github.com/miekg/dns+
|
crypto/tls from github.com/miekg/dns+
|
||||||
crypto/x509 from crypto/tls+
|
crypto/x509 from crypto/tls+
|
||||||
crypto/x509/pkix from crypto/x509+
|
crypto/x509/pkix from crypto/x509+
|
||||||
database/sql/driver from github.com/google/uuid
|
DW database/sql/driver from github.com/google/uuid
|
||||||
W debug/dwarf from debug/pe
|
W debug/dwarf from debug/pe
|
||||||
W debug/pe from github.com/dblohm7/wingoes/pe
|
W debug/pe from github.com/dblohm7/wingoes/pe
|
||||||
embed from crypto/internal/nistec+
|
embed from crypto/internal/nistec+
|
||||||
|
@ -111,7 +111,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
L github.com/google/nftables/expr from github.com/google/nftables+
|
L github.com/google/nftables/expr from github.com/google/nftables+
|
||||||
L github.com/google/nftables/internal/parseexprfunc from github.com/google/nftables+
|
L github.com/google/nftables/internal/parseexprfunc from github.com/google/nftables+
|
||||||
L github.com/google/nftables/xt from github.com/google/nftables/expr+
|
L github.com/google/nftables/xt from github.com/google/nftables/expr+
|
||||||
github.com/google/uuid from tailscale.com/clientupdate+
|
DW github.com/google/uuid from tailscale.com/clientupdate+
|
||||||
github.com/gorilla/csrf from tailscale.com/client/web
|
github.com/gorilla/csrf from tailscale.com/client/web
|
||||||
github.com/gorilla/securecookie from github.com/gorilla/csrf
|
github.com/gorilla/securecookie from github.com/gorilla/csrf
|
||||||
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign+
|
github.com/hdevalence/ed25519consensus from tailscale.com/clientupdate/distsign+
|
||||||
@ -508,7 +508,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
crypto/tls from github.com/aws/aws-sdk-go-v2/aws/transport/http+
|
crypto/tls from github.com/aws/aws-sdk-go-v2/aws/transport/http+
|
||||||
crypto/x509 from crypto/tls+
|
crypto/x509 from crypto/tls+
|
||||||
crypto/x509/pkix from crypto/x509+
|
crypto/x509/pkix from crypto/x509+
|
||||||
database/sql/driver from github.com/google/uuid
|
DW database/sql/driver from github.com/google/uuid
|
||||||
W debug/dwarf from debug/pe
|
W debug/dwarf from debug/pe
|
||||||
W debug/pe from github.com/dblohm7/wingoes/pe
|
W debug/pe from github.com/dblohm7/wingoes/pe
|
||||||
embed from crypto/internal/nistec+
|
embed from crypto/internal/nistec+
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"tailscale.com/client/tailscale/apitype"
|
"tailscale.com/client/tailscale/apitype"
|
||||||
"tailscale.com/clientupdate"
|
"tailscale.com/clientupdate"
|
||||||
@ -1563,7 +1562,7 @@ func (h *Handler) serveFilePut(w http.ResponseWriter, r *http.Request) {
|
|||||||
switch r.Method {
|
switch r.Method {
|
||||||
case "PUT":
|
case "PUT":
|
||||||
file := ipn.OutgoingFile{
|
file := ipn.OutgoingFile{
|
||||||
ID: uuid.Must(uuid.NewRandom()).String(),
|
ID: rands.HexString(30),
|
||||||
PeerID: peerID,
|
PeerID: peerID,
|
||||||
Name: filenameEscaped,
|
Name: filenameEscaped,
|
||||||
DeclaredSize: r.ContentLength,
|
DeclaredSize: r.ContentLength,
|
||||||
|
@ -20,6 +20,8 @@ func TestDeps(t *testing.T) {
|
|||||||
"tailscale.com/net/wsconn": "https://github.com/tailscale/tailscale/issues/13762",
|
"tailscale.com/net/wsconn": "https://github.com/tailscale/tailscale/issues/13762",
|
||||||
"github.com/coder/websocket": "https://github.com/tailscale/tailscale/issues/13762",
|
"github.com/coder/websocket": "https://github.com/tailscale/tailscale/issues/13762",
|
||||||
"github.com/mitchellh/go-ps": "https://github.com/tailscale/tailscale/pull/13759",
|
"github.com/mitchellh/go-ps": "https://github.com/tailscale/tailscale/pull/13759",
|
||||||
|
"database/sql/driver": "iOS doesn't use an SQL database",
|
||||||
|
"github.com/google/uuid": "see tailscale/tailscale#13760",
|
||||||
},
|
},
|
||||||
}.Check(t)
|
}.Check(t)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user