mirror of
https://github.com/nix-community/impermanence
synced 2024-11-10 05:44:17 +00:00
b4160ba71d
Construct directory items for all parent directories of the user specified files and directories, assigning better default permissions and ownership to each and removing this responsibility from the create-directories script. This means that all parent directories of root directories will now have the default permissions and ownership, not inherit them from the child. User directories are assigned default user ownership. The home directory itself is handled specially to make sure it is owned by the user, not readable by anyone else and its parent gets default root ownership. To illustrate this with an example, here is a directory specification and the ownership and permissions that could potentially be assigned to the parent directories, given none of them yet exist in persistent storage: environment.persistence."/persistent" = { users.talyz = { directories = [ { directory = ".local/share/secret"; mode = "0500"; } ]; }; }; Before: /home talyz:talyz 0500 /home/talyz talyz:talyz 0500 /home/talyz/.local talyz:talyz 0500 /home/talyz/.local/share talyz:talyz 0500 /home/talyz/.local/share/secret talyz:talyz 0500 After: /home root:root 0755 /home/talyz talyz:talyz 0700 /home/talyz/.local talyz:talyz 0755 /home/talyz/.local/share talyz:talyz 0755 /home/talyz/.local/share/secret talyz:talyz 0500
63 lines
2.4 KiB
Bash
Executable file
63 lines
2.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
set -o nounset # Fail on use of unset variable.
|
|
set -o errexit # Exit on command failure.
|
|
set -o pipefail # Exit on failure of any command in a pipeline.
|
|
set -o errtrace # Trap errors in functions and subshells.
|
|
set -o noglob # Disable filename expansion (globbing),
|
|
# since it could otherwise happen during
|
|
# path splitting.
|
|
shopt -s inherit_errexit # Inherit the errexit option status in subshells.
|
|
|
|
# Print a useful trace when an error occurs
|
|
trap 'echo Error when executing ${BASH_COMMAND} at line ${LINENO}! >&2' ERR
|
|
|
|
# Given a source directory, /source, and a target directory,
|
|
# /target/foo/bar/bazz, we want to "clone" the target structure
|
|
# from source into the target. Essentially, we want both
|
|
# /source/target/foo/bar/bazz and /target/foo/bar/bazz to exist
|
|
# on the filesystem. More concretely, we'd like to map
|
|
# /state/etc/ssh/example.key to /etc/ssh/example.key
|
|
#
|
|
# To achieve this, we split the target's path into parts -- target, foo,
|
|
# bar, bazz -- and iterate over them while accumulating the path
|
|
# (/target/, /target/foo/, /target/foo/bar, and so on); then, for each of
|
|
# these increasingly qualified paths we:
|
|
# 1. Ensure both /source/qualifiedPath and qualifiedPath exist
|
|
# 2. Copy the ownership of the source path to the target path
|
|
# 3. Copy the mode of the source path to the target path
|
|
|
|
# Get inputs from command line arguments
|
|
if [[ "$#" != 6 ]]; then
|
|
printf "Error: 'create-directories.bash' requires *six* args.\n" >&2
|
|
exit 1
|
|
fi
|
|
sourceBase="$1"
|
|
target="$2"
|
|
user="$3"
|
|
group="$4"
|
|
mode="$5"
|
|
debug="$6"
|
|
|
|
if (( "$debug" )); then
|
|
set -o xtrace
|
|
fi
|
|
|
|
# trim trailing slashes the root of all evil
|
|
sourceBase="${sourceBase%/}"
|
|
target="${target%/}"
|
|
|
|
# check that the source exists and warn the user if it doesn't, then
|
|
# create them with the specified permissions
|
|
realSource="$(realpath -m "$sourceBase$target")"
|
|
if [[ ! -d "$realSource" ]]; then
|
|
printf "Warning: Source directory '%s' does not exist; it will be created for you with the following permissions: owner: '%s:%s', mode: '%s'.\n" "$realSource" "$user" "$group" "$mode"
|
|
mkdir --mode="$mode" "$realSource"
|
|
chown "$user:$group" "$realSource"
|
|
fi
|
|
|
|
[[ -d "$target" ]] || mkdir "$target"
|
|
|
|
# synchronize perms between source and target
|
|
chown --reference="$realSource" "$target"
|
|
chmod --reference="$realSource" "$target"
|