github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/utils.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/opencontainers/runtime-spec/specs-go"
    12  
    13  	"github.com/sirupsen/logrus"
    14  	"github.com/urfave/cli"
    15  )
    16  
    17  const (
    18  	exactArgs = iota
    19  	minArgs
    20  	maxArgs
    21  )
    22  
    23  func checkArgs(context *cli.Context, expected, checkType int) error {
    24  	var err error
    25  	cmdName := context.Command.Name
    26  	switch checkType {
    27  	case exactArgs:
    28  		if context.NArg() != expected {
    29  			err = fmt.Errorf("%s: %q requires exactly %d argument(s)", os.Args[0], cmdName, expected)
    30  		}
    31  	case minArgs:
    32  		if context.NArg() < expected {
    33  			err = fmt.Errorf("%s: %q requires a minimum of %d argument(s)", os.Args[0], cmdName, expected)
    34  		}
    35  	case maxArgs:
    36  		if context.NArg() > expected {
    37  			err = fmt.Errorf("%s: %q requires a maximum of %d argument(s)", os.Args[0], cmdName, expected)
    38  		}
    39  	}
    40  
    41  	if err != nil {
    42  		fmt.Printf("Incorrect Usage.\n\n")
    43  		_ = cli.ShowCommandHelp(context, cmdName)
    44  		return err
    45  	}
    46  	return nil
    47  }
    48  
    49  func logrusToStderr() bool {
    50  	l, ok := logrus.StandardLogger().Out.(*os.File)
    51  	return ok && l.Fd() == os.Stderr.Fd()
    52  }
    53  
    54  // fatal prints the error's details if it is a libcontainer specific error type
    55  // then exits the program with an exit status of 1.
    56  func fatal(err error) {
    57  	fatalWithCode(err, 1)
    58  }
    59  
    60  func fatalWithCode(err error, ret int) {
    61  	// Make sure the error is written to the logger.
    62  	logrus.Error(err)
    63  	if !logrusToStderr() {
    64  		fmt.Fprintln(os.Stderr, err)
    65  	}
    66  
    67  	os.Exit(ret)
    68  }
    69  
    70  // setupSpec performs initial setup based on the cli.Context for the container
    71  func setupSpec(context *cli.Context) (*specs.Spec, error) {
    72  	bundle := context.String("bundle")
    73  	if bundle != "" {
    74  		if err := os.Chdir(bundle); err != nil {
    75  			return nil, err
    76  		}
    77  	}
    78  	spec, err := loadSpec(specConfig)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	return spec, nil
    83  }
    84  
    85  func revisePidFile(context *cli.Context) error {
    86  	pidFile := context.String("pid-file")
    87  	if pidFile == "" {
    88  		return nil
    89  	}
    90  
    91  	// convert pid-file to an absolute path so we can write to the right
    92  	// file after chdir to bundle
    93  	pidFile, err := filepath.Abs(pidFile)
    94  	if err != nil {
    95  		return err
    96  	}
    97  	return context.Set("pid-file", pidFile)
    98  }
    99  
   100  // reviseRootDir ensures that the --root option argument,
   101  // if specified, is converted to an absolute and cleaned path,
   102  // and that this path is sane.
   103  func reviseRootDir(context *cli.Context) error {
   104  	if !context.IsSet("root") {
   105  		return nil
   106  	}
   107  	root, err := filepath.Abs(context.GlobalString("root"))
   108  	if err != nil {
   109  		return err
   110  	}
   111  	if root == "/" {
   112  		// This can happen if --root argument is
   113  		//  - "" (i.e. empty);
   114  		//  - "." (and the CWD is /);
   115  		//  - "../../.." (enough to get to /);
   116  		//  - "/" (the actual /).
   117  		return errors.New("Option --root argument should not be set to /")
   118  	}
   119  
   120  	return context.GlobalSet("root", root)
   121  }
   122  
   123  // parseBoolOrAuto returns (nil, nil) if s is empty or "auto"
   124  func parseBoolOrAuto(s string) (*bool, error) {
   125  	if s == "" || strings.ToLower(s) == "auto" {
   126  		return nil, nil
   127  	}
   128  	b, err := strconv.ParseBool(s)
   129  	return &b, err
   130  }