From c315862c99fcca83389b99715a712a6c8e1ad65e Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 18 Nov 2024 18:09:17 -0800 Subject: [PATCH] os: add OpenInRoot For #67002 Change-Id: If919ee8a5e3d90e91c7848330762e3254245fba1 Reviewed-on: https://go-review.googlesource.com/c/go/+/629555 Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- api/next/67002.txt | 1 + src/os/root.go | 16 ++++++++++++++++ src/os/root_test.go | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/api/next/67002.txt b/api/next/67002.txt index 67c47969f4f..72fdec83708 100644 --- a/api/next/67002.txt +++ b/api/next/67002.txt @@ -1,3 +1,4 @@ +pkg os, func OpenInRoot(string, string) (*File, error) #67002 pkg os, func OpenRoot(string) (*Root, error) #67002 pkg os, method (*Root) Close() error #67002 pkg os, method (*Root) Create(string) (*File, error) #67002 diff --git a/src/os/root.go b/src/os/root.go index c7d9b5b0712..d9fc6358a50 100644 --- a/src/os/root.go +++ b/src/os/root.go @@ -14,6 +14,22 @@ import ( "slices" ) +// OpenInRoot opens the file name in the directory dir. +// It is equivalent to OpenRoot(dir) followed by opening the file in the root. +// +// OpenInRoot returns an error if any component of the name +// references a location outside of dir. +// +// See [Root] for details and limitations. +func OpenInRoot(dir, name string) (*File, error) { + r, err := OpenRoot(dir) + if err != nil { + return nil, err + } + defer r.Close() + return r.Open(name) +} + // Root may be used to only access files within a single directory tree. // // Methods on Root can only access files and directories beneath a root directory. diff --git a/src/os/root_test.go b/src/os/root_test.go index 1cff474b939..288b4060cd8 100644 --- a/src/os/root_test.go +++ b/src/os/root_test.go @@ -1157,3 +1157,26 @@ func TestRootRaceRenameDir(t *testing.T) { } } } + +func TestOpenInRoot(t *testing.T) { + dir := makefs(t, []string{ + "file", + "link => ../ROOT/file", + }) + f, err := os.OpenInRoot(dir, "file") + if err != nil { + t.Fatalf("OpenInRoot(`file`) = %v, want success", err) + } + f.Close() + for _, name := range []string{ + "link", + "../ROOT/file", + dir + "/file", + } { + f, err := os.OpenInRoot(dir, name) + if err == nil { + f.Close() + t.Fatalf("OpenInRoot(%q) = nil, want error", name) + } + } +}