Skip to content

Commit 43d90c6

Browse files
committed
os: add Root
Add os.Root, a type which represents a directory and permits performing file operations within that directory. For #67002 Change-Id: I863f4f1bc320a89b1125ae4237761f3e9320a901 Reviewed-on: https://go-review.googlesource.com/c/go/+/612136 Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Quim Muntal <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 558f537 commit 43d90c6

17 files changed

Lines changed: 2243 additions & 70 deletions

File tree

api/next/67002.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pkg os, func OpenRoot(string) (*Root, error) #67002
2+
pkg os, method (*Root) Close() error #67002
3+
pkg os, method (*Root) Create(string) (*File, error) #67002
4+
pkg os, method (*Root) Mkdir(string, fs.FileMode) error #67002
5+
pkg os, method (*Root) Name() string #67002
6+
pkg os, method (*Root) Open(string) (*File, error) #67002
7+
pkg os, method (*Root) OpenFile(string, int, fs.FileMode) (*File, error) #67002
8+
pkg os, method (*Root) OpenRoot(string) (*Root, error) #67002
9+
pkg os, type Root struct #67002

doc/next/6-stdlib/1-os-root.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
### Directory-limited filesystem access
2+
3+
<!-- go.dev/issue/67002 -->
4+
The new [os.Root] type provides the ability to perform filesystem
5+
operations within a specific directory.
6+
7+
The [os.OpenRoot] function opens a directory and returns an [os.Root].
8+
Methods on [os.Root] operate within the directory and do not permit
9+
paths that refer to locations outside the directory, including
10+
ones that follow symbolic links out of the directory.
11+
12+
- [os.Root.Open] opens a file for reading.
13+
- [os.Root.Create] creates a file.
14+
- [os.Root.OpenFile] is the generalized open call.
15+
- [os.Root.Mkdir] creates a directory.
16+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<!-- os.Root -->

src/internal/syscall/windows/at_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func Openat(dirfd syscall.Handle, name string, flag int, perm uint32) (_ syscall
4242
}
4343
if flag&syscall.O_APPEND != 0 {
4444
access |= FILE_APPEND_DATA
45-
// Remove GENERIC_WRITE access unless O_TRUNC is set,
45+
// Remove FILE_WRITE_DATA access unless O_TRUNC is set,
4646
// in which case we need it to truncate the file.
4747
if flag&syscall.O_TRUNC == 0 {
4848
access &^= FILE_WRITE_DATA
@@ -99,7 +99,7 @@ func Openat(dirfd syscall.Handle, name string, flag int, perm uint32) (_ syscall
9999
fileAttrs,
100100
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
101101
disposition,
102-
FILE_SYNCHRONOUS_IO_NONALERT|options,
102+
FILE_SYNCHRONOUS_IO_NONALERT|FILE_OPEN_FOR_BACKUP_INTENT|options,
103103
0,
104104
0,
105105
)

src/os/file.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ func OpenFile(name string, flag int, perm FileMode) (*File, error) {
398398
return f, nil
399399
}
400400

401+
var errPathEscapes = errors.New("path escapes from parent")
402+
401403
// openDir opens a file which is assumed to be a directory. As such, it skips
402404
// the syscalls that make the file descriptor non-blocking as these take time
403405
// and will fail on file descriptors for directories.

src/os/file_windows.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,13 @@ func readReparseLink(path string) (string, error) {
415415
return "", err
416416
}
417417
defer syscall.CloseHandle(h)
418+
return readReparseLinkHandle(h)
419+
}
418420

421+
func readReparseLinkHandle(h syscall.Handle) (string, error) {
419422
rdbbuf := make([]byte, syscall.MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
420423
var bytesReturned uint32
421-
err = syscall.DeviceIoControl(h, syscall.FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
424+
err := syscall.DeviceIoControl(h, syscall.FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
422425
if err != nil {
423426
return "", err
424427
}

0 commit comments

Comments
 (0)