github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/cmd/podman/mount.go (about)

     1  package main
     2  
     3  import (
     4  	js "encoding/json"
     5  	"fmt"
     6  	"os"
     7  
     8  	of "github.com/containers/buildah/pkg/formats"
     9  	"github.com/containers/libpod/cmd/podman/cliconfig"
    10  	"github.com/containers/libpod/cmd/podman/libpodruntime"
    11  	"github.com/containers/libpod/pkg/rootless"
    12  	"github.com/pkg/errors"
    13  	"github.com/sirupsen/logrus"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  var (
    18  	mountCommand cliconfig.MountValues
    19  
    20  	mountDescription = `podman mount
    21      Lists all mounted containers mount points if no container is specified
    22  
    23    podman mount CONTAINER-NAME-OR-ID
    24      Mounts the specified container and outputs the mountpoint
    25  `
    26  
    27  	_mountCommand = &cobra.Command{
    28  		Use:   "mount [flags] [CONTAINER]",
    29  		Short: "Mount a working container's root filesystem",
    30  		Long:  mountDescription,
    31  		RunE: func(cmd *cobra.Command, args []string) error {
    32  			mountCommand.InputArgs = args
    33  			mountCommand.GlobalFlags = MainGlobalOpts
    34  			mountCommand.Remote = remoteclient
    35  			return mountCmd(&mountCommand)
    36  		},
    37  		Args: func(cmd *cobra.Command, args []string) error {
    38  			return checkAllLatestAndCIDFile(cmd, args, true, false)
    39  		},
    40  	}
    41  )
    42  
    43  func init() {
    44  	mountCommand.Command = _mountCommand
    45  	mountCommand.SetHelpTemplate(HelpTemplate())
    46  	mountCommand.SetUsageTemplate(UsageTemplate())
    47  	flags := mountCommand.Flags()
    48  	flags.BoolVarP(&mountCommand.All, "all", "a", false, "Mount all containers")
    49  	flags.StringVar(&mountCommand.Format, "format", "", "Change the output format to Go template")
    50  	flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
    51  	flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output")
    52  
    53  	markFlagHiddenForRemoteClient("latest", flags)
    54  }
    55  
    56  // jsonMountPoint stores info about each container
    57  type jsonMountPoint struct {
    58  	ID         string   `json:"id"`
    59  	Names      []string `json:"names"`
    60  	MountPoint string   `json:"mountpoint"`
    61  }
    62  
    63  func mountCmd(c *cliconfig.MountValues) error {
    64  	runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand)
    65  	if err != nil {
    66  		return errors.Wrapf(err, "could not get runtime")
    67  	}
    68  	defer runtime.DeferredShutdown(false)
    69  
    70  	if os.Geteuid() != 0 {
    71  		if driver := runtime.StorageConfig().GraphDriverName; driver != "vfs" {
    72  			// Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part
    73  			// of the mount command.
    74  			return fmt.Errorf("cannot mount using driver %s in rootless mode", driver)
    75  		}
    76  
    77  		became, ret, err := rootless.BecomeRootInUserNS("")
    78  		if err != nil {
    79  			return err
    80  		}
    81  		if became {
    82  			os.Exit(ret)
    83  		}
    84  	}
    85  
    86  	if c.All && c.Latest {
    87  		return errors.Errorf("--all and --latest cannot be used together")
    88  	}
    89  
    90  	mountContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
    91  	if err != nil {
    92  		if len(mountContainers) == 0 {
    93  			return err
    94  		}
    95  		fmt.Println(err.Error())
    96  	}
    97  
    98  	formats := map[string]bool{
    99  		"":            true,
   100  		of.JSONString: true,
   101  	}
   102  
   103  	json := c.Format == of.JSONString
   104  	if !formats[c.Format] {
   105  		return errors.Errorf("%q is not a supported format", c.Format)
   106  	}
   107  
   108  	var lastError error
   109  	if len(mountContainers) > 0 {
   110  		for _, ctr := range mountContainers {
   111  			if json {
   112  				if lastError != nil {
   113  					logrus.Error(lastError)
   114  				}
   115  				lastError = errors.Wrapf(err, "json option cannot be used with a container id")
   116  				continue
   117  			}
   118  			mountPoint, err := ctr.Mount()
   119  			if err != nil {
   120  				if lastError != nil {
   121  					logrus.Error(lastError)
   122  				}
   123  				lastError = errors.Wrapf(err, "error mounting container %q", ctr.ID())
   124  				continue
   125  			}
   126  			fmt.Printf("%s\n", mountPoint)
   127  		}
   128  		return lastError
   129  	} else {
   130  		jsonMountPoints := []jsonMountPoint{}
   131  		containers, err2 := runtime.GetContainers()
   132  		if err2 != nil {
   133  			return errors.Wrapf(err2, "error reading list of all containers")
   134  		}
   135  		for _, container := range containers {
   136  			mounted, mountPoint, err := container.Mounted()
   137  			if err != nil {
   138  				return errors.Wrapf(err, "error getting mountpoint for %q", container.ID())
   139  			}
   140  
   141  			if !mounted {
   142  				continue
   143  			}
   144  
   145  			if json {
   146  				jsonMountPoints = append(jsonMountPoints, jsonMountPoint{ID: container.ID(), Names: []string{container.Name()}, MountPoint: mountPoint})
   147  				continue
   148  			}
   149  
   150  			if c.NoTrunc {
   151  				fmt.Printf("%-64s %s\n", container.ID(), mountPoint)
   152  			} else {
   153  				fmt.Printf("%-12.12s %s\n", container.ID(), mountPoint)
   154  			}
   155  		}
   156  		if json {
   157  			data, err := js.MarshalIndent(jsonMountPoints, "", "    ")
   158  			if err != nil {
   159  				return err
   160  			}
   161  			fmt.Printf("%s\n", data)
   162  		}
   163  	}
   164  	return nil
   165  }