github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/tools/nogo/check/main.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Binary check is the nogo entrypoint. 16 package main 17 18 import ( 19 "encoding/json" 20 "flag" 21 "fmt" 22 "io/ioutil" 23 "log" 24 "os" 25 26 "github.com/SagerNet/gvisor/tools/nogo" 27 "github.com/SagerNet/gvisor/tools/worker" 28 ) 29 30 var ( 31 packageFile = flag.String("package", "", "package configuration file (in JSON format)") 32 stdlibFile = flag.String("stdlib", "", "stdlib configuration file (in JSON format)") 33 findingsOutput = flag.String("findings", "", "output file (or stdout, if not specified)") 34 factsOutput = flag.String("facts", "", "output file for facts (optional)") 35 ) 36 37 func loadConfig(file string, config interface{}) interface{} { 38 // Load the configuration. 39 f, err := os.Open(file) 40 if err != nil { 41 log.Fatalf("unable to open configuration %q: %v", file, err) 42 } 43 defer f.Close() 44 dec := json.NewDecoder(f) 45 dec.DisallowUnknownFields() 46 if err := dec.Decode(config); err != nil { 47 log.Fatalf("unable to decode configuration: %v", err) 48 } 49 return config 50 } 51 52 func main() { 53 worker.Work(run) 54 } 55 56 func run([]string) int { 57 var ( 58 findings []nogo.Finding 59 factData []byte 60 err error 61 ) 62 63 // Check & load the configuration. 64 if *packageFile != "" && *stdlibFile != "" { 65 fmt.Fprintf(os.Stderr, "unable to perform stdlib and package analysis; provide only one!") 66 return 1 67 } 68 69 // Run the configuration. 70 if *stdlibFile != "" { 71 // Perform stdlib analysis. 72 c := loadConfig(*stdlibFile, new(nogo.StdlibConfig)).(*nogo.StdlibConfig) 73 findings, factData, err = nogo.CheckStdlib(c, nogo.AllAnalyzers) 74 } else if *packageFile != "" { 75 // Perform standard analysis. 76 c := loadConfig(*packageFile, new(nogo.PackageConfig)).(*nogo.PackageConfig) 77 findings, factData, err = nogo.CheckPackage(c, nogo.AllAnalyzers, nil) 78 } else { 79 fmt.Fprintf(os.Stderr, "please provide at least one of package or stdlib!") 80 return 1 81 } 82 83 // Check that analysis was successful. 84 if err != nil { 85 fmt.Fprintf(os.Stderr, "error performing analysis: %v", err) 86 return 1 87 } 88 89 // Save facts. 90 if *factsOutput != "" { 91 if err := ioutil.WriteFile(*factsOutput, factData, 0644); err != nil { 92 fmt.Fprintf(os.Stderr, "error saving findings to %q: %v", *factsOutput, err) 93 return 1 94 } 95 } 96 97 // Write all findings. 98 if *findingsOutput != "" { 99 w, err := os.OpenFile(*findingsOutput, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) 100 if err != nil { 101 fmt.Fprintf(os.Stderr, "error opening output file %q: %v", *findingsOutput, err) 102 return 1 103 } 104 if err := nogo.WriteFindingsTo(w, findings, false /* json */); err != nil { 105 fmt.Fprintf(os.Stderr, "error writing findings to %q: %v", *findingsOutput, err) 106 return 1 107 } 108 } else { 109 for _, finding := range findings { 110 fmt.Fprintf(os.Stdout, "%s\n", finding.String()) 111 } 112 } 113 114 return 0 115 }