diff --git a/pkgs/os-specific/linux/shadow/default.nix b/pkgs/os-specific/linux/shadow/default.nix index 1055fccd8aa..af579920ec7 100644 --- a/pkgs/os-specific/linux/shadow/default.nix +++ b/pkgs/os-specific/linux/shadow/default.nix @@ -24,7 +24,19 @@ stdenv.mkDerivation rec { buildInputs = stdenv.lib.optional (pam != null && stdenv.isLinux) pam; - patches = [ ./keep-path.patch dots_in_usernames ]; + patches = [ ./keep-path.patch dots_in_usernames + /* nixos managed /etc[/skel] files are symlinks pointing to /etc/static[/skel] + * thus useradd will create symlinks ~/.bashrc. This patch fixes it: If a file + * should be copied to user's home directory and it points to /etc/static + * the target of the symbolic link is copied instead. + * This is only one way to fix it. The alternative would be making nixos + * create files in /etc/skel and keep some state around so that it knows + * which files it put there so that it can remove them itself. This more + * complicated approach would pay off if multiple apps woulb be using + * /etc/skel + */ + ./etc-copy-etc-satic-target.patch + ]; # Assume System V `setpgrp (void)', which is the default on GNU variants # (`AC_FUNC_SETPGRP' is not cross-compilation capable.) diff --git a/pkgs/os-specific/linux/shadow/etc-copy-etc-satic-target.patch b/pkgs/os-specific/linux/shadow/etc-copy-etc-satic-target.patch new file mode 100644 index 00000000000..3520ab20957 --- /dev/null +++ b/pkgs/os-specific/linux/shadow/etc-copy-etc-satic-target.patch @@ -0,0 +1,32 @@ +diff --git a/libmisc/copydir.c b/libmisc/copydir.c +index fac585c..ddf3788 100644 +--- a/libmisc/copydir.c ++++ b/libmisc/copydir.c +@@ -490,6 +490,27 @@ static int copy_symlink (const char *src, const char *dst, + if (NULL == oldlink) { + return -1; + } ++ ++ /* NixOS hack: if the link points to a file in /etc/static/ this ++ * means the file is managed by nix and probably its meant to be a ++ * file. So derefence once more until the original store path (real file) ++ * is found*/ ++ ++ ++ if (strncmp (oldlink, "/etc/static/", strlen ("/etc/static/")) == 0) { ++ char *target = readlink_malloc (oldlink); ++ free (oldlink); ++ int r = copy_entry(target, dst, reset_selinux, old_uid, new_uid, old_gid, new_gid); ++ ++ /* make writeable by user */ ++ struct stat s; ++ stat(dst, &s); ++ s.st_mode |= S_IWUSR; // u+w ++ chmod(dst, s.st_mode); // not minding higher bits because chmod (coreutils) doesn't either ++ ++ free (target); ++ return r; ++ } + + /* If src was a link to an entry of the src_orig directory itself, + * create a link to the corresponding entry in the dst_orig