diff options
Diffstat (limited to 'util')
| -rw-r--r-- | util/errors.go | 4 | ||||
| -rw-r--r-- | util/util.go | 48 | ||||
| -rw-r--r-- | util/util_test.go | 7 |
3 files changed, 50 insertions, 9 deletions
diff --git a/util/errors.go b/util/errors.go index f10569e..3c87a2c 100644 --- a/util/errors.go +++ b/util/errors.go @@ -72,7 +72,7 @@ type ErrWriter struct { err error } -// NewErrWriter creates an ErrWriter which wraps the provided reader. +// NewErrWriter creates an ErrWriter which wraps the provided writer. func NewErrWriter(writer io.Writer) *ErrWriter { return &ErrWriter{w: writer, err: nil} } @@ -116,7 +116,7 @@ func NeverError(err error) { } var ( - // testEnvVarName is the name on an environment variable that should be + // testEnvVarName is the name of an environment variable that should be // set to an empty mountpoint. This is only used for integration tests. // If not set, integration tests are skipped. testEnvVarName = "TEST_FILESYSTEM_ROOT" diff --git a/util/util.go b/util/util.go index 3de4a1a..1dab335 100644 --- a/util/util.go +++ b/util/util.go @@ -25,14 +25,17 @@ package util import ( "bufio" - "math" + "fmt" + "log" "os" "os/user" "strconv" "unsafe" + + "golang.org/x/sys/unix" ) -// Ptr converts an Go byte array to a pointer to the start of the array. +// Ptr converts a Go byte array to a pointer to the start of the array. func Ptr(slice []byte) unsafe.Pointer { if len(slice) == 0 { return nil @@ -43,15 +46,15 @@ func Ptr(slice []byte) unsafe.Pointer { // ByteSlice takes a pointer to some data and views it as a slice of bytes. // Note, indexing into this slice is unsafe. func ByteSlice(ptr unsafe.Pointer) []byte { - // Silce must fix in 32-bit address space to build on 32-bit platforms. - return (*[math.MaxInt32]byte)(ptr)[:] + // Slice must fit in the smallest address space go supports. + return (*[1 << 30]byte)(ptr)[:] } // PointerSlice takes a pointer to an array of pointers and views it as a slice // of pointers. Note, indexing into this slice is unsafe. func PointerSlice(ptr unsafe.Pointer) []unsafe.Pointer { - // Silce must fix in 32-bit address space to build on 32-bit platforms. - return (*[math.MaxInt32 / 4]unsafe.Pointer)(ptr)[:] + // Slice must fit in the smallest address space go supports. + return (*[1 << 28]unsafe.Pointer)(ptr)[:] } // Index returns the first index i such that inVal == inArray[i]. @@ -118,12 +121,43 @@ func AtoiOrPanic(input string) int { return i } +// UserFromUID returns the User corresponding to the given user id. +func UserFromUID(uid int64) (*user.User, error) { + return user.LookupId(strconv.FormatInt(uid, 10)) +} + // EffectiveUser returns the user entry corresponding to the effective user. func EffectiveUser() (*user.User, error) { - return user.LookupId(strconv.Itoa(os.Geteuid())) + return UserFromUID(int64(os.Geteuid())) } // IsUserRoot checks if the effective user is root. func IsUserRoot() bool { return os.Geteuid() == 0 } + +// Chown changes the owner of a File to a User. +func Chown(file *os.File, user *user.User) error { + uid := AtoiOrPanic(user.Uid) + gid := AtoiOrPanic(user.Gid) + return file.Chown(uid, gid) +} + +// IsKernelVersionAtLeast returns true if the Linux kernel version is at least +// major.minor. If something goes wrong it assumes false. +func IsKernelVersionAtLeast(major, minor int) bool { + var uname unix.Utsname + if err := unix.Uname(&uname); err != nil { + log.Printf("Uname failed [%v], assuming old kernel", err) + return false + } + release := string(uname.Release[:]) + log.Printf("Kernel version is %s", release) + var actualMajor, actualMinor int + if n, _ := fmt.Sscanf(release, "%d.%d", &actualMajor, &actualMinor); n != 2 { + log.Printf("Unrecognized uname format %q, assuming old kernel", release) + return false + } + return actualMajor > major || + (actualMajor == major && actualMinor >= minor) +} diff --git a/util/util_test.go b/util/util_test.go index 7739edd..70e7070 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -91,3 +91,10 @@ func TestNeverErrorNoPanic(t *testing.T) { NeverError(nil) } + +func TestIsKernelVersionAtLeast(t *testing.T) { + // Even just running Go requires at least v2.6.23, so... + if !IsKernelVersionAtLeast(2, 6) { + t.Error("IsKernelVersionAtLeast() is broken") + } +} |