Created new derivation based on this: https://github.com/scawp/Steam-Deck.Mount-External-Drive/
This commit is contained in:
parent
6f65c57314
commit
fc3384472d
|
@ -78,14 +78,14 @@
|
||||||
ungoogled-chromium
|
ungoogled-chromium
|
||||||
];
|
];
|
||||||
|
|
||||||
# Automount services for user
|
# # Automount services for user
|
||||||
programs.bashmount.enable = true;
|
# programs.bashmount.enable = true;
|
||||||
services.udiskie = {
|
# services.udiskie = {
|
||||||
enable = true;
|
# enable = true;
|
||||||
automount = true;
|
# automount = true;
|
||||||
notify = false;
|
# notify = false;
|
||||||
tray = "never";
|
# tray = "never";
|
||||||
};
|
# };
|
||||||
|
|
||||||
# Enable home-manager and git
|
# Enable home-manager and git
|
||||||
programs.home-manager.enable = true;
|
programs.home-manager.enable = true;
|
||||||
|
|
30
nixos/hosts/shodan/auto-mount.nix
Normal file
30
nixos/hosts/shodan/auto-mount.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
services.udev.extraRules = ''
|
||||||
|
KERNEL=="sd[a-z]|sd[a-z][0-9]", ACTION=="add", RUN+="/bin/systemctl start --no-block external-drive-mount@%k.service"
|
||||||
|
KERNEL=="sd[a-z]|sd[a-z][0-9]", ACTION=="remove", RUN+="/bin/systemctl stop --no-block external-drive-mount@%k.service"
|
||||||
|
KERNEL=="mmcblk0|mmcblk0p[0-9]", ACTION=="add", RUN+="/bin/systemctl start --no-block external-drive-mount@%k.service"
|
||||||
|
KERNEL=="mmcblk0|mmcblk0p[0-9]", ACTION=="remove", RUN+="/bin/systemctl stop --no-block external-drive-mount@%k.service"
|
||||||
|
KERNEL=="nvme0n1p9|nvme0n1p1[0-9]", ACTION=="add", RUN+="/bin/systemctl start --no-block external-drive-mount@%k.service"
|
||||||
|
KERNEL=="nvme0n1p9|nvme0n1p1[0-9]", ACTION=="remove", RUN+="/bin/systemctl stop --no-block external-drive-mount@%k.service"
|
||||||
|
'';
|
||||||
|
systemd.services.auto-mount = {
|
||||||
|
enable = true;
|
||||||
|
description = "Mount External Drive on %i";
|
||||||
|
unitConfig = {
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "/run/current-system/sw/bin/automount add %i";
|
||||||
|
ExecStop = "/run/current-system/sw/bin/automount remove %i";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
};
|
||||||
|
}
|
233
pkgs/auto-mount/default.nix
Normal file
233
pkgs/auto-mount/default.nix
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
direnv,
|
||||||
|
writeShellApplication,
|
||||||
|
}:
|
||||||
|
writeShellApplication
|
||||||
|
{
|
||||||
|
name = "auto-mount";
|
||||||
|
|
||||||
|
runtimeInputs = [];
|
||||||
|
|
||||||
|
text = ''
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Originally from https://serverfault.com/a/767079
|
||||||
|
|
||||||
|
# This script is called from our systemd unit file to mount or unmount
|
||||||
|
# a USB drive.
|
||||||
|
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
echo "Usage: $0 {add|remove} device_name (e.g. sdb1)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $# -ne 2 ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
ACTION=$1
|
||||||
|
DEVBASE=$2
|
||||||
|
DEVICE="/dev/''${DEVBASE}"
|
||||||
|
|
||||||
|
# Shared between this and the auto-mount script to ensure we're not double-triggering nor automounting while formatting
|
||||||
|
# or vice-versa.
|
||||||
|
MOUNT_LOCK="/var/run/jupiter-automount-''${DEVBASE//\/_}.lock"
|
||||||
|
|
||||||
|
# Obtain lock
|
||||||
|
exec 9<>"$MOUNT_LOCK"
|
||||||
|
if ! flock -n 9; then
|
||||||
|
echo "$MOUNT_LOCK is active: ignoring action $ACTION"
|
||||||
|
# Do not return a success exit code: it could end up putting the service in 'started' state without doing the mount
|
||||||
|
# work (further start commands will be ignored after that)
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wait N seconds for steam
|
||||||
|
wait_steam()
|
||||||
|
{
|
||||||
|
local i=0
|
||||||
|
local wait=$1
|
||||||
|
echo "Waiting up to $wait seconds for steam to load"
|
||||||
|
while ! pgrep -x steamwebhelper &>/dev/null && (( i++ < wait )); do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
send_steam_url()
|
||||||
|
{
|
||||||
|
local command="$1"
|
||||||
|
local arg="$2"
|
||||||
|
local encoded=$(urlencode "$arg")
|
||||||
|
if pgrep -x "steam" > /dev/null; then
|
||||||
|
# TODO use -ifrunning and check return value - if there was a steam process and it returns -1, the message wasn't sent
|
||||||
|
# need to retry until either steam process is gone or -ifrunning returns 0, or timeout i guess
|
||||||
|
systemd-run -M 1000@ --user --collect --wait sh -c "./.steam/root/ubuntu12_32/steam steam://''${command}/''${encoded@Q}"
|
||||||
|
echo "Sent URL to steam: steam://''${command}/''${arg} (steam://''${command}/''${encoded})"
|
||||||
|
else
|
||||||
|
echo "Could not send steam URL steam://''${command}/''${arg} (steam://''${command}/''${encoded}) -- steam not running"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# From https://gist.github.com/HazCod/da9ec610c3d50ebff7dd5e7cac76de05
|
||||||
|
urlencode()
|
||||||
|
{
|
||||||
|
[ -z "$1" ] || echo -n "$@" | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%\1/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
do_mount()
|
||||||
|
{
|
||||||
|
declare -i ret
|
||||||
|
# NOTE: these values are ABI, since they are sent to the Steam client
|
||||||
|
readonly FSCK_ERROR=1
|
||||||
|
readonly MOUNT_ERROR=2
|
||||||
|
|
||||||
|
# Get info for this drive: $ID_FS_LABEL, and $ID_FS_TYPE
|
||||||
|
dev_json=$(lsblk -o PATH,LABEL,FSTYPE --json -- "$DEVICE" | jq '.blockdevices[0]')
|
||||||
|
ID_FS_LABEL=$(jq -r '.label | select(type == "string")' <<< "$dev_json")
|
||||||
|
ID_FS_TYPE=$(jq -r '.fstype | select(type == "string")' <<< "$dev_json")
|
||||||
|
|
||||||
|
# Global mount options
|
||||||
|
OPTS="rw,noatime"
|
||||||
|
|
||||||
|
# File system type specific mount options
|
||||||
|
#if [[ ''${ID_FS_TYPE} == "vfat" ]]; then
|
||||||
|
# OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush"
|
||||||
|
#fi
|
||||||
|
|
||||||
|
case "''${ID_FS_TYPE}" in
|
||||||
|
"ntfs")
|
||||||
|
echo "FSType is NTFS"
|
||||||
|
#Extra Opts don't seem necessary anymore? add if required
|
||||||
|
#OPTS+=""
|
||||||
|
;;
|
||||||
|
"exfat")
|
||||||
|
echo "FSType is exFat"
|
||||||
|
#OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush"
|
||||||
|
;;
|
||||||
|
"btrfs")
|
||||||
|
echo "FSType is btrfs"
|
||||||
|
;;
|
||||||
|
"ext4")
|
||||||
|
echo "FSType is ext4"
|
||||||
|
#exit 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error mounting ''${DEVICE}: unsupported fstype: ''${ID_FS_TYPE} - ''${dev_json}"
|
||||||
|
rm "''${MOUNT_LOCK}"
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Prior to talking to udisks, we need all udev hooks (we were started by one) to finish, so we know it has knowledge
|
||||||
|
# of the drive. Our own rule starts us as a service with --no-block, so we can wait for rules to settle here
|
||||||
|
# safely.
|
||||||
|
#if ! udevadm settle; then
|
||||||
|
# echo "Failed to wait for \`udevadm settle\`"
|
||||||
|
# exit 1
|
||||||
|
#fi
|
||||||
|
|
||||||
|
# Ask udisks to auto-mount. This needs a version of udisks that supports the 'as-user' option.
|
||||||
|
ret=0
|
||||||
|
reply=$(busctl call --allow-interactive-authorization=false --expect-reply=true --json=short \
|
||||||
|
org.freedesktop.UDisks2 \
|
||||||
|
/org/freedesktop/UDisks2/block_devices/"''${DEVBASE}" \
|
||||||
|
org.freedesktop.UDisks2.Filesystem \
|
||||||
|
Mount 'a{sv}' 3 \
|
||||||
|
as-user s lillian \
|
||||||
|
auth.no_user_interaction b true \
|
||||||
|
options s "$OPTS") || ret=$?
|
||||||
|
|
||||||
|
if (( ret != 0 )); then
|
||||||
|
send_steam_url "system/devicemountresult" "''${DEVBASE}/''${MOUNT_ERROR}"
|
||||||
|
echo "Error mounting ''${DEVICE} (status = $ret)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Expected reply is of the format
|
||||||
|
# {"type":"s","data":["/run/media/lillian/home"]}
|
||||||
|
mount_point=$(jq -r '.data[0] | select(type == "string")' <<< "$reply" || true)
|
||||||
|
if [[ -z $mount_point ]]; then
|
||||||
|
echo "Error when mounting ''${DEVICE}: udisks returned success but could not parse reply:"
|
||||||
|
echo "---"$'\n'"$reply"$'\n'"---"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ''${ID_FS_TYPE} == "exfat" ]]; then
|
||||||
|
echo "exFat does not support symlinks, do not add library to Steam"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a symlink from /run/media to keep compatibility with apps
|
||||||
|
# that use the older mount point (for SD cards only).
|
||||||
|
case "''${DEVBASE}" in
|
||||||
|
mmcblk0p*)
|
||||||
|
if [[ -z "''${ID_FS_LABEL}" ]]; then
|
||||||
|
old_mount_point="/run/media/''${DEVBASE}"
|
||||||
|
else
|
||||||
|
old_mount_point="/run/media/''${mount_point##*/}"
|
||||||
|
fi
|
||||||
|
if [[ ! -d "''${old_mount_point}" ]]; then
|
||||||
|
rm -f -- "''${old_mount_point}"
|
||||||
|
ln -s -- "''${mount_point}" "''${old_mount_point}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "**** Mounted ''${DEVICE} at ''${mount_point} ****"
|
||||||
|
|
||||||
|
if [ -f "''${mount_point}/libraryfolder.vdf" ]; then
|
||||||
|
send_steam_url "addlibraryfolder" "''${mount_point}"
|
||||||
|
else
|
||||||
|
#TODO check permissions are 1000 when creating new SteamLibrary
|
||||||
|
mkdir -p "''${mount_point}/SteamLibrary"
|
||||||
|
chown lillian:lillian "''${mount_point}/SteamLibrary"
|
||||||
|
send_steam_url "addlibraryfolder" "''${mount_point}/SteamLibrary"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
do_unmount()
|
||||||
|
{
|
||||||
|
local mount_point=$(findmnt -fno TARGET "''${DEVICE}" || true)
|
||||||
|
if [[ -n $mount_point ]]; then
|
||||||
|
# Remove symlink to the mount point that we're unmounting
|
||||||
|
find /run/media -maxdepth 1 -xdev -type l -lname "''${mount_point}" -exec rm -- {} \;
|
||||||
|
else
|
||||||
|
# If we don't know the mount point then remove all broken symlinks
|
||||||
|
find /run/media -maxdepth 1 -xdev -xtype l -exec rm -- {} \;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
do_retrigger()
|
||||||
|
{
|
||||||
|
local mount_point=$(findmnt -fno TARGET "''${DEVICE}" || true)
|
||||||
|
[[ -n $mount_point ]] || return 0
|
||||||
|
|
||||||
|
# In retrigger mode, we want to wait a bit for steam as the common pattern is starting in parallel with a retrigger
|
||||||
|
wait_steam 10
|
||||||
|
# This is a truly gnarly way to ensure steam is ready for commands.
|
||||||
|
# TODO literally anything else
|
||||||
|
sleep 6
|
||||||
|
send_steam_url "addlibraryfolder" "''${mount_point}"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "''${ACTION}" in
|
||||||
|
add)
|
||||||
|
do_mount
|
||||||
|
;;
|
||||||
|
remove)
|
||||||
|
do_unmount
|
||||||
|
;;
|
||||||
|
retrigger)
|
||||||
|
do_retrigger
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
'';
|
||||||
|
}
|
|
@ -11,4 +11,5 @@ pkgs: {
|
||||||
update = pkgs.callPackage ./update {};
|
update = pkgs.callPackage ./update {};
|
||||||
upgrade = pkgs.callPackage ./upgrade {};
|
upgrade = pkgs.callPackage ./upgrade {};
|
||||||
restart = pkgs.callPackage ./restart {};
|
restart = pkgs.callPackage ./restart {};
|
||||||
|
auto-mount = pkgs.callPackage ./auto-mount {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue