func runExport(cmd *cobra.Command, args []string) (exit int) { if len(args) != 2 { cmd.Usage() return 1 } outACI := args[1] ext := filepath.Ext(outACI) if ext != schema.ACIExtension { stderr.Printf("extension must be %s (given %s)", schema.ACIExtension, outACI) return 1 } p, err := getPodFromUUIDString(args[0]) if err != nil { stderr.PrintE("problem retrieving pod", err) return 1 } defer p.Close() if !p.isExited { stderr.Print("pod is not exited. Only exited pods can be exported") return 1 } app, err := getApp(p) if err != nil { stderr.PrintE("unable to find app", err) return 1 } root := common.AppPath(p.path(), app.Name) manifestPath := filepath.Join(common.AppInfoPath(p.path(), app.Name), aci.ManifestFile) if p.usesOverlay() { tmpDir := filepath.Join(getDataDir(), "tmp") if err := os.MkdirAll(tmpDir, common.DefaultRegularDirPerm); err != nil { stderr.PrintE("unable to create temp directory", err) return 1 } podDir, err := ioutil.TempDir(tmpDir, fmt.Sprintf("rkt-export-%s", p.uuid)) if err != nil { stderr.PrintE("unable to create export temp directory", err) return 1 } defer func() { if err := os.RemoveAll(podDir); err != nil { stderr.PrintE("problem removing temp directory", err) exit = 1 } }() mntDir := filepath.Join(podDir, "rootfs") if err := os.Mkdir(mntDir, common.DefaultRegularDirPerm); err != nil { stderr.PrintE("unable to create rootfs directory inside temp directory", err) return 1 } if err := mountOverlay(p, app, mntDir); err != nil { stderr.PrintE(fmt.Sprintf("couldn't mount directory at %s", mntDir), err) return 1 } defer func() { if err := syscall.Unmount(mntDir, 0); err != nil { stderr.PrintE(fmt.Sprintf("error unmounting directory %s", mntDir), err) exit = 1 } }() root = podDir } else { hasMPs, err := appHasMountpoints(p.path(), app.Name) if err != nil { stderr.PrintE("error parsing mountpoints", err) return 1 } if hasMPs { stderr.Printf("pod has remaining mountpoints. Only pods using overlayfs or with no mountpoints can be exported") return 1 } } // Check for user namespace (--private-user), if in use get uidRange var uidRange *user.UidRange privUserFile := filepath.Join(p.path(), common.PrivateUsersPreparedFilename) privUserContent, err := ioutil.ReadFile(privUserFile) if err == nil { uidRange = user.NewBlankUidRange() // The file was found, save uid & gid shift and count if err := uidRange.Deserialize(privUserContent); err != nil { stderr.PrintE(fmt.Sprintf("problem deserializing the content of %s", common.PrivateUsersPreparedFilename), err) return 1 } } if err = buildAci(root, manifestPath, outACI, uidRange); err != nil { stderr.PrintE("error building aci", err) return 1 } return 0 }