github.com/google/go-safeweb@v0.0.0-20231219055052-64d8cfc90fbb/cmd/bancheck/config/config.go (about) 1 // Copyright 2020 Google LLC 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 // https://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 package config 16 17 import ( 18 "encoding/json" 19 "errors" 20 "os" 21 ) 22 23 // Config represents a configuration passed to the linter. 24 type Config struct { 25 Imports []BannedAPI `json:"imports"` 26 Functions []BannedAPI `json:"functions"` 27 } 28 29 // BannedAPI represents an identifier (e.g. import, function call) that should not be used. 30 type BannedAPI struct { 31 Name string `json:"name"` // fully qualified identifier name 32 Msg string `json:"msg"` // additional information e.g. rationale for banning 33 Exemptions []Exemption `json:"exemptions"` 34 } 35 36 // Exemption represents a location that should be exempted from checking for banned APIs. 37 type Exemption struct { 38 Justification string `json:"justification"` 39 AllowedPkg string `json:"allowedPkg"` // Uses Go RegExp https://golang.org/pkg/regexp/syntax 40 } 41 42 // ReadConfigs reads banned APIs from all files. 43 func ReadConfigs(files []string) (*Config, error) { 44 var imports []BannedAPI 45 var fns []BannedAPI 46 47 for _, file := range files { 48 config, err := readCfg(file) 49 if err != nil { 50 return nil, err 51 } 52 53 imports = append(imports, config.Imports...) 54 fns = append(fns, config.Functions...) 55 } 56 57 return &Config{Imports: imports, Functions: fns}, nil 58 } 59 60 func readCfg(filename string) (*Config, error) { 61 f, err := openFile(filename) 62 if err != nil { 63 return nil, err 64 } 65 defer f.Close() 66 67 return decodeCfg(f) 68 } 69 70 func openFile(filename string) (*os.File, error) { 71 info, err := os.Stat(filename) 72 if os.IsNotExist(err) { 73 return nil, errors.New("file does not exist") 74 } 75 if info.IsDir() { 76 return nil, errors.New("file is a directory") 77 } 78 79 return os.Open(filename) 80 } 81 82 func decodeCfg(f *os.File) (*Config, error) { 83 var cfg Config 84 err := json.NewDecoder(f).Decode(&cfg) 85 if err != nil { 86 return nil, err 87 } 88 89 return &cfg, nil 90 }