Can't copy more that one file to $out in pkgs.runCommand (Permission denied)

foo = pkgs.writeTextDir "foo" "foo";
bar = pkgs.writeTextDir "bar" "bar";
baz = pkgs.runCommand "baz" {} ''
  mkdir $out
  cp -a ${foo}/. $out
  cp -a ${bar}/. $out
'';

Trying to build baz, I get the following error:

builder for '/nix/store/fq1a7km4cd7nqgry1zjsxgg6hps507wl-baz.drv' failed with exit code 1; last 1 log lines:
  cp: cannot create regular file '/nix/store/325c0jnxhbjha333bqfrcksiwkv5i059-baz/./bar': Permission denied

Weirdly, copying foo to $out went fine:

$ ls /nix/store/325c0jnxhbjha333bqfrcksiwkv5i059-baz
foo

This confuses me: why should the copying only be allowed once? Is there a good reason for this restriction or could this be a bug in nix(pkgs)? Thanks!

1 Like

That is just how cp -a works – it will preserve permissions of the . directory being copied. Try running ls -la $out before the first cp and after:

total 8
drwxr-xr-x  2 nixbld nixbld 4096 Mar  4 22:27 .
drwxrwxr-t 31 nixbld nixbld 4096 Mar  4 22:27 ..
total 12
dr-xr-xr-x  2 nixbld nixbld 4096 Jan  1  1970 .
drwxrwxr-t 31 nixbld nixbld 4096 Mar  4 22:27 ..
-r--r--r--  1 nixbld nixbld    3 Jan  1  1970 foo

Notice the write bit being removed.

If you use cp -r then it will not overwrite the permissions.

1 Like

Ah, that makes sense. Thank you!