/*input: ocidirectory output:rktdirectrory */ func (this *oci2rkt) makeRktBundle() (err error) { //this.RktBunldePath = "/var/lib/rkt/rktbunld" stage1Path := this.RktBundlePath + "/stage1" err = os.MkdirAll(stage1Path, 0755) if err != nil { return err } //extra stage1.aci r, err := os.Open(this.Stage1Image) if err != nil { return err } defer r.Close() dr, err := aci.NewCompressedReader(r) if err != nil { return fmt.Errorf("error decompressing image: %v", err) } err = ptar.ExtractTar(dr, stage1Path, true, uid.NewBlankUidRange(), nil) if err != nil { fmt.Printf("extra stage1 image error,%v\n", err) return err } return nil }
// ExtractImage will extract the contents of the image at path to the directory // at dst. If fileMap is set, only files in it will be extracted. func ExtractImage(path, dst string, fileMap map[string]struct{}) error { dst, err := filepath.Abs(dst) if err != nil { return err } file, err := os.Open(path) if err != nil { return err } defer file.Close() dr, err := aci.NewCompressedReader(file) if err != nil { return fmt.Errorf("error decompressing image: %v", err) } defer dr.Close() uidRange := user.NewBlankUidRange() if os.Geteuid() == 0 { return rkttar.ExtractTar(dr, dst, true, uidRange, fileMap) } editor, err := rkttar.NewUidShiftingFilePermEditor(uidRange) if err != nil { return fmt.Errorf("error determining current user: %v", err) } return rkttar.ExtractTarInsecure(tar.NewReader(dr), dst, true, fileMap, editor) }
// Given a RenderedACI, it will extract, under the provided directory, the // needed files from the right source ACI. // The manifest will be extracted from the upper ACI. // No file overwriting is done as it should usually be called // providing an empty directory. func renderImage(renderedACI acirenderer.RenderedACI, dir string, ap acirenderer.ACIProvider) error { for _, ra := range renderedACI { rs, err := ap.ReadStream(ra.Key) if err != nil { return err } defer rs.Close() // Overwrite is not needed. If a file needs to be overwritten then the renderedACI builder has a bug if err := ptar.ExtractTar(tar.NewReader(rs), dir, false, ra.FileMap); err != nil { return fmt.Errorf("error extracting ACI: %v", err) } } return nil }
// Given a RenderedACI, it will extract, under the provided directory, the // needed files from the right source ACI. // The manifest will be extracted from the upper ACI. // No file overwriting is done as it should usually be called // providing an empty directory. func renderImage(renderedACI acirenderer.RenderedACI, dir string, ap acirenderer.ACIProvider, uidRange *user.UidRange) error { for _, ra := range renderedACI { rs, err := ap.ReadStream(ra.Key) if err != nil { return err } // Overwrite is not needed. If a file needs to be overwritten then the renderedACI builder has a bug if err := ptar.ExtractTar(rs, dir, false, uidRange, ra.FileMap); err != nil { rs.Close() return errwrap.Wrap(errors.New("error extracting ACI"), err) } rs.Close() } return nil }
func runImageExtract(cmd *cobra.Command, args []string) (exit int) { if len(args) != 2 { cmd.Usage() return 254 } outputDir := args[1] s, err := imagestore.NewStore(storeDir()) if err != nil { stderr.PrintE("cannot open store", err) return 254 } key, err := getStoreKeyFromAppOrHash(s, args[0]) if err != nil { stderr.Error(err) return 254 } aci, err := s.ReadStream(key) if err != nil { stderr.PrintE("error reading ACI from the store", err) return 254 } // ExtractTar needs an absolute path absOutputDir, err := filepath.Abs(outputDir) if err != nil { stderr.PrintE("error converting output to an absolute path", err) return 254 } if _, err := os.Stat(absOutputDir); err == nil { if !flagExtractOverwrite { stderr.Print("output directory exists (try --overwrite)") return 254 } // don't allow the user to delete the root filesystem by mistake if absOutputDir == "/" { stderr.Print("this would delete your root filesystem. Refusing.") return 254 } if err := os.RemoveAll(absOutputDir); err != nil { stderr.PrintE("error removing existing output dir", err) return 254 } } // if the user only asks for the rootfs we extract the image to a temporary // directory and then move/copy the rootfs to the output directory, if not // we just extract the image to the output directory extractDir := absOutputDir if flagExtractRootfsOnly { rktTmpDir, err := s.TmpDir() if err != nil { stderr.PrintE("error creating rkt temporary directory", err) return 254 } tmpDir, err := ioutil.TempDir(rktTmpDir, "rkt-image-extract-") if err != nil { stderr.PrintE("error creating temporary directory", err) return 254 } defer os.RemoveAll(tmpDir) extractDir = tmpDir } else { if err := os.MkdirAll(absOutputDir, 0755); err != nil { stderr.PrintE("error creating output directory", err) return 254 } } if err := tar.ExtractTar(aci, extractDir, false, user.NewBlankUidRange(), nil); err != nil { stderr.PrintE("error extracting ACI", err) return 254 } if flagExtractRootfsOnly { rootfsDir := filepath.Join(extractDir, "rootfs") if err := os.Rename(rootfsDir, absOutputDir); err != nil { if e, ok := err.(*os.LinkError); ok && e.Err == syscall.EXDEV { // it's on a different device, fall back to copying if err := fileutil.CopyTree(rootfsDir, absOutputDir, user.NewBlankUidRange()); err != nil { stderr.PrintE("error copying ACI rootfs", err) return 254 } } else { stderr.PrintE("error moving ACI rootfs", err) return 254 } } } return 0 }