def create_tarball(self, tarfile):
        """Creates a gzip-compressed tarball and writes the contents to the
        filename specified in tarfile."""
        if not self.patches:
            return

        patch_dir = os.path.dirname(self.series)

        with ArchiveFileWriter(tarfile, libarchive.FORMAT_TAR_PAX_RESTRICTED,
                               libarchive.COMPRESSION_GZIP) as archive:
            for p in self.patches:
                # Remove extra parameter, e.g. -p1
                p = re.sub(r"\s+-p\d+\s*$", r"", p)

                patch_abs_path = os.path.join(patch_dir, p)
                patch_pathname = os.path.join("patches", p)

                archive.add_file(patch_abs_path,
                                 pathname=patch_pathname,
                                 uname="root",
                                 gname="root")
            #end for
        #end with

        size = os.path.getsize(tarfile)
        sha256sum = self._file_sha256_sum(tarfile)

        return (sha256sum, size)
Exemple #2
0
    def write_control_part(self, meta_data, pkg_contents, ctrl_abspath):
        with ArchiveFileWriter(ctrl_abspath, libarchive.FORMAT_TAR_USTAR,
                libarchive.COMPRESSION_GZIP) as archive:

            control_contents = [("control", str(meta_data), 0o644)]

            for script_name, script_content in self.maintainer_scripts.items():
                control_contents.append([script_name, script_content, 0o754])

            conffiles = self.conffiles(pkg_contents)
            if conffiles:
                control_contents.append(["conffiles", conffiles, 0o644])

            timestamp = int(time.time())

            with ArchiveEntry() as archive_entry:
                for entry_name, entry_contents, entry_mode in control_contents:
                    entry_contents = entry_contents.encode("utf-8")
                    archive_entry.clear()
                    archive_entry.pathname = entry_name
                    archive_entry.mode = stat.S_IFREG | entry_mode
                    archive_entry.atime = timestamp
                    archive_entry.mtime = timestamp
                    archive_entry.ctime = timestamp
                    archive_entry.uid = 0
                    archive_entry.gid = 0
                    archive_entry.uname = "root"
                    archive_entry.gname = "root"
                    archive_entry.size = len(entry_contents)
                    archive.write_entry(archive_entry)
                    archive.write_data(entry_contents)
Exemple #3
0
    def write_data_part(self, pkg_contents, data_abspath):
        installed_size = 0

        with ArchiveFileWriter(data_abspath, libarchive.FORMAT_TAR_USTAR,
                libarchive.COMPRESSION_GZIP) as archive:

            timestamp = int(time.time())

            with ArchiveEntry() as archive_entry:
                for src, attr in pkg_contents.items():
                    deftype    = attr.deftype
                    file_path  = "." + src
                    file_mode  = attr.mode
                    file_owner = attr.owner
                    file_group = attr.group
                    real_path  = os.path.normpath(self.basedir + os.sep + src)

                    archive_entry.clear()
                    if deftype != "file" and not os.path.exists(real_path):
                        archive_entry.mode = stat.S_IFDIR | 0o755
                        archive_entry.atime = timestamp
                        archive_entry.mtime = timestamp
                        archive_entry.ctime = timestamp
                    else:
                        archive_entry._copy_raw_stat(attr.stats)
                    #end if

                    archive_entry.pathname = file_path
                    archive_entry.uname = file_owner if file_owner else "root"
                    archive_entry.gname = file_group if file_group else "root"

                    if file_mode:
                        archive_entry.mode = archive_entry.filetype | file_mode
                    if archive_entry.is_symbolic_link:
                        archive_entry.symlink = attr.stats.link_target

                    archive.write_entry(archive_entry)

                    if archive_entry.is_file:
                        with open(real_path, "rb") as fp:
                            while True:
                                buf = fp.read(4096)
                                if not buf:
                                    break
                                archive.write_data(buf)
                            #end while
                        #end with
                    #end if

                    # imitate behavior of dpkg-gencontrol
                    if attr.stats.is_file or attr.stats.is_symbolic_link:
                        installed_size += attr.stats.st_size
                    else:
                        installed_size += 1024
                #end for
            #end with
        #end with

        return installed_size
Exemple #4
0
    def assemble_parts(self, meta_data, pkg_contents, pkg_filename):
        with TemporaryDirectory(prefix="bolt-") as tmpdir:
            installed_size = self.write_data_part(pkg_contents,
                    os.path.join(tmpdir, "data.tar.gz"))

            # According to Debian Policy Manual Installed-Size is in KB
            installed_size = int(installed_size / 1024 + 0.5)

            meta_data["Installed-Size"] = "{}".format(installed_size)

            self.write_control_part(meta_data, pkg_contents,
                    os.path.join(tmpdir, "control.tar.gz"))

            with open(os.path.join(tmpdir, "debian-binary"), "w+",
                    encoding="utf-8") as fp:
                fp.write(self.debian_binary_version + "\n")
            #end with

            with ArchiveFileWriter(pkg_filename, libarchive.FORMAT_AR_SVR4,
                    libarchive.COMPRESSION_NONE) as archive:
                with ArchiveEntry() as archive_entry:
                    for entry_name in ["debian-binary", "control.tar.gz",
                            "data.tar.gz"]:
                        archive_entry.clear()

                        full_path = os.path.normpath(os.sep.join([tmpdir,
                            entry_name]))
                        archive_entry.copy_stat(full_path)
                        archive_entry.pathname = entry_name
                        archive_entry.mode = stat.S_IFREG | 0o644
                        archive_entry.uid = 0
                        archive_entry.gid = 0
                        archive_entry.uname = "root"
                        archive_entry.gname = "root"
                        archive.write_entry(archive_entry)

                        with open(full_path, "rb") as fp:
                            while True:
                                buf = fp.read(4096)
                                if not buf:
                                    break
                                archive.write_data(buf)
    def store_package_index(self, index, current_digest=None):
        meta_data_list = []

        for name in sorted(index.keys()):
            for version in sorted(index[name].keys(), key=functools.cmp_to_key(
                    BaseXpkg.compare_versions)):
                meta_data_list.append(index[name][version])
            #end for
        #end for

        if not meta_data_list:
            return

        output = "\n".join([str(entry) for entry in meta_data_list])
        output = output.encode("utf-8")

        changed = True

        if current_digest is not None:
            h = hashlib.sha256()
            h.update(output)
            if h.hexdigest() == current_digest:
                changed = False

        packages_gz  = os.path.join(self._repo_dir, "Packages.gz")
        tempfile_gz  = None
        packages_sig = os.path.join(self._repo_dir, "Packages.sig")
        tempfile_sig = None

        try:
            if changed:
                with NamedTemporaryFile(dir=self._repo_dir, delete=False) \
                        as tempfile_gz:
                    pass

                options = [("gzip", "timestamp", None)]

                with ArchiveFileWriter(
                        tempfile_gz.name,
                        libarchive.FORMAT_RAW,
                        libarchive.COMPRESSION_GZIP,
                        options=options) as archive:

                    with ArchiveEntry() as archive_entry:
                        archive_entry.filetype = stat.S_IFREG
                        archive.write_entry(archive_entry)
                        archive.write_data(output)
                    #end with
                #end with

                os.chmod(
                    tempfile_gz.name,
                    stat.S_IRUSR |
                    stat.S_IWUSR |
                    stat.S_IRGRP |
                    stat.S_IROTH
                )
            #end if

            if self._sign_with and \
                    (changed or not os.path.exists(packages_sig)):
                signature = self._create_usign_signature(output)
                with NamedTemporaryFile(dir=self._repo_dir, delete=False) \
                        as tempfile_sig:
                    tempfile_sig.write(signature)

                os.chmod(
                    tempfile_sig.name,
                    stat.S_IRUSR |
                    stat.S_IWUSR |
                    stat.S_IRGRP |
                    stat.S_IROTH
                )
            #end if

            if tempfile_gz:
                os.rename(tempfile_gz.name, packages_gz)
            if tempfile_sig:
                os.rename(tempfile_sig.name, packages_sig)
        finally:
            if tempfile_gz and os.path.exists(tempfile_gz.name):
                os.unlink(tempfile_gz.name)
            if tempfile_sig and os.path.exists(tempfile_sig.name):
                os.unlink(tempfile_sig.name)
    def store_package_index(self, index, current_digest=None):
        meta_data_list = []

        for name in sorted(index.keys()):
            for version in sorted(index[name].keys(),
                                  key=functools.cmp_to_key(
                                      BaseXpkg.compare_versions)):
                meta_data_list.append(index[name][version])
            #end for
        #end for

        if not meta_data_list:
            return

        text_output = "\n".join([str(entry) for entry in meta_data_list])
        byte_output = text_output.encode("utf-8")

        signature = None
        signed_output = None

        if self._sign_with:
            signature = self._create_usign_signature(byte_output)

            signed_output = (
                """\
-----BEGIN SIGNIFY SIGNED MESSAGE-----
{output}\
-----BEGIN SIGNIFY SIGNATURE-----
{signature}\
-----END SIGNIFY SIGNATURE-----
"""
            ) \
            .format(
                output=text_output,
                signature=signature
            ) \
            .encode("utf-8")
        #end if

        changed = True

        if current_digest is not None:
            h = hashlib.sha256()
            h.update(byte_output)
            if h.hexdigest() == current_digest:
                changed = False

        packages_gz = os.path.join(self._repo_dir, "Packages.gz")
        tempfile_gz = None
        packages_sig = os.path.join(self._repo_dir, "Packages.sig")
        tempfile_sig = None
        packages_in = os.path.join(self._repo_dir, "InPackages.gz")
        tempfile_in = None

        options = [("gzip", "timestamp", None)]

        try:
            if changed:
                with NamedTemporaryFile(dir=self._repo_dir, delete=False) \
                        as tempfile_gz:
                    pass

                with ArchiveFileWriter(tempfile_gz.name,
                                       libarchive.FORMAT_RAW,
                                       libarchive.COMPRESSION_GZIP,
                                       options=options) as archive:

                    with ArchiveEntry() as archive_entry:
                        archive_entry.filetype = stat.S_IFREG
                        archive.write_entry(archive_entry)
                        archive.write_data(byte_output)
                    #end with
                #end with

                os.chmod(
                    tempfile_gz.name,
                    stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
            #end if

            if signature and signed_output:
                if changed or not os.path.exists(packages_in):
                    with NamedTemporaryFile(dir=self._repo_dir, delete=False) \
                            as tempfile_in:
                        pass

                    with ArchiveFileWriter(tempfile_in.name,
                                           libarchive.FORMAT_RAW,
                                           libarchive.COMPRESSION_GZIP,
                                           options=options) as archive:

                        with ArchiveEntry() as archive_entry:
                            archive_entry.filetype = stat.S_IFREG
                            archive.write_entry(archive_entry)
                            archive.write_data(signed_output)
                        #end with
                    #end with

                    os.chmod(
                        tempfile_in.name, stat.S_IRUSR | stat.S_IWUSR
                        | stat.S_IRGRP | stat.S_IROTH)
                #end if

                if changed or not os.path.exists(packages_sig):
                    with NamedTemporaryFile(dir=self._repo_dir,
                                            mode="w+",
                                            delete=False,
                                            encoding="utf-8") as tempfile_sig:
                        tempfile_sig.write(signature)

                    os.chmod(
                        tempfile_sig.name, stat.S_IRUSR | stat.S_IWUSR
                        | stat.S_IRGRP | stat.S_IROTH)
                #end if
            #end if

            if tempfile_gz:
                os.rename(tempfile_gz.name, packages_gz)
            if tempfile_sig:
                os.rename(tempfile_sig.name, packages_sig)
            if tempfile_in:
                os.rename(tempfile_in.name, packages_in)
        finally:
            if tempfile_gz and os.path.exists(tempfile_gz.name):
                os.unlink(tempfile_gz.name)
            if tempfile_sig and os.path.exists(tempfile_sig.name):
                os.unlink(tempfile_sig.name)
            if tempfile_in and os.path.exists(tempfile_in.name):
                os.unlink(tempfile_in.name)