/* handle - Pointer to a Tar file being built rootPath - Path to read the contents from relPath - Path to write these files into */ func writeFile(handle *tar.Writer, rootPath, relPath string) error { var file *os.File var stat os.FileInfo var buffer []byte var err error if file, err = os.OpenFile(rootPath, os.O_RDONLY, os.ModePerm); err != nil { return err } if stat, err = file.Stat(); err != nil { return err } file.Close() header := &tar.Header{ Name: relPath, Size: stat.Size(), } if err := handle.WriteHeader(header); err != nil { return err } if buffer, err = ioutil.ReadFile(rootPath); err != nil { return err } if _, err := handle.Write(buffer); err != nil { return err } return nil }
// WritePackage satisfies the platform interface for generating a docker package // that encapsulates the environment for a CAR based chaincode func (carPlatform *Platform) WritePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error { path, err := download(spec.ChaincodeID.Path) if err != nil { return err } var buf []string //let the executable's name be chaincode ID's name buf = append(buf, cutil.GetDockerfileFromConfig("chaincode.car.Dockerfile")) buf = append(buf, "COPY package.car /tmp/package.car") // invoking directly for maximum JRE compatiblity buf = append(buf, fmt.Sprintf("RUN java -jar /usr/local/bin/chaintool buildcar /tmp/package.car -o $GOPATH/bin/%s && rm /tmp/package.car", spec.ChaincodeID.Name)) dockerFileContents := strings.Join(buf, "\n") dockerFileSize := int64(len([]byte(dockerFileContents))) //Make headers identical by using zero time var zeroTime time.Time tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) tw.Write([]byte(dockerFileContents)) err = cutil.WriteFileToPackage(path, "package.car", tw) if err != nil { return err } return nil }
// synthesizeMain generates a new main func and writes it to the tarball. func synthesizeMain(tw *tar.Writer, appFiles []string) error { appMap := make(map[string]bool) for _, f := range appFiles { appMap[f] = true } var f string for i := 0; i < 100; i++ { f = fmt.Sprintf("app_main%d.go", i) if !appMap[filepath.Join(*rootDir, f)] { break } } if appMap[filepath.Join(*rootDir, f)] { return fmt.Errorf("unable to find unique name for %v", f) } hdr := &tar.Header{ Name: f, Mode: 0644, Size: int64(len(newMain)), } if err := tw.WriteHeader(hdr); err != nil { return fmt.Errorf("unable to write header for %v: %v", f, err) } if _, err := tw.Write([]byte(newMain)); err != nil { return fmt.Errorf("unable to write %v to tar file: %v", f, err) } return nil }
func (c *PackCmd) packSource(writer *tar.Writer, p *utils.Paths) error { base := path.Join(p.SrcDir, p.PkgName) files, err := ioutil.ReadDir(base) if err != nil { return err } for _, file := range files { if !file.IsDir() && strings.HasSuffix(file.Name(), ".go") { fpath := path.Join(base, file.Name()) src, err := ioutil.ReadFile(fpath) if err != nil { return err } src, err = source.Prune(src) header := tar.Header{ Name: fmt.Sprintf("src/%s/%s", p.PkgName, file.Name()), Mode: 0444, Size: int64(len(src)), } writer.WriteHeader(&header) writer.Write(src) } } return nil }
//tw is expected to have the chaincode in it from GenerateHashcode. This method //will just package rest of the bytes func writeChaincodePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error { var urlLocation string if strings.HasPrefix(spec.ChaincodeID.Path, "http://") { urlLocation = spec.ChaincodeID.Path[7:] } else if strings.HasPrefix(spec.ChaincodeID.Path, "https://") { urlLocation = spec.ChaincodeID.Path[8:] } else { urlLocation = spec.ChaincodeID.Path } newRunLine := fmt.Sprintf("RUN go install %s && cp src/github.com/openblockchain/obc-peer/openchain.yaml $GOPATH/bin", urlLocation) dockerFileContents := fmt.Sprintf("%s\n%s", viper.GetString("chaincode.golang.Dockerfile"), newRunLine) dockerFileSize := int64(len([]byte(dockerFileContents))) //Make headers identical by using zero time var zeroTime time.Time tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) tw.Write([]byte(dockerFileContents)) err := writeGopathSrc(tw, urlLocation) if err != nil { return fmt.Errorf("Error writing Chaincode package contents: %s", err) } return nil }
// Write a single file to TarGz func TarGzWrite(item ArchiveItem, tw *tar.Writer, fi os.FileInfo) (err error) { if item.FileSystemPath != "" { fr, err := os.Open(item.FileSystemPath) if err == nil { defer fr.Close() h := new(tar.Header) h.Name = item.ArchivePath h.Size = fi.Size() h.Mode = int64(fi.Mode()) h.ModTime = fi.ModTime() err = tw.WriteHeader(h) if err == nil { _, err = io.Copy(tw, fr) } } } else { h := new(tar.Header) //backslash-only paths h.Name = strings.Replace(item.ArchivePath, "\\", "/", -1) h.Size = int64(len(item.Data)) h.Mode = int64(0644) //? is this ok? h.ModTime = time.Now() err = tw.WriteHeader(h) if err == nil { _, err = tw.Write(item.Data) } } return err }
// WritePackage satisfies the platform interface for generating a docker package // that encapsulates the environment for a CAR based chaincode func (carPlatform *Platform) WritePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error { path, err := download(spec.ChaincodeID.Path) if err != nil { return err } spec.ChaincodeID.Name, err = generateHashcode(spec, path) if err != nil { return fmt.Errorf("Error generating hashcode: %s", err) } var buf []string //let the executable's name be chaincode ID's name buf = append(buf, viper.GetString("chaincode.car.Dockerfile")) buf = append(buf, "COPY package.car /tmp/package.car") buf = append(buf, fmt.Sprintf("RUN chaintool buildcar /tmp/package.car -o $GOPATH/bin/%s && rm /tmp/package.car", spec.ChaincodeID.Name)) dockerFileContents := strings.Join(buf, "\n") dockerFileSize := int64(len([]byte(dockerFileContents))) //Make headers identical by using zero time var zeroTime time.Time tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) tw.Write([]byte(dockerFileContents)) err = cutil.WriteFileToPackage(path, "package.car", tw) if err != nil { return err } return nil }
func (c *PackCmd) packLib(writer *tar.Writer, dir string) error { // these should be of the form $GOOS_$GOARCH name := fmt.Sprintf("pkg/%s/%s%s", dir, c.Paths.PkgName, GO_LIB_EXT) fname := os.ExpandEnv("$GOPATH/") + name c.log.Logv("Looking for %s", fname) file, err := os.Open(fname) if err != nil { return err } defer file.Close() body, err := ioutil.ReadAll(file) if err != nil { panic(err) } header := tar.Header{ Name: name, Mode: 0444, Size: int64(len(body)), } writer.WriteHeader(&header) writer.Write(body) return nil }
func addFileToArchive(name string, content []byte, modTime time.Time, w *tar.Writer) error { e := w.WriteHeader(&tar.Header{Name: name, Size: int64(len(content)), ModTime: modTime, Mode: 0644}) if e != nil { return e } _, e = w.Write(content) return e }
func MakeTarball(tarname string, fnames []string) error { log.Printf("tarring %d entrires to %s ...", len(fnames), tarname) tarfile, err := os.Create(tarname) if err != nil { return err } defer tarfile.Close() var tarwriter *tar.Writer if strings.HasSuffix(tarname, ".gz") { zipper := gzip.NewWriter(tarfile) defer zipper.Close() tarwriter = tar.NewWriter(zipper) /* } else if strings.HasSuffix(tarname, ".xz") { p := xz.WriterDefaults p.DictCap = 1 << 24 zipper, err := xz.NewWriterParams(tarfile, &p) //xz.NewWriter(tarfile) if err != nil { return err } defer zipper.Close() tarwriter = tar.NewWriter(zipper) */ } else { tarwriter = tar.NewWriter(tarfile) } defer tarwriter.Close() for _, fname := range fnames { realm, ts, good := util.Parse_FName(fname) if !good { log.Printf("warning: skip ill-named file '%s'", fname) continue // skip } data, err := util.Load(fname) if err != nil { return err } hdr := new(tar.Header) hdr.Name = util.Make_FName(realm, ts, false) hdr.Size = int64(len(data)) hdr.ModTime = ts hdr.Mode = 0644 err = tarwriter.WriteHeader(hdr) if err != nil { return err } log.Printf("tar %d bytes for file %s", hdr.Size, hdr.Name) _, err = tarwriter.Write(data) if err != nil { return err } } log.Printf("%s tarred without errors", tarname) return nil }
//tw is expected to have the chaincode in it from GenerateHashcode. //This method will just package the dockerfile func writeChaincodePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error { var urlLocation string var err error if strings.HasPrefix(spec.ChaincodeID.Path, "http://") || strings.HasPrefix(spec.ChaincodeID.Path, "https://") { urlLocation, err = getCodeFromHTTP(spec.ChaincodeID.Path) defer func() { os.RemoveAll(urlLocation) }() if err != nil { return err } } else { urlLocation = spec.ChaincodeID.Path } if urlLocation == "" { return fmt.Errorf("empty url location") } if strings.LastIndex(urlLocation, "/") == len(urlLocation)-1 { urlLocation = urlLocation[:len(urlLocation)-1] } buildCmd, err := getBuildCmd(urlLocation) if err != nil { return err } var dockerFileContents string var buf []string if viper.GetBool("security.enabled") { //todo } else { buf = append(buf, cutil.GetDockerfileFromConfig("chaincode.java.Dockerfile")) buf = append(buf, "COPY src /root/chaincode") buf = append(buf, "RUN cd /root/chaincode && "+buildCmd) buf = append(buf, "RUN cp /root/chaincode/build/chaincode.jar /root") buf = append(buf, "RUN cp /root/chaincode/build/libs/* /root/libs") } dockerFileContents = strings.Join(buf, "\n") dockerFileSize := int64(len([]byte(dockerFileContents))) //Make headers identical by using zero time var zeroTime time.Time tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) tw.Write([]byte(dockerFileContents)) err = cutil.WriteJavaProjectToPackage(tw, urlLocation) if err != nil { return fmt.Errorf("Error writing Chaincode package contents: %s", err) } return nil }
// TarAddBytes adds a file by bytes with a given path func TarAddBytes(tw *tar.Writer, bytes []byte, destName string, mode int64) error { err := tw.WriteHeader(TarHeader(destName, int64(len(bytes)), mode)) if err != nil { return err } _, err = tw.Write(bytes) if err != nil { return err } return nil }
func outputTarFiles(out *tar.Writer, files []*TarFile) error { for _, file := range files { if err := out.WriteHeader(file.Header); err != nil { return err } if _, err := out.Write(file.Data); err != nil { return err } } return nil }
//tw is expected to have the chaincode in it from GenerateHashcode. This method //will just package rest of the bytes func writeChaincodePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error { var urlLocation string if strings.HasPrefix(spec.ChaincodeID.Path, "http://") { urlLocation = spec.ChaincodeID.Path[7:] } else if strings.HasPrefix(spec.ChaincodeID.Path, "https://") { urlLocation = spec.ChaincodeID.Path[8:] } else { urlLocation = spec.ChaincodeID.Path } if urlLocation == "" { return fmt.Errorf("empty url location") } if strings.LastIndex(urlLocation, "/") == len(urlLocation)-1 { urlLocation = urlLocation[:len(urlLocation)-1] } toks := strings.Split(urlLocation, "/") if toks == nil || len(toks) == 0 { return fmt.Errorf("cannot get path components from %s", urlLocation) } chaincodeGoName := toks[len(toks)-1] if chaincodeGoName == "" { return fmt.Errorf("could not get chaincode name from path %s", urlLocation) } //let the executable's name be chaincode ID's name newRunLine := fmt.Sprintf("RUN go install %s && cp src/github.com/hyperledger/fabric/peer/core.yaml $GOPATH/bin && mv $GOPATH/bin/%s $GOPATH/bin/%s", urlLocation, chaincodeGoName, spec.ChaincodeID.Name) //NOTE-this could have been abstracted away so we could use it for all platforms in a common manner //However, it would still be docker specific. Hence any such abstraction has to be done in a manner that //is not just language dependent but also container depenedent. So lets make this change per platform for now //in the interest of avoiding over-engineering without proper abstraction if viper.GetBool("peer.tls.enabled") { newRunLine = fmt.Sprintf("%s\nCOPY src/certs/cert.pem %s", newRunLine, viper.GetString("peer.tls.cert.file")) } dockerFileContents := fmt.Sprintf("%s\n%s", viper.GetString("chaincode.golang.Dockerfile"), newRunLine) dockerFileSize := int64(len([]byte(dockerFileContents))) //Make headers identical by using zero time var zeroTime time.Time tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) tw.Write([]byte(dockerFileContents)) err := cutil.WriteGopathSrc(tw, urlLocation) if err != nil { return fmt.Errorf("Error writing Chaincode package contents: %s", err) } return nil }
func (vm *VM) writePeerPackage(tw *tar.Writer) error { startTime := time.Now() dockerFileContents := viper.GetString("peer.Dockerfile") dockerFileSize := int64(len([]byte(dockerFileContents))) tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: startTime, AccessTime: startTime, ChangeTime: startTime}) tw.Write([]byte(dockerFileContents)) err := cutil.WriteGopathSrc(tw, "") if err != nil { return fmt.Errorf("Error writing Peer package contents: %s", err) } return nil }
func writeBytesToTar(fname string, b []byte, tw *tar.Writer) error { err := tw.WriteHeader(&tar.Header{ Name: fname, Size: int64(len(b)), Mode: 0777, }) _, err = tw.Write(b) if err != nil { return err } return nil }
func writeTarEntry(tw *tar.Writer, name string, data []byte) error { h := new(tar.Header) h.Name = name h.Uid = 1000 h.Gid = 1000 h.Mode = 0755 h.Size = int64(len(data)) if err := tw.WriteHeader(h); err != nil { return err } if _, err := tw.Write(data); err != nil { return err } return nil }
// writeToTar writes a single file to a tar archive. func writeToTar(out *tar.Writer, name string, body []byte) error { // TODO: Do we need to create dummy parent directory names if none exist? h := &tar.Header{ Name: name, Mode: 0755, Size: int64(len(body)), } if err := out.WriteHeader(h); err != nil { return err } if _, err := out.Write(body); err != nil { return err } return nil }
func (vm *VM) writeObccaPackage(tw *tar.Writer) error { startTime := time.Now() dockerFileContents := viper.GetString("peer.Dockerfile") dockerFileContents = dockerFileContents + "WORKDIR ../membersrvc\nRUN go install && cp membersrvc.yaml $GOPATH/bin\n" dockerFileSize := int64(len([]byte(dockerFileContents))) tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: startTime, AccessTime: startTime, ChangeTime: startTime}) tw.Write([]byte(dockerFileContents)) err := cutil.WriteGopathSrc(tw, "") if err != nil { return fmt.Errorf("Error writing membersrvc package contents: %s", err) } return nil }
func writeManifest(tw *tar.Writer, manifest map[string]interface{}) error { buf, err := json.Marshal(manifest) if err != nil { return fmt.Errorf("cannot serialize manifest: %v", err) } header := tar.Header{} header.Name = "manifest" header.Mode = 0644 header.Size = int64(len(buf)) header.Typeflag = tar.TypeReg tw.WriteHeader(&header) if _, err := tw.Write(buf); err != nil { return fmt.Errorf("cannot write manifest: %v", err) } return nil }
func (d *Docker) addFileToTar(tr *tar.Writer, file string, content []byte) error { t := time.Now() tr.WriteHeader(&tar.Header{ Name: file, Size: int64(len(content)), ModTime: t, AccessTime: t, ChangeTime: t, }) if _, err := tr.Write(content); err != nil { return err } return nil }
func addRegularFile(tw *tar.Writer, fd *fileDesc) error { contentBytes := []byte(fd.content) hdr := &tar.Header{ Name: fd.name, Mode: int64(fd.mode), Size: int64(len(contentBytes)), Typeflag: tar.TypeReg, AccessTime: time.Now(), ModTime: fd.modifiedDate, ChangeTime: fd.modifiedDate, } if err := tw.WriteHeader(hdr); err != nil { return err } _, err := tw.Write(contentBytes) return err }
func writeTarData(tw *tar.Writer, f *os.File) error { log.Tracef("Writing %s to tar archive", f.Name()) b := make([]byte, 1024) for { read, err := f.Read(b) if _, werr := tw.Write(b[0:read]); werr != nil { return err } if err != nil { if err == io.EOF { return nil } return err } } return nil }
// WriteToTarStream writes a byte array of data into a tar stream func WriteToTarStream(stream *tar.Writer, data []byte, header tar.Header) error { if header.Mode == 0 { header.Mode = 0644 } if header.Size == 0 { header.Size = int64(len(data)) } if header.Typeflag == 0 { header.Typeflag = tar.TypeReg } if err := stream.WriteHeader(&header); err != nil { return err } if _, err := stream.Write(data); err != nil { return err } return nil }
func AddStringToTar(tw *tar.Writer, name, file string) error { hdr := &tar.Header{ Name: name, Size: int64(len(file)), Mode: 0666, Uid: syscall.Getuid(), Gid: syscall.Getgid(), } if err := tw.WriteHeader(hdr); err != nil { return err } if _, err := tw.Write([]byte(file)); err != nil { return err } return nil }
//tw is expected to have the chaincode in it from GenerateHashcode. This method //will just package rest of the bytes func writeChaincodePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error { var urlLocation string if strings.HasPrefix(spec.ChaincodeID.Path, "http://") { urlLocation = spec.ChaincodeID.Path[7:] } else if strings.HasPrefix(spec.ChaincodeID.Path, "https://") { urlLocation = spec.ChaincodeID.Path[8:] } else { urlLocation = spec.ChaincodeID.Path } if urlLocation == "" { return fmt.Errorf("empty url location") } if strings.LastIndex(urlLocation, "/") == len(urlLocation)-1 { urlLocation = urlLocation[:len(urlLocation)-1] } toks := strings.Split(urlLocation, "/") if toks == nil || len(toks) == 0 { return fmt.Errorf("cannot get path components from %s", urlLocation) } chaincodeGoName := toks[len(toks)-1] if chaincodeGoName == "" { return fmt.Errorf("could not get chaincode name from path %s", urlLocation) } //let the executable's name be chaincode ID's name newRunLine := fmt.Sprintf("RUN go install %s && cp src/github.com/hyperledger/fabric/peer/core.yaml $GOPATH/bin && mv $GOPATH/bin/%s $GOPATH/bin/%s", urlLocation, chaincodeGoName, spec.ChaincodeID.Name) dockerFileContents := fmt.Sprintf("%s\n%s", viper.GetString("chaincode.golang.Dockerfile"), newRunLine) dockerFileSize := int64(len([]byte(dockerFileContents))) //Make headers identical by using zero time var zeroTime time.Time tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) tw.Write([]byte(dockerFileContents)) err := cutil.WriteGopathSrc(tw, urlLocation) if err != nil { return fmt.Errorf("Error writing Chaincode package contents: %s", err) } return nil }
//tw is expected to have the chaincode in it from GenerateHashcode. //This method will just package the dockerfile func writeChaincodePackage(spec *pb.ChaincodeSpec, tw *tar.Writer) error { var urlLocation string if strings.HasPrefix(spec.ChaincodeID.Path, "http://") { urlLocation = spec.ChaincodeID.Path[7:] } else if strings.HasPrefix(spec.ChaincodeID.Path, "https://") { urlLocation = spec.ChaincodeID.Path[8:] } else { urlLocation = spec.ChaincodeID.Path // if !strings.HasPrefix(urlLocation, "/") { // wd := "" // wd, _ = os.Getwd() // urlLocation = wd + "/" + urlLocation // } } if urlLocation == "" { return fmt.Errorf("empty url location") } if strings.LastIndex(urlLocation, "/") == len(urlLocation)-1 { urlLocation = urlLocation[:len(urlLocation)-1] } urlLocation = urlLocation[strings.LastIndex(urlLocation, "/")+1:] var newRunLine string if viper.GetBool("security.enabled") { //todo } else { newRunLine = fmt.Sprintf("COPY %s /root/\n"+ "RUN cd /root/ && gradle build", urlLocation) } dockerFileContents := fmt.Sprintf("%s\n%s", viper.GetString("chaincode.java.Dockerfile"), newRunLine) dockerFileSize := int64(len([]byte(dockerFileContents))) //Make headers identical by using zero time var zeroTime time.Time tw.WriteHeader(&tar.Header{Name: "Dockerfile", Size: dockerFileSize, ModTime: zeroTime, AccessTime: zeroTime, ChangeTime: zeroTime}) tw.Write([]byte(dockerFileContents)) return nil }
func addFile(w *tar.Writer, name string, contents []byte) error { // Use similar file info to /etc/hosts fi, err := os.Stat("/etc/hosts") if err != nil { return err } h, err := tar.FileInfoHeader(fi, "") if err != nil { return err } h.Name = name h.Size = int64(len(contents)) if err := w.WriteHeader(h); err != nil { return err } if _, err := w.Write(contents); err != nil { return err } return nil }
func writeHosts(tw *tar.Writer) error { etcheader := tar.Header{} etcheader.Name = "rootfs/etc/" etcheader.Mode = 0644 etcheader.Typeflag = tar.TypeDir tw.WriteHeader(&etcheader) content := []byte("127.0.0.1 localhost\n::1 localhost\n") header := tar.Header{} header.Name = "rootfs/etc/hosts" header.Mode = 0644 header.Typeflag = tar.TypeReg header.Size = int64(len(content)) tw.WriteHeader(&header) if _, err := tw.Write(content); err != nil { return fmt.Errorf("cannot write manifest: %v", err) } return nil }
func WriteManifest(outputWriter *tar.Writer, manifest schema.ImageManifest) error { b, err := json.Marshal(manifest) if err != nil { return err } hdr := getGenericTarHeader() hdr.Name = "manifest" hdr.Mode = 0644 hdr.Size = int64(len(b)) hdr.Typeflag = tar.TypeReg if err := outputWriter.WriteHeader(hdr); err != nil { return err } if _, err := outputWriter.Write(b); err != nil { return err } return nil }