Skip to content

Commit

Permalink
os: do not skip directory entries with zero inodes on wasip1
Browse files Browse the repository at this point in the history
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 <[email protected]>
Run-TryBot: Ian Lance Taylor <[email protected]>
Auto-Submit: Ian Lance Taylor <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
Reviewed-by: Johan Brandhorst-Satzkorn <[email protected]>
  • Loading branch information
achille-roussel authored and gopherbot committed Jul 6, 2023
1 parent e6ec2a3 commit 39c5070
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 3 deletions.
9 changes: 9 additions & 0 deletions src/os/dir_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 5 additions & 1 deletion src/os/dir_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
9 changes: 7 additions & 2 deletions src/syscall/dirent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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))
Expand Down

0 comments on commit 39c5070

Please sign in to comment.