Skip to content

Commit

Permalink
Allow for symlinking files
Browse files Browse the repository at this point in the history
Signed-off-by: magic_rb <[email protected]>
  • Loading branch information
MagicRB committed Oct 21, 2023
1 parent 0f317c2 commit 1e7f9de
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 18 deletions.
36 changes: 23 additions & 13 deletions mount-file.bash
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ shopt -s inherit_errexit # Inherit the errexit option status in subshells.
trap 'echo Error when executing ${BASH_COMMAND} at line ${LINENO}! >&2' ERR

# Get inputs from command line arguments
if [[ "$#" != 3 ]]; then
if [[ "$#" != 4 ]]; then
echo "Error: 'mount-file.bash' requires *three* args." >&2
exit 1
fi

mountPoint="$1"
targetFile="$2"
debug="$3"
method="$4"

trace() {
if (( "$debug" )); then
Expand All @@ -28,16 +29,25 @@ if (( "$debug" )); then
set -o xtrace
fi

if [[ -L "$mountPoint" && $(readlink -f "$mountPoint") == "$targetFile" ]]; then
trace "$mountPoint already links to $targetFile, ignoring"
elif mount | grep -F "$mountPoint"' ' >/dev/null && ! mount | grep -F "$mountPoint"/ >/dev/null; then
trace "mount already exists at $mountPoint, ignoring"
elif [[ -e "$mountPoint" ]]; then
echo "A file already exists at $mountPoint!" >&2
exit 1
elif [[ -e "$targetFile" ]]; then
touch "$mountPoint"
mount -o bind "$targetFile" "$mountPoint"
else
ln -s "$targetFile" "$mountPoint"
if [[ "$method" == "bind" ]]; then
if [[ -L "$mountPoint" && $(readlink -f "$mountPoint") == "$targetFile" ]]; then
trace "$mountPoint already links to $targetFile, ignoring"
elif mount | grep -F "$mountPoint"' ' >/dev/null && ! mount | grep -F "$mountPoint"/ >/dev/null; then
trace "mount already exists at $mountPoint, ignoring"
elif [[ -e "$mountPoint" ]]; then
echo "A file already exists at $mountPoint!" >&2
exit 1
elif [[ -e "$targetFile" ]]; then
touch "$mountPoint"
mount -o bind "$targetFile" "$mountPoint"
else
ln -s "$targetFile" "$mountPoint"
fi
elif [[ "$method" == "symlink" ]]; then
if [[ -e "$mountPoint" ]] && ! [[ -L "$mountPoint" ]]; then
echo "symlink requested, but something else than symlink is present at $mountPoint"
exit 1
else
ln -sf "$targetFile" "$mountPoint"
fi
fi
26 changes: 21 additions & 5 deletions nixos.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ let
parentsOf
;

isSymlink = entry:
entry.method == "symlink";
isBind = entry:
entry.method == "bind";

cfg = config.environment.persistence;
users = config.users.users;
allPersistentStoragePaths = { directories = [ ]; files = [ ]; users = [ ]; }
Expand All @@ -64,7 +69,7 @@ let

# Create all fileSystems bind mount entries for a specific
# persistent storage path.
bindMounts = listToAttrs (map mkBindMountNameValuePair directories);
bindMounts = listToAttrs (map mkBindMountNameValuePair (filter isBind directories));
in
{
options = {
Expand All @@ -83,6 +88,7 @@ in
either
str
coercedTo
enum
;
in
attrsOf (
Expand All @@ -96,6 +102,13 @@ in
};
commonOpts = {
options = {
method = mkOption {
type = enum [ "bind" "symlink" ];
default = "bind";
description = ''
Whether to use a bind mount or a plain symlink to persist this.
'';
};
persistentStoragePath = mkOption {
type = path;
default = cfg.${name}.persistentStoragePath;
Expand Down Expand Up @@ -477,7 +490,7 @@ in
config = {
systemd.services =
let
mkPersistFileService = { filePath, persistentStoragePath, enableDebugging, ... }:
mkPersistFileService = { filePath, persistentStoragePath, enableDebugging, method, ... }:
let
targetFile = escapeShellArg (concatPaths [ persistentStoragePath filePath ]);
mountPoint = escapeShellArg filePath;
Expand All @@ -492,7 +505,7 @@ in
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${mountFile} ${mountPoint} ${targetFile} ${escapeShellArg enableDebugging}";
ExecStart = "${mountFile} ${mountPoint} ${targetFile} ${escapeShellArg enableDebugging} ${escapeShellArg method}";
ExecStop = pkgs.writeShellScript "unbindOrUnlink-${sanitizeName targetFile}" ''
set -eu
if [[ -L ${mountPoint} ]]; then
Expand All @@ -505,8 +518,10 @@ in
};
};
};
mkPersistDirectoryService = { dirPath, ... }@args:
mkPersistFileService (args // { filePath = dirPath; });
in
foldl' recursiveUpdate { } (map mkPersistFileService files);
foldl' recursiveUpdate { } ((map mkPersistFileService files) ++ (map mkPersistDirectoryService (filter isSymlink directories)));

fileSystems = bindMounts;
# So the mounts still make it into a VM built from `system.build.vm`
Expand Down Expand Up @@ -639,14 +654,15 @@ in
exit $_status
'';

mkPersistFile = { filePath, persistentStoragePath, enableDebugging, ... }:
mkPersistFile = { filePath, persistentStoragePath, enableDebugging, method, ... }:
let
mountPoint = filePath;
targetFile = concatPaths [ persistentStoragePath filePath ];
args = escapeShellArgs [
mountPoint
targetFile
enableDebugging
method
];
in
''
Expand Down

0 comments on commit 1e7f9de

Please sign in to comment.