Mirror of BoringSSL (grpc依赖)
https://boringssl.googlesource.com/boringssl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
4.3 KiB
187 lines
4.3 KiB
// import_tool is a quick tool for importing Chromium's certificate verifier |
|
// code into google3. In time it might be replaced by Copybara, but this is a |
|
// lighter-weight solution while we're quickly iterating and only going in one |
|
// direction. |
|
// |
|
// Usage: ./import_tool -spec import_spec.json\ |
|
// -source-base ~/src/chromium/src/net\ |
|
// -dest-base . |
|
package main |
|
|
|
import ( |
|
"bufio" |
|
"encoding/json" |
|
"errors" |
|
"flag" |
|
"fmt" |
|
"io/ioutil" |
|
"os" |
|
"path/filepath" |
|
"regexp" |
|
"strings" |
|
"sync" |
|
"sync/atomic" |
|
) |
|
|
|
type specification struct { |
|
Replacements []replacement `json:"replacements"` |
|
Files []string `json:"files"` |
|
} |
|
|
|
type replacement struct { |
|
Match string `json:"match"` |
|
matchRE *regexp.Regexp `json:"-"` |
|
Replace string `json:"replace"` |
|
Include string `json:"include"` |
|
Using []string `json:"using"` |
|
used uint32 |
|
} |
|
|
|
var ( |
|
specFile *string = flag.String("spec", "", "Location of spec JSON") |
|
sourceBase *string = flag.String("source-base", "", "Path of the source files") |
|
destBase *string = flag.String("dest-base", "", "Path of the destination files") |
|
) |
|
|
|
func transformFile(spec *specification, filename string) error { |
|
const newLine = "\n" |
|
|
|
sourcePath := filepath.Join(*sourceBase, filename) |
|
destPath := filename |
|
destPath = strings.TrimPrefix(destPath, "net/") |
|
destPath = strings.TrimPrefix(destPath, "cert/") |
|
destPath = strings.TrimPrefix(destPath, "der/") |
|
destPath = strings.TrimPrefix(destPath, "pki/") |
|
destPath = filepath.Join(*destBase, destPath) |
|
destDir := filepath.Dir(destPath) |
|
if err := os.MkdirAll(destDir, 0755); err != nil { |
|
return err |
|
} |
|
|
|
source, err := os.Open(sourcePath) |
|
if err != nil { |
|
return err |
|
} |
|
defer source.Close() |
|
|
|
dest, err := os.OpenFile(destPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) |
|
if err != nil { |
|
return err |
|
} |
|
defer dest.Close() |
|
|
|
var using []string |
|
var includeInsertionPoint int |
|
includes := make(map[string]struct{}) |
|
scanner := bufio.NewScanner(source) |
|
out := "" |
|
for scanner.Scan() { |
|
line := scanner.Text() |
|
|
|
if includeInsertionPoint == 0 && len(line) > 0 && |
|
!strings.HasPrefix(line, "// ") && |
|
!strings.HasPrefix(line, "#if") && |
|
!strings.HasPrefix(line, "#define ") { |
|
includeInsertionPoint = len(out) |
|
} |
|
|
|
for i, repl := range spec.Replacements { |
|
if !repl.matchRE.MatchString(line) { |
|
continue |
|
} |
|
line = repl.matchRE.ReplaceAllString(line, repl.Replace) |
|
atomic.StoreUint32(&spec.Replacements[i].used, 1) |
|
using = append(using, repl.Using...) |
|
if repl.Include != "" { |
|
includes[repl.Include] = struct{}{} |
|
} |
|
} |
|
|
|
for _, u := range using { |
|
line = strings.Replace( |
|
line, "namespace chromium_certificate_verifier {", |
|
"namespace chromium_certificate_verifier {\nusing "+u+";", 1) |
|
} |
|
|
|
out += line |
|
out += newLine |
|
} |
|
|
|
if len(includes) > 0 { |
|
if includeInsertionPoint == 0 { |
|
panic("failed to find include insertion point for " + filename) |
|
} |
|
|
|
var s string |
|
for include := range includes { |
|
s = s + "#include \"" + include + "\"\n" |
|
} |
|
|
|
out = out[:includeInsertionPoint] + s + out[includeInsertionPoint:] |
|
} |
|
|
|
dest.WriteString(out) |
|
fmt.Printf("%s\n", filename) |
|
|
|
return nil |
|
} |
|
|
|
func do() error { |
|
flag.Parse() |
|
|
|
specBytes, err := ioutil.ReadFile(*specFile) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
var spec specification |
|
if err := json.Unmarshal(specBytes, &spec); err != nil { |
|
if jsonError, ok := err.(*json.SyntaxError); ok { |
|
return fmt.Errorf("JSON parse error at offset %v: %v", jsonError.Offset, err.Error()) |
|
} |
|
return errors.New("JSON parse error: " + err.Error()) |
|
} |
|
|
|
for i, repl := range spec.Replacements { |
|
var err error |
|
spec.Replacements[i].matchRE, err = regexp.Compile(repl.Match) |
|
if err != nil { |
|
return fmt.Errorf("Failed to parse %q: %s", repl.Match, err) |
|
} |
|
} |
|
|
|
errors := make(chan error, len(spec.Files)) |
|
var wg sync.WaitGroup |
|
|
|
for _, filename := range spec.Files { |
|
wg.Add(1) |
|
|
|
go func(filename string) { |
|
if err := transformFile(&spec, filename); err != nil { |
|
errors <- err |
|
} |
|
wg.Done() |
|
}(filename) |
|
} |
|
|
|
wg.Wait() |
|
select { |
|
case err := <-errors: |
|
return err |
|
default: |
|
break |
|
} |
|
for _, repl := range spec.Replacements { |
|
if repl.used == 0 { |
|
fmt.Fprintf(os.Stderr, "replacement for \"%s\" not used\n", repl.Match) |
|
} |
|
} |
|
return nil |
|
} |
|
|
|
func main() { |
|
if err := do(); err != nil { |
|
fmt.Fprintf(os.Stderr, "%s\n", err) |
|
os.Exit(1) |
|
} |
|
}
|
|
|