auparse/mk_audit_exit_codes.go (174 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. //go:build ignore // +build ignore package main import ( "bufio" "bytes" "flag" "fmt" "os" "os/exec" "path/filepath" "regexp" "sort" "strconv" "text/template" ) const includeErrno = ` #include <asm-generic/errno.h> ` type ErrorNumber struct { Name string Value int } // TemplateParams is the data used in evaluating the template. type TemplateParams struct { Command string NameToNum []ErrorNumber NumToName []ErrorNumber } const header = ` // Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // Code generated by {{.Command}} - DO NOT EDIT. ` var headerTmpl = template.Must(template.New("header").Parse(header)) const godefsTemplate = ` package auparse /* #include <asm-generic/errno.h> */ import "C" // AuditErrnoToNum contains a mapping of POSIX error names to errnos (error numbers). var AuditErrnoToNum = map[string]int{ {{- range $err := .NameToNum }} "{{ $err.Name }}": C.{{ $err.Name }}, {{- end }} } // AuditErrnoToName contains a mapping of errnos (error numbers) to POSIX names. var AuditErrnoToName = map[int]string{ {{- range $err := .NumToName }} {{ $err.Value }}: "{{ $err.Name }}", {{- end }} } ` var tmpl = template.Must(template.New("message_types").Parse(godefsTemplate)) var errnoDefRegex = regexp.MustCompile(`^#define\s+(E\w+)\s+(\w+)`) func readErrorNumbers() ([]ErrorNumber, error) { cmd := exec.Command("gcc", "-E", "-dD", "-") cmd.Stdin = bytes.NewBufferString(includeErrno) out, err := cmd.Output() if err != nil { return nil, err } errorToNum := map[string]int{} s := bufio.NewScanner(bytes.NewReader(out)) for s.Scan() { matches := errnoDefRegex.FindStringSubmatch(s.Text()) if len(matches) != 3 { continue } errno, err := strconv.Atoi(matches[2]) if err != nil { errorToNum[matches[1]] = -1 continue } errorToNum[matches[1]] = errno } var errnos []ErrorNumber for name, value := range errorToNum { errnos = append(errnos, ErrorNumber{ Name: name, Value: value, }) } sort.Slice(errnos, func(i, j int) bool { if errnos[i].Value == errnos[j].Value { return errnos[i].Name < errnos[j].Name } return errnos[i].Value < errnos[j].Value }) return errnos, nil } func run() error { tmp, err := os.MkdirTemp("", "mk_audit_exit_codes") if err != nil { return err } defer os.RemoveAll(tmp) if err := os.Chdir(tmp); err != nil { return err } errnos, err := readErrorNumbers() if err != nil { return err } // Filter duplicates and sort by name. var numToName []ErrorNumber for _, errno := range errnos { if errno.Value >= 0 { numToName = append(numToName, errno) } } // Create output file. f, err := os.Create("defs.go") if err != nil { return err } defer f.Close() // Evaluate template. r := TemplateParams{ Command: filepath.Base(os.Args[0]), NameToNum: errnos, NumToName: numToName, } if err := tmpl.Execute(f, r); err != nil { return err } output, err := exec.Command("go", "tool", "cgo", "-godefs", "defs.go").Output() if err != nil { return err } buf := new(bytes.Buffer) if err = headerTmpl.Execute(buf, r); err != nil { return nil } s := bufio.NewScanner(bytes.NewReader(output)) for s.Scan() { if !bytes.HasPrefix(s.Bytes(), []byte("//")) { buf.Write(s.Bytes()) buf.WriteByte('\n') } } if err = os.WriteFile(flagOut, buf.Bytes(), 0o644); err != nil { return err } _, err = exec.Command("gofmt", "-w", "-s", flagOut).Output() if err != nil { return err } return nil } var flagOut string func main() { flag.StringVar(&flagOut, "out", "zaudit_exit_codes.go", "output file") flag.Parse() var err error flagOut, err = filepath.Abs(flagOut) if err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } if err := run(); err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } }