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)
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)
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
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)