Fix Limits type

Linux limits are uint64, not int64[0]. "unlimited" is also defined as
max uint64.

[0]: https://github.com/torvalds/linux/blob/7c53f6b671f4aba70ff15e1b05148b10d58c2837/include/uapi/linux/resource.h#L48-L53

Signed-off-by: Ben Kochie <[email protected]>
diff --git a/proc_limits.go b/proc_limits.go
index 91ee24d..5a6451f 100644
--- a/proc_limits.go
+++ b/proc_limits.go
@@ -16,6 +16,7 @@
 import (
 	"bufio"
 	"fmt"
+	"math"
 	"os"
 	"regexp"
 	"strconv"
@@ -26,46 +27,46 @@
 // http://man7.org/linux/man-pages/man2/getrlimit.2.html.
 type ProcLimits struct {
 	// CPU time limit in seconds.
-	CPUTime int64
+	CPUTime uint64
 	// Maximum size of files that the process may create.
-	FileSize int64
+	FileSize uint64
 	// Maximum size of the process's data segment (initialized data,
 	// uninitialized data, and heap).
-	DataSize int64
+	DataSize uint64
 	// Maximum size of the process stack in bytes.
-	StackSize int64
+	StackSize uint64
 	// Maximum size of a core file.
-	CoreFileSize int64
+	CoreFileSize uint64
 	// Limit of the process's resident set in pages.
-	ResidentSet int64
+	ResidentSet uint64
 	// Maximum number of processes that can be created for the real user ID of
 	// the calling process.
-	Processes int64
+	Processes uint64
 	// Value one greater than the maximum file descriptor number that can be
 	// opened by this process.
-	OpenFiles int64
+	OpenFiles uint64
 	// Maximum number of bytes of memory that may be locked into RAM.
-	LockedMemory int64
+	LockedMemory uint64
 	// Maximum size of the process's virtual memory address space in bytes.
-	AddressSpace int64
+	AddressSpace uint64
 	// Limit on the combined number of flock(2) locks and fcntl(2) leases that
 	// this process may establish.
-	FileLocks int64
+	FileLocks uint64
 	// Limit of signals that may be queued for the real user ID of the calling
 	// process.
-	PendingSignals int64
+	PendingSignals uint64
 	// Limit on the number of bytes that can be allocated for POSIX message
 	// queues for the real user ID of the calling process.
-	MsqqueueSize int64
+	MsqqueueSize uint64
 	// Limit of the nice priority set using setpriority(2) or nice(2).
-	NicePriority int64
+	NicePriority uint64
 	// Limit of the real-time priority set using sched_setscheduler(2) or
 	// sched_setparam(2).
-	RealtimePriority int64
+	RealtimePriority uint64
 	// Limit (in microseconds) on the amount of CPU time that a process
 	// scheduled under a real-time scheduling policy may consume without making
 	// a blocking system call.
-	RealtimeTimeout int64
+	RealtimeTimeout uint64
 }
 
 const (
@@ -105,37 +106,37 @@
 
 		switch fields[0] {
 		case "Max cpu time":
-			l.CPUTime, err = parseInt(fields[1])
+			l.CPUTime, err = parseLimitsUInt(fields[1])
 		case "Max file size":
-			l.FileSize, err = parseInt(fields[1])
+			l.FileSize, err = parseLimitsUInt(fields[1])
 		case "Max data size":
-			l.DataSize, err = parseInt(fields[1])
+			l.DataSize, err = parseLimitsUInt(fields[1])
 		case "Max stack size":
-			l.StackSize, err = parseInt(fields[1])
+			l.StackSize, err = parseLimitsUInt(fields[1])
 		case "Max core file size":
-			l.CoreFileSize, err = parseInt(fields[1])
+			l.CoreFileSize, err = parseLimitsUInt(fields[1])
 		case "Max resident set":
-			l.ResidentSet, err = parseInt(fields[1])
+			l.ResidentSet, err = parseLimitsUInt(fields[1])
 		case "Max processes":
-			l.Processes, err = parseInt(fields[1])
+			l.Processes, err = parseLimitsUInt(fields[1])
 		case "Max open files":
-			l.OpenFiles, err = parseInt(fields[1])
+			l.OpenFiles, err = parseLimitsUInt(fields[1])
 		case "Max locked memory":
-			l.LockedMemory, err = parseInt(fields[1])
+			l.LockedMemory, err = parseLimitsUInt(fields[1])
 		case "Max address space":
-			l.AddressSpace, err = parseInt(fields[1])
+			l.AddressSpace, err = parseLimitsUInt(fields[1])
 		case "Max file locks":
-			l.FileLocks, err = parseInt(fields[1])
+			l.FileLocks, err = parseLimitsUInt(fields[1])
 		case "Max pending signals":
-			l.PendingSignals, err = parseInt(fields[1])
+			l.PendingSignals, err = parseLimitsUInt(fields[1])
 		case "Max msgqueue size":
-			l.MsqqueueSize, err = parseInt(fields[1])
+			l.MsqqueueSize, err = parseLimitsUInt(fields[1])
 		case "Max nice priority":
-			l.NicePriority, err = parseInt(fields[1])
+			l.NicePriority, err = parseLimitsUInt(fields[1])
 		case "Max realtime priority":
-			l.RealtimePriority, err = parseInt(fields[1])
+			l.RealtimePriority, err = parseLimitsUInt(fields[1])
 		case "Max realtime timeout":
-			l.RealtimeTimeout, err = parseInt(fields[1])
+			l.RealtimeTimeout, err = parseLimitsUInt(fields[1])
 		}
 		if err != nil {
 			return ProcLimits{}, err
@@ -145,11 +146,13 @@
 	return l, s.Err()
 }
 
-func parseInt(s string) (int64, error) {
+func parseLimitsUInt(s string) (uint64, error) {
 	if s == limitsUnlimited {
-		return -1, nil
+		// From Linux include/uapi/linux/resource.h:
+		//   #define RLIM64_INFINITY (~0ULL)
+		return math.MaxUint64, nil
 	}
-	i, err := strconv.ParseInt(s, 10, 64)
+	i, err := strconv.ParseUint(s, 10, 64)
 	if err != nil {
 		return 0, fmt.Errorf("couldn't parse value %s: %s", s, err)
 	}
diff --git a/proc_limits_test.go b/proc_limits_test.go
index 9148e28..bb8ae61 100644
--- a/proc_limits_test.go
+++ b/proc_limits_test.go
@@ -28,10 +28,10 @@
 
 	for _, test := range []struct {
 		name string
-		want int64
-		have int64
+		want uint64
+		have uint64
 	}{
-		{name: "cpu time", want: -1, have: l.CPUTime},
+		{name: "cpu time", want: 18446744073709551615, have: l.CPUTime},
 		{name: "open files", want: 2048, have: l.OpenFiles},
 		{name: "msgqueue size", want: 819200, have: l.MsqqueueSize},
 		{name: "nice priority", want: 0, have: l.NicePriority},