diff --git a/rust/Cargo.lock b/rust/Cargo.lock index f7024a33..fe2883e6 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -215,6 +215,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "drop_bomb" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1" + [[package]] name = "dtoa" version = "0.4.6" @@ -590,15 +596,14 @@ dependencies = [ [[package]] name = "nix" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" +checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" dependencies = [ "bitflags", "cc", "cfg-if 0.1.10", "libc", - "void", ] [[package]] @@ -665,13 +670,15 @@ dependencies = [ [[package]] name = "openat-ext" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1be1e54fbd54bae8b4497ddcc30f97ae57f18fa37fa2f35d48db7b0a8f0b59" +checksum = "73e85ee792caf10bf54dc2a844b9f5cbc4a05095360fdeba67ffe687912d2b8b" dependencies = [ + "drop_bomb", "libc", - "nix 0.17.0", + "nix 0.18.0", "openat", + "rand", ] [[package]] @@ -1263,12 +1270,6 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 32958dc5..4068884f 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -22,7 +22,7 @@ tempfile = "3.1.0" clap = "2.33.3" structopt = "0.3.20" openat = "0.1.19" -openat-ext = "0.1.6" +openat-ext = "^0.1.8" curl = "0.4.34" rayon = "1.5.0" c_utf8 = "0.1.0" diff --git a/rust/src/cliwrap.rs b/rust/src/cliwrap.rs index 7a90acd4..d53f9288 100644 --- a/rust/src/cliwrap.rs +++ b/rust/src/cliwrap.rs @@ -18,7 +18,7 @@ use anyhow::{bail, Result}; use std::io::prelude::*; -use std::{io, path}; +use std::path; use openat_ext::OpenatDirExt; use rayon::prelude::*; @@ -84,20 +84,19 @@ fn write_wrappers(rootfs_dfd: &openat::Dir) -> Result<()> { let destpath = format!("{}/{}", CLIWRAP_DESTDIR, name); rootfs_dfd.local_rename(bin, destpath.as_str())?; - let f = rootfs_dfd.write_file(binpath, 0o755)?; - let mut f = io::BufWriter::new(f); - write!( - f, - "#!/bin/sh -# Wrapper created by rpm-ostree to override -# behavior of the underlying binary. For more -# information see `man rpm-ostree`. The real -# binary is now located at: {} -exec /usr/bin/rpm-ostree cliwrap $0 \"$@\" -", - binpath.to_str().unwrap() - )?; - f.flush()?; + rootfs_dfd.write_file_with(binpath, 0o755, |w| { + write!( + w, + "#!/bin/sh + # Wrapper created by rpm-ostree to override + # behavior of the underlying binary. For more + # information see `man rpm-ostree`. The real + # binary is now located at: {} + exec /usr/bin/rpm-ostree cliwrap $0 \"$@\" + ", + binpath.to_str().unwrap() + ) + })?; Ok(()) }) } diff --git a/rust/src/composepost.rs b/rust/src/composepost.rs index ee1db855..f8ae58e1 100644 --- a/rust/src/composepost.rs +++ b/rust/src/composepost.rs @@ -12,8 +12,6 @@ use std::io; use std::io::{BufRead, Write}; use std::path::Path; -use crate::utils; - // rpm-ostree uses /home → /var/home by default as generated by our // rootfs; we don't expect people to change this. Let's be nice // and also fixup the $HOME entries generated by `useradd` so @@ -26,21 +24,19 @@ use crate::utils; fn postprocess_useradd(rootfs_dfd: &openat::Dir) -> Result<()> { let path = Path::new("usr/etc/default/useradd"); if let Some(f) = rootfs_dfd.open_file_optional(path)? { - let f = io::BufReader::new(f); - let tmp_path = utils::parent_dir(path).unwrap().join("useradd.tmp"); - let o = rootfs_dfd.write_file(&tmp_path, 0o644)?; - let mut bufw = io::BufWriter::new(&o); - for line in f.lines() { - let line = line?; - if !line.starts_with("HOME=") { - bufw.write(line.as_bytes())?; - } else { - bufw.write("HOME=/var/home".as_bytes())?; + rootfs_dfd.write_file_with(&path, 0o644, |bufw| -> Result<_> { + let f = io::BufReader::new(&f); + for line in f.lines() { + let line = line?; + if !line.starts_with("HOME=") { + bufw.write(line.as_bytes())?; + } else { + bufw.write("HOME=/var/home".as_bytes())?; + } + bufw.write("\n".as_bytes())?; } - bufw.write("\n".as_bytes())?; - } - bufw.flush()?; - rootfs_dfd.local_rename(&tmp_path, path)?; + Ok(()) + })?; } Ok(()) } @@ -49,18 +45,19 @@ fn postprocess_useradd(rootfs_dfd: &openat::Dir) -> Result<()> { // enabled; let's just do this rather than trying to propagate the // preset everywhere. fn postprocess_presets(rootfs_dfd: &openat::Dir) -> Result<()> { - let mut o = rootfs_dfd.write_file( + rootfs_dfd.write_file_with( "usr/lib/systemd/system-preset/40-rpm-ostree-auto.preset", 0o644, - )?; - o.write( - r###"# Written by rpm-ostree compose tree + |w| { + w.write( + r###"# Written by rpm-ostree compose tree enable ostree-remount.service enable ostree-finalize-staged.path "### - .as_bytes(), + .as_bytes(), + ) + }, )?; - o.flush()?; Ok(()) } @@ -71,26 +68,22 @@ enable ostree-finalize-staged.path fn postprocess_subs_dist(rootfs_dfd: &openat::Dir) -> Result<()> { let path = Path::new("usr/etc/selinux/targeted/contexts/files/file_contexts.subs_dist"); if let Some(f) = rootfs_dfd.open_file_optional(path)? { - let f = io::BufReader::new(f); - let tmp_path = utils::parent_dir(path) - .unwrap() - .join("file_contexts.subs_dist.tmp"); - let o = rootfs_dfd.write_file(&tmp_path, 0o644)?; - let mut bufw = io::BufWriter::new(&o); - for line in f.lines() { - let line = line?; - if line.starts_with("/var/home ") { - bufw.write(b"# https://github.com/projectatomic/rpm-ostree/pull/1754\n")?; - bufw.write(b"# ")?; + rootfs_dfd.write_file_with(&path, 0o644, |w| -> Result<()> { + let f = io::BufReader::new(&f); + for line in f.lines() { + let line = line?; + if line.starts_with("/var/home ") { + w.write(b"# https://github.com/projectatomic/rpm-ostree/pull/1754\n")?; + w.write(b"# ")?; + } + w.write(line.as_bytes())?; + w.write(b"\n")?; } - bufw.write(line.as_bytes())?; - bufw.write(b"\n")?; - } - bufw.write(b"# https://github.com/projectatomic/rpm-ostree/pull/1754\n")?; - bufw.write(b"/home /var/home")?; - bufw.write(b"\n")?; - bufw.flush()?; - rootfs_dfd.local_rename(&tmp_path, path)?; + w.write(b"# https://github.com/projectatomic/rpm-ostree/pull/1754\n")?; + w.write(b"/home /var/home")?; + w.write(b"\n")?; + Ok(()) + })?; } Ok(()) } diff --git a/rust/src/lockfile.rs b/rust/src/lockfile.rs index a02114e4..e98a52f1 100644 --- a/rust/src/lockfile.rs +++ b/rust/src/lockfile.rs @@ -9,6 +9,7 @@ use anyhow::Result; use chrono::prelude::*; +use openat_ext::OpenatDirExt; use serde_derive::{Deserialize, Serialize}; use serde_json; use std::collections::{BTreeMap, HashMap}; @@ -230,7 +231,7 @@ mod ffi { rpmmd_repos: *mut glib_sys::GPtrArray, gerror: *mut *mut glib_sys::GError, ) -> libc::c_int { - let filename = ffi_view_os_str(filename); + let filename = Path::new(ffi_view_os_str(filename)); let packages: Vec<*mut DnfPackage> = ffi_ptr_array_to_vec(packages); let rpmmd_repos: Vec<*mut DnfRepo> = ffi_ptr_array_to_vec(rpmmd_repos); @@ -292,9 +293,14 @@ mod ffi { } int_glib_error( - utils::write_file(filename, |w| { - Ok(serde_json::to_writer_pretty(w, &lockfile)?) - }), + || -> Result<()> { + let lockfile_dir = openat::Dir::open(filename.parent().unwrap_or(Path::new("/")))?; + let basename = filename.file_name().expect("filename"); + lockfile_dir.write_file_with(basename, 0o644, |w| -> Result<()> { + Ok(serde_json::to_writer_pretty(w, &lockfile)?) + })?; + Ok(()) + }(), gerror, ) } diff --git a/rust/src/treefile.rs b/rust/src/treefile.rs index 0359fd48..6abfe323 100644 --- a/rust/src/treefile.rs +++ b/rust/src/treefile.rs @@ -949,6 +949,7 @@ impl TreeComposeConfig { #[cfg(test)] mod tests { use super::*; + use openat_ext::OpenatDirExt; use tempfile; static ARCH_X86_64: &str = "x86_64"; @@ -1172,10 +1173,7 @@ automatic_version_prefix: bar basearch: Option<&'b str>, ) -> Result> { let tf_path = workdir.join("treefile.yaml"); - utils::write_file(&tf_path, |b| { - b.write_all(contents.as_bytes())?; - Ok(()) - })?; + std::fs::write(&tf_path, contents)?; Ok(Treefile::new_boxed( tf_path.as_path(), basearch, @@ -1215,14 +1213,15 @@ rojig: #[test] fn test_treefile_includes() -> Result<()> { let workdir = tempfile::tempdir()?; - utils::write_file(workdir.path().join("foo.yaml"), |b| { - let foo = r#" -packages: - - fooinclude -"#; - b.write_all(foo.as_bytes())?; - Ok(()) - })?; + let workdir_d = openat::Dir::open(workdir.path())?; + workdir_d.write_file_contents( + "foo.yaml", + 0o644, + r#" + packages: + - fooinclude + "#, + )?; let mut buf = VALID_PRELUDE.to_string(); buf.push_str( r#" @@ -1237,14 +1236,15 @@ include: foo.yaml #[test] fn test_treefile_arch_includes() -> Result<()> { let workdir = tempfile::tempdir()?; - utils::write_file(workdir.path().join("foo-x86_64.yaml"), |b| { - let foo = r#" + let workdir_d = openat::Dir::open(workdir.path())?; + workdir_d.write_file_contents( + "foo-x86_64.yaml", + 0o644, + r#" packages: - foo-x86_64-include -"#; - b.write_all(foo.as_bytes())?; - Ok(()) - })?; +"#, + )?; let mut buf = VALID_PRELUDE.to_string(); buf.push_str( r#" diff --git a/rust/src/utils.rs b/rust/src/utils.rs index a83f0ffa..c23df86b 100644 --- a/rust/src/utils.rs +++ b/rust/src/utils.rs @@ -104,23 +104,6 @@ pub fn create_file>(filename: P) -> Result { })?); } -/// Open file for writing, passes a Writer to a closure, and closes the file, with O_TMPFILE -/// semantics. -pub fn write_file(filename: P, f: F) -> Result<()> -where - P: AsRef, - F: Fn(&mut io::BufWriter<&mut fs::File>) -> Result<()>, -{ - // XXX: enhance with tempfile + linkat + rename dance - let mut file = create_file(filename)?; - { - let mut w = io::BufWriter::new(&mut file); - f(&mut w)?; - } - file.sync_all()?; - Ok(()) -} - // Surprising we need a wrapper for this... parent() returns a slice of its buffer, so doesn't // handle going up relative paths well: https://github.com/rust-lang/rust/issues/36861 pub fn parent_dir(filename: &Path) -> Option<&Path> {