Skip to content

Commit c34b5e5

Browse files
authored
Merge pull request #1108 from cgwalters/misc-prep
A few misc prep patches
2 parents 8decbcd + 0205e92 commit c34b5e5

File tree

7 files changed

+106
-69
lines changed

7 files changed

+106
-69
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hack/provision-derived.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ mkdir -p ~/.config/nushell
1414
echo '$env.config = { show_banner: false, }' > ~/.config/nushell/config.nu
1515
touch ~/.config/nushell/env.nu
1616
dnf -y install nu
17-
dnf clean all && rm /var/log/* -rf
17+
dnf clean all
18+
# Stock extra cleaning of logs and caches in general (mostly dnf)
19+
rm /var/log/* /var/cache /var/lib/dnf /var/lib/rpm-state -rf
20+
# And clean root's homedir
21+
rm /var/roothome/.config -rf

lib/src/install.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ use crate::progress_jsonl::ProgressWriter;
5858
use crate::spec::ImageReference;
5959
use crate::store::Storage;
6060
use crate::task::Task;
61-
use crate::utils::{open_dir_noxdev, sigpolicy_from_opt};
61+
use crate::utils::sigpolicy_from_opt;
6262

6363
/// The toplevel boot directory
6464
const BOOT: &str = "boot";
@@ -1579,7 +1579,7 @@ fn remove_all_in_dir_no_xdev(d: &Dir, mount_err: bool) -> Result<()> {
15791579
let name = entry.file_name();
15801580
let etype = entry.file_type()?;
15811581
if etype == FileType::dir() {
1582-
if let Some(subdir) = open_dir_noxdev(d, &name)? {
1582+
if let Some(subdir) = d.open_dir_noxdev(&name)? {
15831583
remove_all_in_dir_no_xdev(&subdir, mount_err)?;
15841584
d.remove_dir(&name)?;
15851585
} else if mount_err {

lib/src/lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ fn check_utf8(dir: &Dir) -> LintResult {
346346
return lint_err(format!("/{strname}: Found non-utf8 symlink target"));
347347
}
348348
} else if ifmt.is_dir() {
349-
let Some(subdir) = crate::utils::open_dir_noxdev(dir, entry.file_name())? else {
349+
let Some(subdir) = dir.open_dir_noxdev(entry.file_name())? else {
350350
continue;
351351
};
352352
if let Err(err) = check_utf8(&subdir)? {

lib/src/utils.rs

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::future::Future;
22
use std::io::Write;
3-
use std::os::fd::{AsFd, BorrowedFd, OwnedFd};
4-
use std::path::Path;
3+
use std::os::fd::BorrowedFd;
54
use std::process::Command;
65
use std::time::Duration;
76

@@ -17,7 +16,6 @@ use libsystemd::logging::journal_print;
1716
use ostree::glib;
1817
use ostree_ext::container::SignatureSource;
1918
use ostree_ext::ostree;
20-
use rustix::path::Arg;
2119

2220
/// Try to look for keys injected by e.g. rpm-ostree requesting machine-local
2321
/// changes; if any are present, return `true`.
@@ -54,33 +52,6 @@ pub(crate) fn deployment_fd(
5452
sysroot_dir.open_dir(&dirpath).map_err(Into::into)
5553
}
5654

57-
/// A thin wrapper for [`openat2`] but that retries on interruption.
58-
pub fn openat2_with_retry(
59-
dirfd: impl AsFd,
60-
path: impl AsRef<Path>,
61-
oflags: rustix::fs::OFlags,
62-
mode: rustix::fs::Mode,
63-
resolve: rustix::fs::ResolveFlags,
64-
) -> rustix::io::Result<OwnedFd> {
65-
let dirfd = dirfd.as_fd();
66-
let path = path.as_ref();
67-
// We loop forever on EAGAIN right now. The cap-std version loops just 4 times,
68-
// which seems really arbitrary.
69-
path.into_with_c_str(|path_c_str| 'start: loop {
70-
match rustix::fs::openat2(dirfd, path_c_str, oflags, mode, resolve) {
71-
Ok(file) => {
72-
return Ok(file);
73-
}
74-
Err(rustix::io::Errno::AGAIN | rustix::io::Errno::INTR) => {
75-
continue 'start;
76-
}
77-
Err(e) => {
78-
return Err(e);
79-
}
80-
}
81-
})
82-
}
83-
8455
/// Given an mount option string list like foo,bar=baz,something=else,ro parse it and find
8556
/// the first entry like $optname=
8657
/// This will not match a bare `optname` without an equals.
@@ -110,25 +81,6 @@ pub(crate) fn open_dir_remount_rw(root: &Dir, target: &Utf8Path) -> Result<Dir>
11081
root.open_dir(target).map_err(anyhow::Error::new)
11182
}
11283

113-
/// Open the target directory, but return Ok(None) if this would cross a mount point.
114-
pub fn open_dir_noxdev(
115-
parent: &Dir,
116-
path: impl AsRef<std::path::Path>,
117-
) -> std::io::Result<Option<Dir>> {
118-
use rustix::fs::{Mode, OFlags, ResolveFlags};
119-
match openat2_with_retry(
120-
parent,
121-
path,
122-
OFlags::CLOEXEC | OFlags::DIRECTORY | OFlags::NOFOLLOW,
123-
Mode::empty(),
124-
ResolveFlags::NO_XDEV | ResolveFlags::BENEATH,
125-
) {
126-
Ok(r) => Ok(Some(Dir::reopen_dir(&r)?)),
127-
Err(e) if e == rustix::io::Errno::XDEV => Ok(None),
128-
Err(e) => return Err(e.into()),
129-
}
130-
}
131-
13284
/// Given a target path, remove its immutability if present
13385
#[context("Removing immutable flag from {target}")]
13486
pub(crate) fn remove_immutability(root: &Dir, target: &Utf8Path) -> Result<()> {
@@ -236,8 +188,6 @@ pub(crate) fn digested_pullspec(image: &str, digest: &str) -> String {
236188

237189
#[cfg(test)]
238190
mod tests {
239-
use cap_std_ext::cap_std;
240-
241191
use super::*;
242192

243193
#[test]
@@ -273,15 +223,4 @@ mod tests {
273223
SignatureSource::ContainerPolicyAllowInsecure
274224
);
275225
}
276-
277-
#[test]
278-
fn test_open_noxdev() -> Result<()> {
279-
let root = Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
280-
// This hard requires the host setup to have /usr/bin on the same filesystem as /
281-
let usr = Dir::open_ambient_dir("/usr", cap_std::ambient_authority())?;
282-
assert!(open_dir_noxdev(&usr, "bin").unwrap().is_some());
283-
// Requires a mounted /proc, but that also seems ane.
284-
assert!(open_dir_noxdev(&root, "proc").unwrap().is_none());
285-
Ok(())
286-
}
287226
}

utils/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ serde = { workspace = true, features = ["derive"] }
1313
serde_json = { workspace = true }
1414
tempfile = { workspace = true }
1515
tracing = { workspace = true }
16-
tokio = { workspace = true, features = ["process"] }
16+
tokio = { workspace = true, features = ["process", "rt", "macros"] }
1717
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
1818

1919
[dev-dependencies]

utils/src/lib.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,97 @@ mod command;
66
mod tracing_util;
77
pub use command::*;
88
pub use tracing_util::*;
9+
10+
/// Given an iterator that's clonable, split it into two iterators
11+
/// at a given maximum number of elements.
12+
pub fn iterator_split<I>(
13+
it: I,
14+
max: usize,
15+
) -> (impl Iterator<Item = I::Item>, impl Iterator<Item = I::Item>)
16+
where
17+
I: Iterator + Clone,
18+
{
19+
let rest = it.clone();
20+
(it.take(max), rest.skip(max))
21+
}
22+
23+
/// Given an iterator that's clonable, split off the first N elements
24+
/// at the pivot point. If the iterator would be empty, return None.
25+
/// Return the count of the remainder.
26+
pub fn iterator_split_nonempty_rest_count<I>(
27+
it: I,
28+
max: usize,
29+
) -> Option<(impl Iterator<Item = I::Item>, usize)>
30+
where
31+
I: Iterator + Clone,
32+
{
33+
let rest = it.clone();
34+
let mut it = it.peekable();
35+
if it.peek().is_some() {
36+
Some((it.take(max), rest.skip(max).count()))
37+
} else {
38+
None
39+
}
40+
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use super::*;
45+
46+
#[test]
47+
fn test_it_split() {
48+
let a: &[&str] = &[];
49+
for v in [0, 1, 5] {
50+
let (first, rest) = iterator_split(a.iter(), v);
51+
assert_eq!(first.count(), 0);
52+
assert_eq!(rest.count(), 0);
53+
}
54+
let a = &["foo"];
55+
for v in [1, 5] {
56+
let (first, rest) = iterator_split(a.iter(), v);
57+
assert_eq!(first.count(), 1);
58+
assert_eq!(rest.count(), 0);
59+
}
60+
let (first, rest) = iterator_split(a.iter(), 1);
61+
assert_eq!(first.count(), 1);
62+
assert_eq!(rest.count(), 0);
63+
let a = &["foo", "bar", "baz", "blah", "other"];
64+
let (first, rest) = iterator_split(a.iter(), 2);
65+
assert_eq!(first.count(), 2);
66+
assert_eq!(rest.count(), 3);
67+
}
68+
69+
#[test]
70+
fn test_split_empty_iterator() {
71+
let a: &[&str] = &[];
72+
for v in [0, 1, 5] {
73+
assert!(iterator_split_nonempty_rest_count(a.iter(), v).is_none());
74+
}
75+
}
76+
77+
#[test]
78+
fn test_split_nonempty_iterator() {
79+
let a = &["foo"];
80+
81+
let Some((elts, 1)) = iterator_split_nonempty_rest_count(a.iter(), 0) else {
82+
panic!()
83+
};
84+
assert_eq!(elts.count(), 0);
85+
86+
let Some((elts, 0)) = iterator_split_nonempty_rest_count(a.iter(), 1) else {
87+
panic!()
88+
};
89+
assert_eq!(elts.count(), 1);
90+
91+
let Some((elts, 0)) = iterator_split_nonempty_rest_count(a.iter(), 5) else {
92+
panic!()
93+
};
94+
assert_eq!(elts.count(), 1);
95+
96+
let a = &["foo", "bar", "baz", "blah", "other"];
97+
let Some((elts, 3)) = iterator_split_nonempty_rest_count(a.iter(), 2) else {
98+
panic!()
99+
};
100+
assert_eq!(elts.count(), 2);
101+
}
102+
}

0 commit comments

Comments
 (0)