Skip to content

Commit

Permalink
Fix tmpfiles.d symlinking
Browse files Browse the repository at this point in the history
This makes nix-ld and opengl-driver work
  • Loading branch information
pinkwah committed Jun 20, 2023
1 parent 98a7d1b commit 26e6708
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn data_dir() -> Option<PathBuf> {
fn current_system_dir() -> Option<PathBuf> {
let datadir = data_dir()?.join("root");
if datadir.symlink_metadata().is_ok() {
Some(datadir.join("sw/bin"))
Some(datadir)
} else {
None
}
Expand Down Expand Up @@ -79,7 +79,7 @@ impl Config {
match current_system.clone() {
Some(x) => {
let mut os: OsString = x.into_os_string();
os.push(":/usr/bin:/bin");
os.push("/sw/bin:/usr/bin:/bin");
os
}
None => OsString::from("/usr/local/bin:/usr/bin:/bin"),
Expand Down
33 changes: 27 additions & 6 deletions src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,23 @@ pub fn setup(config: &Config) {

if let Some(nix_profile_dir) = &config.nix_profile {
bind_nix_profile(&config.chroot_dir, &config.nix_home, config.nixbox_root());
bind_tmpfiles(nix_profile_dir);
bind_tmpfiles(
&config.chroot_dir,
&config.nix_home,
&nix_profile_dir.join("lib/tmpfiles.d"),
);

if let Some(current_system) = &config.current_system {
bind_tmpfiles(current_system);
bind_tmpfiles(
&config.chroot_dir,
&config.nix_home,
&current_system.join("lib/tmpfiles.d"),
);
bind_tmpfiles(
&config.chroot_dir,
&config.nix_home,
&current_system.join("etc/tmpfiles.d"),
);
}
} else {
bind_host(&config.chroot_dir);
Expand Down Expand Up @@ -188,11 +201,16 @@ fn bind_common(nix_dir: &Path, chroot_dir: &Path) {
}
}

fn bind_tmpfiles(path: &Path) {
let Ok(dir) = fs::read_dir(path.join("lib/tmpfiles.d")) else { return; };
fn bind_tmpfiles(chroot_dir: &Path, nix_dir: &Path, path: &Path) {
println!("try read {:?}", path);
let Ok(path) = resolve_symlink(&(&Path::new("/nix"), &nix_dir), path) else { return; };
println!("+++ read {:?}", path);
let Ok(dir) = fs::read_dir(path) else { return; };
println!("read {:?}", dir);

for entry in dir {
let path = entry.unwrap().path();
let Ok(path) = resolve_symlink(&(&Path::new("/nix"), &nix_dir), path) else { continue; };
if !path.is_file() {
continue;
}
Expand All @@ -203,8 +221,11 @@ fn bind_tmpfiles(path: &Path) {
let line = line.unwrap();
let vec = line.split_ascii_whitespace().collect::<Vec<_>>();
if let ["L+", target, "-", "-", "-", "-", source] = vec.as_slice() {
fs::create_dir_all(Path::new(target).parent().unwrap_or(Path::new("/"))).unwrap();
create_symlink(Path::new(source), Path::new(target));
let Some(target) = target.strip_prefix('/') else { continue; };
let target = chroot_dir.join(target);
println!("{:?} -> {:?}", source, target);
fs::create_dir_all(target.parent().unwrap_or(Path::new("/"))).unwrap();
create_symlink(Path::new(source), &target);
}
}
}
Expand Down
34 changes: 32 additions & 2 deletions src/util/resolve_symlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn resolve_symlink(
current_dir()?.join(path)
};

loop {
'_loop: loop {
if path.symlink_metadata().is_err() {
for parent in path.ancestors().skip(1) {
if !parent.is_symlink() {
Expand All @@ -25,7 +25,7 @@ pub fn resolve_symlink(

let resolved = resolve_symlink(mapping, parent)?;
path = resolved.join(path.strip_prefix(parent).unwrap());
break;
continue '_loop;
}
}

Expand Down Expand Up @@ -108,6 +108,36 @@ mod tests {
assert_eq!(expect, actual);
}

#[test]
fn it_resolves_nested() {
let path: PathBuf = testdir!();
let expect = path.join("file");

File::create(&expect).unwrap();

// 'dir1/dir2' -> 'dir2'
fs::create_dir(path.join("dir1")).unwrap();
symlink("/fake-directory/dir2", path.join("dir1/dir2")).unwrap();

// 'dir2/dir3' -> 'dir3'
fs::create_dir(path.join("dir2")).unwrap();
symlink("/fake-directory/dir3", path.join("dir2/dir3")).unwrap();

// 'dir3/file' -> 'file'
fs::create_dir(path.join("dir3")).unwrap();
symlink("/fake-directory/file", path.join("dir3/file")).unwrap();

// Cannot resolve symlink
assert!(path.join("dir1/dir2/dir3/file").canonicalize().is_err());

let actual = resolve_symlink(
&("/fake-directory", &path),
&path.join("dir1/dir2/dir3/file"),
)
.unwrap();
assert_eq!(expect, actual);
}

#[test]
fn it_errors_when_file_not_found() {
let path: PathBuf = testdir!();
Expand Down

0 comments on commit 26e6708

Please sign in to comment.