unix: align the getdents buffer

getdents64 stores a 64-bit d_ino at the start of every entry, so the entries
are aligned only if the buffer is. Go promises no alignment for a []byte, and
sparc64 faults on the misaligned store rather than fixing it up, returning
EFAULT.

Buffers from make are already 8-aligned, so this is a no-op unless the caller
passes a sub-slice.

Updates golang/go#55000

Change-Id: I3724af7c4ef7debc4bdd9d0b1c3130c312094957
GitHub-Last-Rev: 2d416d91ae1f7ad56c32636521af5b2c61a567b2
GitHub-Pull-Request: golang/sys#291
Reviewed-on: https://go-review.googlesource.com/c/sys/+/822906
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Kirill Kolyshkin <kolyshkin@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 6926057..8fbfb0d 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -1991,7 +1991,24 @@
 	return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0)
 }
 
-//sys	Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
+//sys	getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
+
+// Getdents reads directory entries from fd into buf.
+func Getdents(fd int, buf []byte) (n int, err error) {
+	// getdents64 stores d_ino with a 64-bit write, which faults on
+	// strict-alignment targets unless buf is 8-aligned.
+	if len(buf) > 0 {
+		if off := int(-uintptr(unsafe.Pointer(&buf[0])) & 7); off > 0 && off < len(buf) {
+			n, err = getdents(fd, buf[off:])
+			if n > 0 {
+				copy(buf, buf[off:off+n])
+			}
+			return n, err
+		}
+	}
+	return getdents(fd, buf)
+}
+
 //sysnb	Getpgid(pid int) (pgid int, err error)
 
 func Getpgrp() (pid int) {
diff --git a/unix/zsyscall_linux.go b/unix/zsyscall_linux.go
index 5788c2a..86d3b56 100644
--- a/unix/zsyscall_linux.go
+++ b/unix/zsyscall_linux.go
@@ -943,7 +943,7 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdents(fd int, buf []byte) (n int, err error) {
+func getdents(fd int, buf []byte) (n int, err error) {
 	var _p0 unsafe.Pointer
 	if len(buf) > 0 {
 		_p0 = unsafe.Pointer(&buf[0])