| // Program mknames parses the cap_names.h file and creates an |
| // equivalent names.go file including comments on each cap.Value from |
| // the documentation directory. |
| package main |
| |
| import ( |
| "bytes" |
| "flag" |
| "fmt" |
| "io" |
| "io/ioutil" |
| "log" |
| "strings" |
| ) |
| |
| var ( |
| header = flag.String("header", "", "name of header file") |
| text = flag.String("textdir", "", "directory name for value txt files") |
| ) |
| |
| func main() { |
| flag.Parse() |
| |
| if *header == "" { |
| log.Fatal("usage: mknames --header=.../cap_names.h") |
| } |
| d, err := ioutil.ReadFile(*header) |
| if err != nil { |
| log.Fatal("reading:", err) |
| } |
| |
| b := bytes.NewBuffer(d) |
| |
| var list []string |
| for { |
| line, err := b.ReadString('\n') |
| if err == io.EOF { |
| break |
| } |
| if !strings.Contains(line, `"`) { |
| continue |
| } |
| i := strings.Index(line, `"`) |
| line = line[i+1:] |
| i = strings.Index(line, `"`) |
| line = line[:i] |
| list = append(list, line) |
| } |
| |
| // generate package file names.go |
| fmt.Print(`package cap |
| |
| /* ** DO NOT EDIT THIS FILE. IT WAS AUTO-GENERATED BY LIBCAP'S GO BUILDER (mknames.go) ** */ |
| |
| // NamedCount holds the number of capability values with official |
| // names known at the time this libcap/cap version, was released. The |
| // "../libcap/cap" package is fully able to manipulate higher numbered |
| // capability values by numerical value. However, if you find |
| // cap.NamedCount < cap.MaxBits(), it is probably time to upgrade this |
| // package on your system. |
| // |
| // FWIW the userspace tool '/sbin/capsh' also contains a runtime check |
| // for the condition that libcap is behind the running kernel in this |
| // way. |
| const NamedCount = `, len(list), ` |
| |
| // CHOWN etc., are the named capability values of the Linux |
| // kernel. The canonical source for each name is the |
| // "uapi/linux/capabilities.h" file. Some values may not be available |
| // (yet) where the kernel is older. The actual number of capabities |
| // supported by the running kernel can be obtained using the |
| // cap.MaxBits() function. |
| const ( |
| `) |
| bits := make(map[string]string) |
| for i, name := range list { |
| doc := fmt.Sprintf("%s/%d.txt", *text, i) |
| content, err := ioutil.ReadFile(doc) |
| if err != nil { |
| log.Fatalf("filed to read %q: %v", doc, err) |
| } |
| detail := strings.Split(strings.Replace(string(content), "CAP_", "cap.", -1), "\n") |
| if i != 0 { |
| fmt.Println() |
| } |
| v := strings.ToUpper(strings.TrimPrefix(name, "cap_")) |
| for j, line := range detail { |
| preamble := "" |
| offset := 0 |
| if j == 0 { |
| if !strings.HasPrefix(line, "Allows ") { |
| log.Fatalf("line should begin \"Allows \": got %s:%d:%q", doc, j, line) |
| } |
| preamble = fmt.Sprint(v, " a") |
| offset = 1 |
| } |
| if len(line) != 0 || j != len(detail)-1 { |
| fmt.Printf(" // %s%s\n", preamble, line[offset:]) |
| } |
| } |
| bits[name] = v |
| if i == 0 { |
| fmt.Println(v, " Value = iota") |
| } else { |
| fmt.Println(v) |
| } |
| } |
| fmt.Print(`) |
| |
| var names = map[Value]string{ |
| `) |
| for _, name := range list { |
| fmt.Printf("%s: %q,\n", bits[name], name) |
| } |
| fmt.Print(`} |
| |
| var bits = map[string]Value { |
| `) |
| for _, name := range list { |
| fmt.Printf("%q: %s,\n", name, bits[name]) |
| } |
| fmt.Println(`}`) |
| } |