tka: keep the CompactionDefaults alongside the other limits #6
@@ -73,7 +73,11 @@ type Binaries struct {
|
||||
|
||||
// BinaryInfo describes a tailscale or tailscaled binary.
|
||||
type BinaryInfo struct {
|
||||
Path string // abs path to tailscale or tailscaled binary
|
||||
// Path is the absolute path to the tailscale or tailscaled binary.
|
||||
// This path may become invalid after the owning test's TempDir is
|
||||
// cleaned up; use FD (or Contents on Windows) to access the binary
|
||||
// contents.
|
||||
Path string
|
||||
Size int64
|
||||
|
||||
// FD and FDmu are set on Unix to efficiently copy the binary to a new
|
||||
@@ -88,16 +92,24 @@ type BinaryInfo struct {
|
||||
Contents []byte
|
||||
}
|
||||
|
||||
// CopyTo copies or hardlinks the binary into dir, returning a new BinaryInfo
|
||||
// with an updated Path. The source bytes come from FD (or Contents on Windows),
|
||||
// not from b.Path, which may have been deleted when its owning test's TempDir
|
||||
// was cleaned up.
|
||||
func (b BinaryInfo) CopyTo(dir string) (BinaryInfo, error) {
|
||||
ret := b
|
||||
ret.Path = filepath.Join(dir, path.Base(b.Path))
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
// TODO(bradfitz): be fancy and use linkat with AT_EMPTY_PATH to avoid
|
||||
// copying? I couldn't get it to work, though.
|
||||
// For now, just do the same thing as every other Unix and copy
|
||||
// the binary.
|
||||
// Try to hardlink from the open FD via /proc/self/fd, avoiding a
|
||||
// full copy of the binary. We can't use os.Link(b.Path, ret.Path)
|
||||
// because b.Path is in the first test's TempDir, which may be
|
||||
// cleaned up before later tests call CopyTo. The open FD keeps the
|
||||
// inode alive after the path is deleted.
|
||||
if err := tryLinkat(b.FD, ret.Path); err == nil {
|
||||
return ret, nil
|
||||
}
|
||||
fallthrough
|
||||
case "darwin", "freebsd", "openbsd", "netbsd":
|
||||
f, err := os.OpenFile(ret.Path, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o755)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// tryLinkat attempts to hardlink the file referenced by fd to newpath,
|
||||
// avoiding a full copy of the binary. It uses /proc/self/fd/<N> with
|
||||
// AT_SYMLINK_FOLLOW, which works without elevated privileges (unlike
|
||||
// AT_EMPTY_PATH which requires CAP_DAC_READ_SEARCH).
|
||||
func tryLinkat(fd *os.File, newpath string) error {
|
||||
procPath := fmt.Sprintf("/proc/self/fd/%d", fd.Fd())
|
||||
err := unix.Linkat(unix.AT_FDCWD, procPath, unix.AT_FDCWD, newpath, unix.AT_SYMLINK_FOLLOW)
|
||||
if err != nil {
|
||||
return fmt.Errorf("linkat via /proc/self/fd: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestTryLinkat(t *testing.T) {
|
||||
src := filepath.Join(t.TempDir(), "src")
|
||||
if err := os.WriteFile(src, []byte("hello world"), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fd, err := os.Open(src)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
dst := filepath.Join(t.TempDir(), "dst")
|
||||
if err := tryLinkat(fd, dst); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := os.ReadFile(dst)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(got) != "hello world" {
|
||||
t.Fatalf("got %q, want %q", got, "hello world")
|
||||
}
|
||||
|
||||
var stSrc, stDst unix.Stat_t
|
||||
if err := unix.Stat(src, &stSrc); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := unix.Stat(dst, &stDst); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if stSrc.Ino != stDst.Ino {
|
||||
t.Fatalf("inodes differ: src=%d, dst=%d", stSrc.Ino, stDst.Ino)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !linux
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
func tryLinkat(_ *os.File, _ string) error {
|
||||
return errors.New("linkat with AT_EMPTY_PATH not supported on this OS")
|
||||
}
|
||||
Reference in New Issue
Block a user