
介绍完mainCommands,下面看看internalCommands,它只有一个命令:漏洞检测
type vulncheck struct {
app *Application
}func (v *vulncheck) Run(ctx context.Context, args ...string) error {
if err := scan.Main(ctx, args...); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
return nil
}它调用了scan.Main方法internal/vulncheck/scan/command.go
func Main(ctx context.Context, args ...string) error {
// wrapping govulncheck.
cmd := scan.Command(ctx, args...)
if err := cmd.Start(); err != nil {
return err
}
return cmd.Wait()
}func Command(ctx context.Context, arg ...string) *Cmd {
return &Cmd{
ctx: ctx,
args: arg,
}
}type Cmd struct {
// Stdin specifies the standard input. If provided, it is expected to be
// the output of govulncheck -json.
Stdin io.Reader
// Stdout specifies the standard output. If nil, Run connects os.Stdout.
Stdout io.Writer
// Stderr specifies the standard error. If nil, Run connects os.Stderr.
Stderr io.Writer
// Env is the environment to use.
// If Env is nil, the current environment is used.
// As in os/exec's Cmd, only the last value in the slice for
// each environment key is used. To specify the setting of only
// a few variables, append to the current environment, as in:
//
// opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386")
//
Env []string
ctx context.Context
args []string
done chan struct{}
err error
}接着开始扫描,获取环境变量,然后启动一个goroutine调用scan方法来扫描
func (c *Cmd) Start() error {
if c.done != nil {
return errors.New("vuln: already started")
}
if c.Stdin == nil {
c.Stdin = os.Stdin
}
if c.Stdout == nil {
c.Stdout = os.Stdout
}
if c.Stderr == nil {
c.Stderr = os.Stderr
}
if c.Env == nil {
c.Env = os.Environ()
}
c.done = make(chan struct{})
go func() {
defer close(c.done)
c.err = c.scan()
}()
return nil
}func (c *Cmd) scan() error {
if err := c.ctx.Err(); err != nil {
return err
}
return scan.RunGovulncheck(c.ctx, c.Env, c.Stdin, c.Stdout, c.Stderr, c.args)
}调用的是包golang.org/x/vuln/internal/scan/run.go
func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Writer, stderr io.Writer, args []string) error {
cfg := &config{env: env}
if err := parseFlags(cfg, stderr, args); err != nil {
return err
}
client, err := client.NewClient(cfg.db, nil)
if err != nil {
return fmt.Errorf("creating client: %w", err)
}
prepareConfig(ctx, cfg, client)
var handler govulncheck.Handler
switch cfg.format {
case formatJSON:
handler = govulncheck.NewJSONHandler(stdout)
case formatSarif:
handler = sarif.NewHandler(stdout)
case formatOpenVEX:
handler = openvex.NewHandler(stdout)
default:
th := NewTextHandler(stdout)
cfg.show.Update(th)
handler = th
}
if err := handler.Config(&cfg.Config); err != nil {
return err
}
incTelemetryFlagCounters(cfg)
switch cfg.ScanMode {
case govulncheck.ScanModeSource:
dir := filepath.FromSlash(cfg.dir)
err = runSource(ctx, handler, cfg, client, dir)
case govulncheck.ScanModeBinary:
err = runBinary(ctx, handler, cfg, client)
case govulncheck.ScanModeExtract:
return runExtract(cfg, stdout)
case govulncheck.ScanModeQuery:
err = runQuery(ctx, handler, cfg, client)
case govulncheck.ScanModeConvert:
err = govulncheck.HandleJSON(r, handler)
}
if err != nil {
return err
}
return Flush(handler)
}会根据不同的格式进行扫描,最后通过等待chan的返回结果来等待goroutine的运行结束
func (c *Cmd) Wait() error {
if c.done == nil {
return errors.New("vuln: start must be called before wait")
}
<-c.done
return c.err
}本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!