// member(arMember, tarMember) returns the content of the given tar member of // the given ar member tar. // // Confused? look at ControlMember and MetaMember, which this generalises. func (d *ClickDeb) member(arMember, tarMember string) (content []byte, err error) { if _, err := d.file.Seek(0, 0); err != nil { return nil, err } arReader := ar.NewReader(d.file) dataReader, err := skipToArMember(arReader, arMember) if err != nil { return nil, err } found := false err = helpers.TarIterate(dataReader, func(tr *tar.Reader, hdr *tar.Header) error { if filepath.Clean(hdr.Name) == tarMember { found = true content, err = ioutil.ReadAll(tr) if err != nil { return err } } return nil }) if !found { return nil, ErrMemberNotFound } if err != nil { return nil, err } return content, nil }
func inspectPackage(filename string) (string, error) { f, err := os.Open(filename) if err != nil { return "", fmt.Errorf("error opening package file %s: %s", filename, err) } arReader := ar.NewReader(f) defer f.Close() var controlBuf bytes.Buffer for { header, err := arReader.Next() if err == io.EOF { break } if err != nil { return "", fmt.Errorf("error in inspectPackage loop: %s", err) } if header.Name == "control.tar.gz" { io.Copy(&controlBuf, arReader) return inspectPackageControl(controlBuf) } } return "", nil }
// extract 'control' file from 'reader'. the contents of a 'control' file // is a set of key-value pairs as described in // https://www.debian.org/doc/debian-policy/ch-controlfields.html func extractControlFromIpk(reader io.Reader) (string, error) { var ( arReader *ar.Reader tarReader *tar.Reader gzReader *gzip.Reader ) arReader = ar.NewReader(reader) for { header, err := arReader.Next() if err != nil && err != io.EOF { return "", fmt.Errorf("extracting contents: %v", err) } else if header == nil { break } // NOTE: strangeley the name of the files end with a "/" ... content error? if header.Name == "control.tar.gz/" || header.Name == "control.tar.gz" { gzReader, err = gzip.NewReader(arReader) if err != nil { return "", fmt.Errorf("analyzing control.tar.gz: %v", err) } break } } if gzReader == nil { return "", fmt.Errorf("missing control.tar.gz entry") } defer gzReader.Close() buffer := bytes.NewBuffer(nil) tarReader = tar.NewReader(gzReader) for { header, err := tarReader.Next() if err != nil && err != io.EOF { return "", fmt.Errorf("extracting control.tar.gz: %v", err) } else if header == nil { break } if header.Name != "./control" { continue } io.Copy(buffer, tarReader) break } if buffer.Len() == 0 { return "", fmt.Errorf("missing or empty 'control' file inside 'control.tar.gz'") } return buffer.String(), nil }
func (t *AddDebTask) Run(b *BuildContext) error { in, err := t.Source.Open() if err != nil { return fmt.Errorf("error reading source deb (%s): %v", t.Source.Name(), err) } defer loggedClose(in, t.Source.Name()) reader := ar.NewReader(in) foundData := false for { header, err := reader.Next() if err == io.EOF { break } if err != nil { return fmt.Errorf("error reading deb file (%s): %v", t.Source.Name(), err) } glog.Infof("ar entry: %s", header.Name) if header.Name == "data.tar.xz" || header.Name == "data.tar.xz/" { foundData = true xz := &XZByteSource{Inner: NewOnceByteSource(ioutil.NopCloser(reader), t.Source.Name())} tarTask := AddTarTask{Source: xz, DestPath: t.DestPath} err = tarTask.Run(b) if err != nil { return err } } else if header.Name == "data.tar.gz" || header.Name == "data.tar.gz/" { foundData = true src := &GZIPByteSource{Inner: NewOnceByteSource(ioutil.NopCloser(reader), t.Source.Name())} tarTask := AddTarTask{Source: src, DestPath: t.DestPath} err = tarTask.Run(b) if err != nil { return err } } else { _, err = io.Copy(ioutil.Discard, reader) if err != nil { return fmt.Errorf("error reading deb file entry (%s): %v", t.Source.Name(), err) } } } if !foundData { return fmt.Errorf("unable to find data segment in %s", t.Source.Name()) } return nil }
// UnpackAll unpacks the data.tar.{gz,bz2,xz} into the given target directory // with click specific verification, i.e. no files will be extracted outside // of the targetdir (no ".." inside the data.tar is allowed) func (d *ClickDeb) UnpackAll(targetDir string) error { if _, err := d.file.Seek(0, 0); err != nil { return err } arReader := ar.NewReader(d.file) dataReader, err := skipToArMember(arReader, "data.tar") if err != nil { return err } // and unpack return helpers.UnpackTar(dataReader, targetDir, clickVerifyContentFn) }
func readDebControlFile(reader io.Reader) (string, error) { archiveReader := ar.NewReader(reader) for { header, err := archiveReader.Next() if err == io.EOF { break } if err != nil { panic(err) } if strings.HasPrefix(header.Name, "control.tar") { var controlReader *tar.Reader if strings.HasSuffix(header.Name, "gz") { gzipStream, err := gzip.NewReader(archiveReader) if err != nil { panic(err) } controlReader = tar.NewReader(gzipStream) } else { return "", errors.New("Compression type not supported") } for { header, err := controlReader.Next() if err == io.EOF { break } if err != nil { panic(err) } if strings.HasSuffix(header.Name, "control") { var buffer bytes.Buffer _, err := io.Copy(bufio.NewWriter(&buffer), controlReader) if err != nil { panic(err) } return buffer.String(), nil } } } } return "", errors.New("Couldn't find control file in package") }