aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAchille Roussel <achille.roussel@gmail.com>2023-07-04 18:15:58 -0700
committerGopher Robot <gobot@golang.org>2023-07-06 23:23:41 +0000
commit39c507071251dbf5ea098077ad0e791679dae548 (patch)
treedf9d399551faf62faa74dadc99d238ed51095db9
parente6ec2a34dc1e1c319588fb0cb449abf55291977f (diff)
downloadgo-39c507071251dbf5ea098077ad0e791679dae548.tar.gz
go-39c507071251dbf5ea098077ad0e791679dae548.zip
os: do not skip directory entries with zero inodes on wasip1
When building programs to GOOS=wasip1, the program does not have the guarantees that the underlying directories will come from a file system where a zero inode value indicates that the entry was deleted but not yet removed from the directory. The host runtime may be running on windows or may be exposing virtual user-space file systems that do not have the concept of inodes. In those setup, we assume that the host runtime is in charge of dealing with edge cases such as skipping directory entries with zero inodes when needed, and the guest application should trust the list of entries that it sees; therefore, we disable skipping over zero inodes on wasip1. Change-Id: I99aa562441cdb4182965f270af054cf3cf7f8f20 Reviewed-on: https://go-review.googlesource.com/c/go/+/507915 Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
-rw-r--r--src/os/dir_darwin.go9
-rw-r--r--src/os/dir_unix.go6
-rw-r--r--src/syscall/dirent.go9
3 files changed, 21 insertions, 3 deletions
diff --git a/src/os/dir_darwin.go b/src/os/dir_darwin.go
index deba3eb37f..e6d5bda24b 100644
--- a/src/os/dir_darwin.go
+++ b/src/os/dir_darwin.go
@@ -54,6 +54,15 @@ func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEn
if entptr == nil { // EOF
break
}
+ // Darwin may return a zero inode when a directory entry has been
+ // deleted but not yet removed from the directory. The man page for
+ // getdirentries(2) states that programs are responsible for skipping
+ // those entries:
+ //
+ // Users of getdirentries() should skip entries with d_fileno = 0,
+ // as such entries represent files which have been deleted but not
+ // yet removed from the directory entry.
+ //
if dirent.Ino == 0 {
continue
}
diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go
index 004b9fbb2b..266a78acaf 100644
--- a/src/os/dir_unix.go
+++ b/src/os/dir_unix.go
@@ -89,7 +89,11 @@ func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEn
if !ok {
break
}
- if ino == 0 {
+ // When building to wasip1, the host runtime might be running on Windows
+ // or might expose a remote file system which does not have the concept
+ // of inodes. Therefore, we cannot make the assumption that it is safe
+ // to skip entries with zero inodes.
+ if ino == 0 && runtime.GOOS != "wasip1" {
continue
}
const namoff = uint64(unsafe.Offsetof(syscall.Dirent{}.Name))
diff --git a/src/syscall/dirent.go b/src/syscall/dirent.go
index eee94bf73c..1a0f1eec11 100644
--- a/src/syscall/dirent.go
+++ b/src/syscall/dirent.go
@@ -6,7 +6,10 @@
package syscall
-import "unsafe"
+import (
+ "runtime"
+ "unsafe"
+)
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
@@ -75,7 +78,9 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
if !ok {
break
}
- if ino == 0 { // File absent in directory.
+ // See src/os/dir_unix.go for the reason why this condition is
+ // excluded on wasip1.
+ if ino == 0 && runtime.GOOS != "wasip1" { // File absent in directory.
continue
}
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))