Browse Source

unix: add Major, Minor and Mkdev functions on Darwin

Add Major, Minor and Mkdev functions for converting devices numbers to
their major/minor components and vice versa.

The functions follow the behavior of the macros defined in Darwin's
sys/types.h header. However, the parameter and return types are changed
to match the respective Linux implementation of these functions.

Test the conversion macros with some well-known static device numbers
for devices which should be present on any Darwin system.

Updates golang/go#8106

Change-Id: I1862be64684cc1b5a53e15a883819571e368cb2b
Reviewed-on: https://go-review.googlesource.com/60610
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Tobias Klauser 8 years ago
parent
commit
a07a691ac8
2 changed files with 73 additions and 0 deletions
  1. 24 0
      unix/dev_darwin.go
  2. 49 0
      unix/dev_darwin_test.go

+ 24 - 0
unix/dev_darwin.go

@@ -0,0 +1,24 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Functions to access/create device major and minor numbers matching the
+// encoding used in Darwin's sys/types.h header.
+
+package unix
+
+// Major returns the major component of a Darwin device number.
+func Major(dev uint64) uint32 {
+	return uint32((dev >> 24) & 0xff)
+}
+
+// Minor returns the minor component of a Darwin device number.
+func Minor(dev uint64) uint32 {
+	return uint32(dev & 0xffffff)
+}
+
+// Mkdev returns a Darwin device number generated from the given major and minor
+// components.
+func Mkdev(major, minor uint32) uint64 {
+	return uint64((major << 24) | minor)
+}

+ 49 - 0
unix/dev_darwin_test.go

@@ -0,0 +1,49 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix_test
+
+import (
+	"fmt"
+	"testing"
+
+	"golang.org/x/sys/unix"
+)
+
+func TestDevices(t *testing.T) {
+	testCases := []struct {
+		path  string
+		major uint32
+		minor uint32
+	}{
+		// Most of the device major/minor numbers on Darwin are
+		// dynamically generated by devfs. These are some well-known
+		// static numbers.
+		{"/dev/ttyp0", 4, 0},
+		{"/dev/ttys0", 4, 48},
+		{"/dev/ptyp0", 5, 0},
+		{"/dev/ptyr0", 5, 32},
+	}
+	for _, tc := range testCases {
+		t.Run(fmt.Sprintf("%s %v:%v", tc.path, tc.major, tc.minor), func(t *testing.T) {
+			var stat unix.Stat_t
+			err := unix.Stat(tc.path, &stat)
+			if err != nil {
+				t.Errorf("failed to stat device: %v", err)
+				return
+			}
+
+			dev := uint64(stat.Rdev)
+			if unix.Major(dev) != tc.major {
+				t.Errorf("for %s Major(%#x) == %d, want %d", tc.path, dev, unix.Major(dev), tc.major)
+			}
+			if unix.Minor(dev) != tc.minor {
+				t.Errorf("for %s Minor(%#x) == %d, want %d", tc.path, dev, unix.Minor(dev), tc.minor)
+			}
+			if unix.Mkdev(tc.major, tc.minor) != dev {
+				t.Errorf("for %s Mkdev(%d, %d) == %#x, want %#x", tc.path, tc.major, tc.minor, unix.Mkdev(tc.major, tc.minor), dev)
+			}
+		})
+	}
+}