mirror of
https://github.com/tailscale/tailscale.git
synced 2026-05-05 20:26:47 +02:00
Use linkat via /proc/self/fd with AT_SYMLINK_FOLLOW to create a hardlink of the test binary instead of copying it. This avoids copying ~50MB+ binaries into each test's temp directory, making test setup faster and reducing disk I/O. The simpler os.Link(b.Path, ret.Path) can't be used here because the source binary lives 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, but os.Link needs a valid path. (See also b9f468240f which tried os.Link but is racy for this reason.) The /proc/self/fd approach works without elevated privileges, unlike AT_EMPTY_PATH which requires CAP_DAC_READ_SEARCH. If the linkat fails for any reason (e.g. cross-filesystem temp dirs), it falls back to the existing full-copy path. Fixes #19397 Change-Id: I4b1f97f7e63a9ae9e09dce36dfbdd1f6cff92320 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
49 lines
949 B
Go
49 lines
949 B
Go
// 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)
|
|
}
|
|
}
|