os: add Root.ReadFile and Root.WriteFile

For #73126

Change-Id: Ie69cc274e7b59f958c239520318b89ff0141e26b
Reviewed-on: https://go-review.googlesource.com/c/go/+/674315
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
This commit is contained in:
Damien Neil 2025-05-19 15:51:14 -07:00 committed by Gopher Robot
parent 3ae95aafb5
commit 4b7aa542eb
5 changed files with 50 additions and 0 deletions

2
api/next/73126.txt Normal file
View File

@ -0,0 +1,2 @@
pkg os, method (*Root) ReadFile(string) ([]uint8, error) #73126
pkg os, method (*Root) WriteFile(string, []uint8, fs.FileMode) error #73126

View File

@ -6,7 +6,9 @@ The [os.Root] type supports the following additional methods:
* [os.Root.Lchown]
* [os.Root.Link]
* [os.Root.MkdirAll]
* [os.Root.ReadFile]
* [os.Root.Readlink]
* [os.Root.RemoveAll]
* [os.Root.Rename]
* [os.Root.Symlink]
* [os.Root.WriteFile]

View File

@ -0,0 +1 @@
<!-- go.dev/issue/73126 is documented as part of 67002 -->

View File

@ -248,6 +248,31 @@ func (r *Root) Symlink(oldname, newname string) error {
return rootSymlink(r, oldname, newname)
}
// ReadFile reads the named file in the root and returns its contents.
// See [ReadFile] for more details.
func (r *Root) ReadFile(name string) ([]byte, error) {
f, err := r.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
return readFileContents(statOrZero(f), f.Read)
}
// WriteFile writes data to the named file in the root, creating it if necessary.
// See [WriteFile] for more details.
func (r *Root) WriteFile(name string, data []byte, perm FileMode) error {
f, err := r.OpenFile(name, O_WRONLY|O_CREATE|O_TRUNC, perm)
if err != nil {
return err
}
_, err = f.Write(data)
if err1 := f.Close(); err == nil {
err = err1
}
return err
}
func (r *Root) logOpen(name string) {
if log := testlog.Logger(); log != nil {
// This won't be right if r's name has changed since it was opened,

View File

@ -1899,3 +1899,23 @@ func TestRootRemoveDot(t *testing.T) {
t.Error(`root.Remove(All)?(".") removed the root`)
}
}
func TestRootWriteReadFile(t *testing.T) {
dir := t.TempDir()
root, err := os.OpenRoot(dir)
if err != nil {
t.Fatal(err)
}
defer root.Close()
name := "filename"
want := []byte("file contents")
if err := root.WriteFile(name, want, 0o666); err != nil {
t.Fatalf("root.WriteFile(%q, %q, 0o666) = %v; want nil", name, want, err)
}
got, err := root.ReadFile(name)
if err != nil {
t.Fatalf("root.ReadFile(%q) = %q, %v; want %q, nil", name, got, err, want)
}
}