package main import ( js "encoding/json" "fmt" "os" "github.com/containers/libpod/cmd/podman/cliconfig" of "github.com/containers/libpod/cmd/podman/formats" "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/pkg/rootless" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var ( mountCommand cliconfig.MountValues mountDescription = ` podman mount Lists all mounted containers mount points podman mount CONTAINER-NAME-OR-ID Mounts the specified container and outputs the mountpoint ` _mountCommand = &cobra.Command{ Use: "mount", Short: "Mount a working container's root filesystem", Long: mountDescription, RunE: func(cmd *cobra.Command, args []string) error { mountCommand.InputArgs = args mountCommand.GlobalFlags = MainGlobalOpts return mountCmd(&mountCommand) }, Args: func(cmd *cobra.Command, args []string) error { return checkAllAndLatest(cmd, args, true) }, } ) func init() { mountCommand.Command = _mountCommand mountCommand.SetUsageTemplate(UsageTemplate()) flags := mountCommand.Flags() flags.BoolVarP(&mountCommand.All, "all", "a", false, "Mount all containers") flags.StringVar(&mountCommand.Format, "format", "", "Change the output format to Go template") flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output") } // jsonMountPoint stores info about each container type jsonMountPoint struct { ID string `json:"id"` Names []string `json:"names"` MountPoint string `json:"mountpoint"` } func mountCmd(c *cliconfig.MountValues) error { if os.Geteuid() != 0 { rootless.SetSkipStorageSetup(true) } runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) if os.Geteuid() != 0 { if driver := runtime.GetConfig().StorageConfig.GraphDriverName; driver != "vfs" { // Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part // of the mount command. return fmt.Errorf("cannot mount using driver %s in rootless mode", driver) } became, ret, err := rootless.BecomeRootInUserNS() if err != nil { return err } if became { os.Exit(ret) } } if c.All && c.Latest { return errors.Errorf("--all and --latest cannot be used together") } mountContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all") if err != nil { if len(mountContainers) == 0 { return err } fmt.Println(err.Error()) } formats := map[string]bool{ "": true, of.JSONString: true, } json := c.Format == of.JSONString if !formats[c.Format] { return errors.Errorf("%q is not a supported format", c.Format) } var lastError error if len(mountContainers) > 0 { for _, ctr := range mountContainers { if json { if lastError != nil { logrus.Error(lastError) } lastError = errors.Wrapf(err, "json option cannot be used with a container id") continue } mountPoint, err := ctr.Mount() if err != nil { if lastError != nil { logrus.Error(lastError) } lastError = errors.Wrapf(err, "error mounting container %q", ctr.ID()) continue } fmt.Printf("%s\n", mountPoint) } return lastError } else { jsonMountPoints := []jsonMountPoint{} containers, err2 := runtime.GetContainers() if err2 != nil { return errors.Wrapf(err2, "error reading list of all containers") } for _, container := range containers { mounted, mountPoint, err := container.Mounted() if err != nil { return errors.Wrapf(err, "error getting mountpoint for %q", container.ID()) } if !mounted { continue } if json { jsonMountPoints = append(jsonMountPoints, jsonMountPoint{ID: container.ID(), Names: []string{container.Name()}, MountPoint: mountPoint}) continue } if c.NoTrunc { fmt.Printf("%-64s %s\n", container.ID(), mountPoint) } else { fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint) } } if json { data, err := js.MarshalIndent(jsonMountPoints, "", " ") if err != nil { return err } fmt.Printf("%s\n", data) } } return nil }