about summary refs log tree commit diff
path: root/nixos/lib
diff options
context:
space:
mode:
authorLéo Gaspard2020-12-21 19:58:49 +0100
committerGitHub2020-12-21 19:58:49 +0100
commita5a819e059ae7db805e0a5cc038bb6510be099ad (patch)
treeaa02dd8181834f84184db8bff560e836d8ab779a /nixos/lib
parent8aaf788e34e2c782a73935f14626ccc78238551e (diff)
parent8e5219372161d4d1d122cc86b9ac0c52dbf7daf8 (diff)
Merge pull request #104292 from fgaz/image-contents
nixos/lib/make-disk-image.nix: support content mode and ownership
Diffstat (limited to 'nixos/lib')
-rw-r--r--nixos/lib/make-disk-image.nix48
1 files changed, 43 insertions, 5 deletions
diff --git a/nixos/lib/make-disk-image.nix b/nixos/lib/make-disk-image.nix
index 0ad0cf1fef5a..3f50bb431c5e 100644
--- a/nixos/lib/make-disk-image.nix
+++ b/nixos/lib/make-disk-image.nix
@@ -18,9 +18,13 @@
   bootSize ? "256M"
 
 , # The files and directories to be placed in the target file system.
-  # This is a list of attribute sets {source, target} where `source'
-  # is the file system object (regular file or directory) to be
-  # grafted in the file system at path `target'.
+  # This is a list of attribute sets {source, target, mode, user, group} where
+  # `source' is the file system object (regular file or directory) to be
+  # grafted in the file system at path `target', `mode' is a string containing
+  # the permissions that will be set (ex. "755"), `user' and `group' are the
+  # user and group name that will be set as owner of the files.
+  # `mode', `user', and `group' are optional.
+  # When setting one of `user' or `group', the other needs to be set too.
   contents ? []
 
 , # Type of partition table to use; either "legacy", "efi", or "none".
@@ -60,6 +64,11 @@
 assert partitionTableType == "legacy" || partitionTableType == "legacy+gpt" || partitionTableType == "efi" || partitionTableType == "hybrid" || partitionTableType == "none";
 # We use -E offset=X below, which is only supported by e2fsprogs
 assert partitionTableType != "none" -> fsType == "ext4";
+# Either both or none of {user,group} need to be set
+assert lib.all
+         (attrs: ((attrs.user  or null) == null)
+              == ((attrs.group or null) == null))
+         contents;
 
 with lib;
 
@@ -148,6 +157,9 @@ let format' = format; in let
   # !!! should use XML.
   sources = map (x: x.source) contents;
   targets = map (x: x.target) contents;
+  modes   = map (x: x.mode  or "''") contents;
+  users   = map (x: x.user  or "''") contents;
+  groups  = map (x: x.group or "''") contents;
 
   closureInfo = pkgs.closureInfo { rootPaths = [ config.system.build.toplevel channelSources ]; };
 
@@ -174,22 +186,33 @@ let format' = format; in let
     set -f
     sources_=(${concatStringsSep " " sources})
     targets_=(${concatStringsSep " " targets})
+    modes_=(${concatStringsSep " " modes})
     set +f
 
     for ((i = 0; i < ''${#targets_[@]}; i++)); do
       source="''${sources_[$i]}"
       target="''${targets_[$i]}"
+      mode="''${modes_[$i]}"
 
+      if [ -n "$mode" ]; then
+        rsync_chmod_flags="--chmod=$mode"
+      else
+        rsync_chmod_flags=""
+      fi
+      # Unfortunately cptofs only supports modes, not ownership, so we can't use
+      # rsync's --chown option. Instead, we change the ownerships in the
+      # VM script with chown.
+      rsync_flags="-a --no-o --no-g $rsync_chmod_flags"
       if [[ "$source" =~ '*' ]]; then
         # If the source name contains '*', perform globbing.
         mkdir -p $root/$target
         for fn in $source; do
-          rsync -a --no-o --no-g "$fn" $root/$target/
+          rsync $rsync_flags "$fn" $root/$target/
         done
       else
         mkdir -p $root/$(dirname $target)
         if ! [ -e $root/$target ]; then
-          rsync -a --no-o --no-g $source $root/$target
+          rsync $rsync_flags $source $root/$target
         else
           echo "duplicate entry $target -> $source"
           exit 1
@@ -284,6 +307,21 @@ in pkgs.vmTools.runInLinuxVM (
       # The above scripts will generate a random machine-id and we don't want to bake a single ID into all our images
       rm -f $mountPoint/etc/machine-id
 
+      # Set the ownerships of the contents. The modes are set in preVM.
+      # No globbing on targets, so no need to set -f
+      targets_=(${concatStringsSep " " targets})
+      users_=(${concatStringsSep " " users})
+      groups_=(${concatStringsSep " " groups})
+      for ((i = 0; i < ''${#targets_[@]}; i++)); do
+        target="''${targets_[$i]}"
+        user="''${users_[$i]}"
+        group="''${groups_[$i]}"
+        if [ -n "$user$group" ]; then
+          # We have to nixos-enter since we need to use the user and group of the VM
+          nixos-enter --root $mountPoint -- chown -R "$user:$group" "$target"
+        fi
+      done
+
       umount -R /mnt
 
       # Make sure resize2fs works. Note that resize2fs has stricter criteria for resizing than a normal