diff --git a/rust/src/composepost.rs b/rust/src/composepost.rs
index dd66870385..ded47e3957 100644
--- a/rust/src/composepost.rs
+++ b/rust/src/composepost.rs
@@ -17,11 +17,66 @@
*/
use openat;
+use std::{io, fs};
+use std::io::{Write, BufRead};
+use std::path::Path;
use failure::Fallible;
+// IMO should propose this at least in a "utils" bit of the openat crate;
+// Like 95% of the time I'm looking at errno (with files) it's for ENOENT,
+// and Rust has an elegant way to map that with Option<>. Every other
+// error I usually just want to propagate back up.
+fn openat_optional
(d: &openat::Dir, p: P, f: F) -> io::Result>
+ where P: openat::AsPath, F: FnOnce(&openat::Dir, P) -> io::Result
+{
+ match f(d, p) {
+ Ok(f) => Ok(Some(f)),
+ Err(e) => {
+ if e.kind() == io::ErrorKind::NotFound {
+ Ok(None)
+ } else {
+ Err(e)
+ }
+ }
+ }
+}
+
+// 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
+// that `~` shows up as expected in shells, etc.
+//
+// https://github.com/coreos/fedora-coreos-config/pull/18
+// https://pagure.io/workstation-ostree-config/pull-request/121
+// https://discussion.fedoraproject.org/t/adapting-user-home-in-etc-passwd/487/6
+// https://github.com/justjanne/powerline-go/issues/94
+fn postprocess_useradd(rootfs_dfd: &openat::Dir) -> Fallible<()>
+{
+ let path = Path::new("usr/etc/default/useradd");
+ if let Some(f) = openat_optional(rootfs_dfd, path, openat::Dir::open_file)? {
+ let mut f = io::BufReader::new(f);
+ let o = rootfs_dfd.new_unnamed_file(0644)?;
+ 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())?;
+ }
+ bufw.write("\n".as_bytes())?;
+ }
+ bufw.flush()?;
+ rootfs_dfd.remove_file(path)?;
+ rootfs_dfd.link_file_at(&o, path)?;
+ }
+ Ok(())
+}
+
// This function is called from rpmostree_postprocess_final(); think of
// it as the bits of that function that we've chosen to implement in Rust.
-fn compose_postprocess_final(_rootfs_dfd: &openat::Dir) -> Fallible<()> {
+fn compose_postprocess_final(rootfs_dfd: &openat::Dir) -> Fallible<()> {
+ postprocess_useradd(rootfs_dfd)?;
Ok(())
}
diff --git a/tests/compose-tests/libbasic-test.sh b/tests/compose-tests/libbasic-test.sh
index 3866b0b68d..11e8dae863 100644
--- a/tests/compose-tests/libbasic-test.sh
+++ b/tests/compose-tests/libbasic-test.sh
@@ -19,6 +19,11 @@ validate_passwd() {
validate_passwd passwd
validate_passwd group
+
+ostree --repo=${repobuild} cat ${treeref} /usr/etc/default/useradd > useradd.txt
+assert_file_has_content_literal useradd.txt HOME=/var/home
+echo "ok etc/default/useradd"
+
for path in /usr/share/rpm /usr/lib/sysimage/rpm-ostree-base-db; do
ostree --repo=${repobuild} ls -R ${treeref} ${path} > db.txt
assert_file_has_content_literal db.txt /Packages