Skip to content

Commit

Permalink
libpriv/importer: move tmpfiles.d entries buffering to Rust
Browse files Browse the repository at this point in the history
This moves the RPM importer buffering logic for tmpfiles.d entries
to Rust.
  • Loading branch information
lucab authored and cgwalters committed Jun 10, 2022
1 parent 939a63a commit d44d81d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 18 deletions.
42 changes: 41 additions & 1 deletion rust/src/importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub struct RpmImporter {
/// - [K] absolute full path of the file
/// - [V] iterator index in RPM header for this file
rpmfi_overrides: HashMap<String, u64>,
/// Filepaths translated to tmpfiles.d entries.
tmpfiles_entries: Vec<String>,
}

/// Build a new RPM importer for a given package.
Expand Down Expand Up @@ -102,6 +104,7 @@ impl RpmImporter {
pkg_name: pkg_name.to_string(),
varlib_direntries: BTreeSet::new(),
rpmfi_overrides: HashMap::new(),
tmpfiles_entries: vec![],
};
Ok(importer)
}
Expand Down Expand Up @@ -176,7 +179,7 @@ impl RpmImporter {
/// Format tmpfiles.d lines for symlinked entries.
// NOTE(lucab): destinations (dirname) can't be quoted as systemd just
// parses the remainder of the line, and doesn't expand quotes.
pub fn tmpfiles_symlink_entries(&self) -> Vec<String> {
fn tmpfiles_symlink_entries(&self) -> Vec<String> {
// /opt/ symlinks
let opt_entries = self.opt_direntries.iter().map(|dirname| {
let quoted = crate::maybe_shell_quote(&format!("/opt/{dirname}"));
Expand Down Expand Up @@ -251,6 +254,43 @@ impl RpmImporter {
x => unreachable!("unknown commit result '{}' for path '{}'", x, path),
}
}

/// Translate a filepath to an equivalent tmpfiles.d line.
pub fn translate_to_tmpfiles_entry(
&mut self,
abs_path: &str,
mut file_info: Pin<&mut crate::FFIGFileInfo>,
username: &str,
groupname: &str,
) -> CxxResult<()> {
let file_info = file_info.gobj_wrap();
let entry = translate_to_tmpfiles_d(abs_path, &file_info, username, groupname)?;
self.tmpfiles_entries.push(entry);
Ok(())
}

/// Return whether this RPM has any auto-translated tmpfiles.d entries.
pub fn has_tmpfiles_entries(&self) -> bool {
self.tmpfiles_entries
.len()
.saturating_add(self.opt_direntries.len())
.saturating_add(self.varlib_direntries.len())
> 0
}

/// Serialize all tmpfiles.d entries as a single configuration fragment.
pub fn serialize_tmpfiles_content(&self) -> String {
let mut buf = String::new();

let symlink_entries = self.tmpfiles_symlink_entries();
let all_entries = symlink_entries.iter().chain(self.tmpfiles_entries.iter());

for entry in all_entries {
buf.push_str(&entry);
buf.push('\n');
}
buf
}
}

/// Canonicalize a path, e.g. replace `//` with `/` and `././` with `./`.
Expand Down
10 changes: 9 additions & 1 deletion rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ pub mod ffi {
fn handle_translate_pathname(self: &mut RpmImporter, path: &str) -> String;
fn ostree_branch(self: &RpmImporter) -> String;
fn pkg_name(self: &RpmImporter) -> String;
fn tmpfiles_symlink_entries(self: &RpmImporter) -> Vec<String>;
fn doc_files_are_filtered(self: &RpmImporter) -> bool;
fn doc_files_insert(self: &mut RpmImporter, path: &str);
fn doc_files_contains(self: &RpmImporter, path: &str) -> bool;
Expand All @@ -363,6 +362,15 @@ pub mod ffi {
path: &str,
mut file_info: Pin<&mut GFileInfo>,
) -> Result<bool>;
fn translate_to_tmpfiles_entry(
self: &mut RpmImporter,
abs_path: &str,
mut file_info: Pin<&mut GFileInfo>,
username: &str,
groupname: &str,
) -> Result<()>;
fn has_tmpfiles_entries(self: &RpmImporter) -> bool;
fn serialize_tmpfiles_content(self: &RpmImporter) -> String;

fn tmpfiles_translate(
abs_path: &str,
Expand Down
23 changes: 7 additions & 16 deletions src/libpriv/rpmostree-importer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ struct RpmOstreeImporter
Header hdr;
rpmfi fi;
off_t cpio_offset;
GString *tmpfiles_d;
DnfPackage *pkg;

std::optional<rust::Box<rpmostreecxx::RpmImporter> > importer_rs;
Expand All @@ -80,7 +79,6 @@ rpmostree_importer_finalize (GObject *object)
if (self->fi)
(void)rpmfiFree (self->fi);
glnx_close_fd (&self->fd);
g_string_free (self->tmpfiles_d, TRUE);
g_clear_object (&self->repo);
g_clear_object (&self->sepolicy);

Expand All @@ -101,7 +99,6 @@ static void
rpmostree_importer_init (RpmOstreeImporter *self)
{
self->fd = -1;
self->tmpfiles_d = g_string_new ("");
self->importer_rs = std::nullopt;
}

Expand Down Expand Up @@ -497,13 +494,9 @@ compose_filter_cb (OstreeRepo *repo, const char *path, GFileInfo *file_info, gpo
const char *group = NULL;
get_rpmfi_override (self, path, &user, &group, NULL, NULL);

auto entry = ROSCXX_VAL (
tmpfiles_translate (path, *file_info, user ?: "root", group ?: "root"), error);
if (entry.has_value ())
{
g_string_append (self->tmpfiles_d, entry.value ().c_str ());
g_string_append_c (self->tmpfiles_d, '\n');
}
CXX ((*self->importer_rs)
->translate_to_tmpfiles_entry (path, *file_info, user ?: "root", group ?: "root"),
error);

return OSTREE_REPO_COMMIT_FILTER_SKIP;
}
Expand Down Expand Up @@ -607,9 +600,6 @@ import_rpm_to_repo (RpmOstreeImporter *self, char **out_csum, char **out_metadat
return FALSE;
}

for (auto &line : (*self->importer_rs)->tmpfiles_symlink_entries ())
g_string_append_printf (self->tmpfiles_d, "%s\n", line.c_str ());

/* Handle any data we've accumulated to write to tmpfiles.d.
* I originally tried to do this entirely in memory but things
* like selinux labeling only happen as callbacks out of using
Expand All @@ -618,8 +608,9 @@ import_rpm_to_repo (RpmOstreeImporter *self, char **out_csum, char **out_metadat
g_auto (GLnxTmpDir) tmpdir = {
0,
};
if (self->tmpfiles_d->len > 0)
if ((*self->importer_rs)->has_tmpfiles_entries ())
{
auto content = (*self->importer_rs)->serialize_tmpfiles_content ();
auto pkg_name = (*self->importer_rs)->pkg_name ();

if (!glnx_mkdtemp ("rpm-ostree-import.XXXXXX", 0700, &tmpdir, error))
Expand All @@ -628,8 +619,8 @@ import_rpm_to_repo (RpmOstreeImporter *self, char **out_csum, char **out_metadat
return FALSE;
if (!glnx_file_replace_contents_at (
tmpdir.fd, glnx_strjoina ("usr/lib/tmpfiles.d/", "pkg-", pkg_name.c_str (), ".conf"),
(guint8 *)self->tmpfiles_d->str, self->tmpfiles_d->len, GLNX_FILE_REPLACE_NODATASYNC,
cancellable, error))
(guint8 *)content.data (), content.size (), GLNX_FILE_REPLACE_NODATASYNC, cancellable,
error))
return FALSE;

if (!ostree_repo_write_dfd_to_mtree (repo, tmpdir.fd, ".", mtree, modifier, cancellable,
Expand Down

0 comments on commit d44d81d

Please sign in to comment.