Skip to content

Commit

Permalink
Merge pull request #153 from kolyshkin/list-enh
Browse files Browse the repository at this point in the history
capability: add ListKnown, ListSupported; deprecate List
  • Loading branch information
kolyshkin authored Sep 25, 2024
2 parents 29394de + 166b98b commit aaea55a
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 19 deletions.
2 changes: 2 additions & 0 deletions capability/capability.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ func NewFile2(path string) (Capabilities, error) {

// LastCap returns highest valid capability of the running kernel,
// or an error if it can not be obtained.
//
// See also: [ListSupported].
func LastCap() (Cap, error) {
return lastCap()
}
52 changes: 39 additions & 13 deletions capability/capability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ import (
"testing"
)

// Based on the fact Go 1.18+ supports Linux >= 2.6.32, and
// - CAP_MAC_ADMIN (33) was added in 2.6.25;
// - CAP_SYSLOG (34) was added in 2.6.38;
// - CAP_CHECKPOINT_RESTORE (40) was added in 5.9, and it is
// the last added capability as of today (July 2024);
//
// LastCap return value should be between minLastCap and maxLastCap.
const (
minLastCap = CAP_MAC_ADMIN
maxLastCap = CAP_CHECKPOINT_RESTORE
)

func TestLastCap(t *testing.T) {
last, err := LastCap()
switch runtime.GOOS {
Expand All @@ -24,21 +36,35 @@ func TestLastCap(t *testing.T) {
}

// Sanity checks (Linux only).
//
// Based on the fact Go 1.18+ supports Linux >= 2.6.32, and
// - CAP_MAC_ADMIN (33) was added in 2.6.25;
// - CAP_SYSLOG (34) was added in 2.6.38;
// - CAP_CHECKPOINT_RESTORE (40) was added in 5.9, and it is
// the last added capability as of today (July 2024);
// LastCap return value should be between minCap and maxCap.
minCap := CAP_MAC_ADMIN
maxCap := CAP_CHECKPOINT_RESTORE
if last < minCap {
if last < minLastCap {
t.Fatalf("LastCap returned %d (%s), expected >= %d (%s)",
last, last, minCap, minCap)
last, last, minLastCap, minLastCap)
}
if last > maxCap {
if last > maxLastCap {
t.Fatalf("LastCap returned %d, expected <= %d (%s). Package needs to be updated.",
last, maxCap, maxCap)
last, maxLastCap, maxLastCap)
}
}

func TestListSupported(t *testing.T) {
list, err := ListSupported()
switch runtime.GOOS {
case "linux":
if err != nil {
t.Fatal(err)
}
default:
if err == nil {
t.Fatal(runtime.GOOS, ": want error, got nil")
}
}
if runtime.GOOS != "linux" {
return
}
// Sanity check (Linux only).
t.Logf("got +%v (len %d)", list, len(list))
minLen := int(minLastCap) + 1
if len(list) < minLen {
t.Fatalf("result is too short (got %d, want %d): +%v", len(list), minLen, list)
}
}
27 changes: 27 additions & 0 deletions capability/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

package capability

import "slices"

type CapType uint

func (c CapType) String() string {
Expand Down Expand Up @@ -301,3 +303,28 @@ const (
// Introduced in kernel 5.9
CAP_CHECKPOINT_RESTORE = Cap(40)
)

// List returns the list of all capabilities known to the package.
//
// Deprecated: use [ListKnown] or [ListSupported] instead.
func List() []Cap {
return ListKnown()
}

// ListKnown returns the list of all capabilities known to the package.
func ListKnown() []Cap {
return list()
}

// ListSupported retuns the list of all capabilities known to the package,
// except those that are not supported by the currently running Linux kernel.
func ListSupported() ([]Cap, error) {
last, err := LastCap()
if err != nil {
return nil, err
}
return slices.DeleteFunc(list(), func(c Cap) bool {
// Remove caps not supported by the kernel.
return c > last
}), nil
}
5 changes: 2 additions & 3 deletions capability/enum_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions capability/enumgen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type generator struct {
}

func (g *generator) writeHeader() {
g.buf.WriteString("// generated file; DO NOT EDIT - use go generate in directory with source\n")
g.buf.WriteString("// Code generated by go generate; DO NOT EDIT.\n")
g.buf.WriteString("\n")
g.buf.WriteString("package capability")
}
Expand All @@ -43,8 +43,7 @@ func (g *generator) writeStringFunc() {

func (g *generator) writeListFunc() {
g.buf.WriteString("\n")
g.buf.WriteString("// List returns list of all supported capabilities\n")
g.buf.WriteString("func List() []Cap {\n")
g.buf.WriteString("func list() []Cap {\n")
g.buf.WriteString("return []Cap{\n")
for _, cap := range g.caps {
fmt.Fprintf(&g.buf, "%s,\n", cap)
Expand Down

0 comments on commit aaea55a

Please sign in to comment.