unix: add ioctl wrappers for RTC wake alarm on Linux

Add wrappers to set and get RTC wake alarm on Linux via the
RTC_WKALM_SET and RTC_WKALM_RD ioctls.

Change-Id: I98c36b2252b2fe65cfaba5dde879f6019ff1ae91
GitHub-Last-Rev: a78d0f41932c6f400784b65b1fff10eb6f1a802c
GitHub-Pull-Request: golang/sys#71
Reviewed-on: https://go-review.googlesource.com/c/sys/+/236140
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 942a4bb..7b7c727 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -97,6 +97,12 @@
 	return err
 }
 
+func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
+	err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value)))
+	runtime.KeepAlive(value)
+	return err
+}
+
 func IoctlGetUint32(fd int, req uint) (uint32, error) {
 	var value uint32
 	err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
@@ -109,6 +115,12 @@
 	return &value, err
 }
 
+func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
+	var value RTCWkAlrm
+	err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value)))
+	return &value, err
+}
+
 //sys	Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
 
 func Link(oldpath string, newpath string) (err error) {
diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go
index a8221d3..01f29ca 100644
--- a/unix/syscall_linux_test.go
+++ b/unix/syscall_linux_test.go
@@ -73,6 +73,22 @@
 	t.Logf("RTC time: %04d-%02d-%02d %02d:%02d:%02d", v.Year+1900, v.Mon+1, v.Mday, v.Hour, v.Min, v.Sec)
 }
 
+func TestIoctlGetRTCWkAlrm(t *testing.T) {
+	f, err := os.Open("/dev/rtc0")
+	if err != nil {
+		t.Skipf("skipping test, %v", err)
+	}
+	defer f.Close()
+
+	v, err := unix.IoctlGetRTCWkAlrm(int(f.Fd()))
+	if err != nil {
+		t.Fatalf("failed to perform ioctl: %v", err)
+	}
+
+	t.Logf("RTC wake alarm enabled '%d'; time: %04d-%02d-%02d %02d:%02d:%02d",
+		v.Enabled, v.Time.Year+1900, v.Time.Mon+1, v.Time.Mday, v.Time.Hour, v.Time.Min, v.Time.Sec)
+}
+
 func TestPpoll(t *testing.T) {
 	if runtime.GOOS == "android" {
 		t.Skip("mkfifo syscall is not available on android, skipping test")