usrmnt

A small utility to mount devices from the command line.
git clone https://git.sr.ht/~jbauer/usrmnt
Log | Files | Refs | README | LICENSE

usrmnt (8567B)


      1 #! /bin/bash
      2 # usrmnt -- An easy-to-use wrapper for udisksctl
      3 #
      4 # Copyright (C) 2019  Jake Bauer
      5 #
      6 # This program is free software: you can redistribute it and/or modify
      7 # it under the terms of the GNU General Public License as published by
      8 # the Free Software Foundation, either version 3 of the License, or
      9 # (at your option) any later version.
     10 #
     11 # This program is distributed in the hope that it will be useful,
     12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 # GNU General Public License for more details.
     15 #
     16 # You should have received a copy of the GNU General Public License
     17 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
     18 
     19 set -u
     20 version="1.1.2"
     21 
     22 print_help()
     23 {
     24     printf "\n  Options:
     25       ls – List the currently recognized devices
     26       q  – Exit
     27       v  – Print the current version
     28       ?  – Print this help dialog
     29       <command> <device> – Execute <command> on <device> where <command> is one of:"
     30     printf "\n  Supported udisks Commands:
     31       mount     – Mount a device to a mountpoint in /media. Will prompt to
     32                   unlock encrypted drives.
     33       unmount   – Unmount a device (can also use \"umount\")
     34       lock      – Lock an unlocked encrypted device
     35       unlock    – Unlock an encrypted device without mounting it
     36       info      – Print device info
     37       power-off – Power a device off (computer will stop recognizing it)
     38                   (can also use \"poweroff\")\n"
     39     printf "  Examples:
     40       ()>>> mount sdc1
     41       (sdc1)>>> unmount sdb2
     42       (sdb2)>>> unlock mmcblk0p1\n
     43       The device in parentheses is the device from the previous command.
     44       When there is a device in parentheses, you can type any command without
     45       specifying a device name and that command will act on the device in
     46       parentheses. The device in parentheses is only updated when the previous
     47       command completed successfully except if you are unlocking a device, it
     48       exists, and you get the password wrong in which case it will still update
     49       so you can just type \"unlock\" or \"mount\" again.\n
     50       For example:
     51       (sdb1)>>> unmount
     52       will unmount /dev/sdb1.\n\n"
     53     return 0
     54 }
     55 
     56 print_dev_list()
     57 {
     58     printf "\n  Devices currently recognized by the computer:\n"
     59     lsblk -o TYPE,KNAME,LABEL,SIZE,MODEL,MOUNTPOINT | sed 's/^/    /'
     60     echo ""
     61     return 0
     62 }
     63 
     64 # Takes one parameter: the device to unlock and mount
     65 unlock_and_mount()
     66 {
     67     printf "  "
     68     unlockResult=$(udisksctl unlock -b /dev/"$1" 2>&1)
     69 
     70     tput setaf 1
     71     tput bold
     72     if echo "$unlockResult" | grep -qi "is already unlocked"; then
     73         printf "\n  ERROR: Device is already unlocked."
     74 
     75     elif echo "$unlockResult" | grep -qi "Operation not permitted"; then
     76         printf "\n  ERROR: Incorrect password."
     77 
     78     elif echo "$unlockResult" | grep -qi "is not an encrypted device"; then
     79         printf "\n  ERROR: This is not an encrypted device."
     80 
     81     elif echo "$unlockResult" | grep -qi "UnknownMethod"; then
     82         printf "\n  ERROR: Device appears to have been unplugged."
     83 
     84     else
     85         unlockedDevice=$(echo "$unlockResult" | cut -d' ' -f4 | sed 's/\.//')
     86         previousDevice=$(echo "$unlockedDevice" | cut -d'/' -f3)
     87         retMsg=$(udisksctl mount -b "$unlockedDevice")
     88         return 0
     89     fi
     90     tput sgr0
     91     return 1
     92 }
     93 
     94 # Takes one parameter: the string to check for udisksctl error messages
     95 check_output()
     96 {
     97     # Print error messages in red
     98     tput setaf 1
     99     tput bold
    100 
    101     if echo "$1" | grep -qi "AlreadyMounted"; then
    102         printf "\n  ERROR: The device is already mounted.\n\n"
    103 
    104     elif echo "$1" | grep -qi "NotMounted"; then
    105         printf "\n  ERROR: The device is not mounted.\n\n"
    106 
    107     elif echo "$1" | grep -qi "is not a mountable filesystem"; then
    108         printf "\n  ERROR: This device is not a mountable filesystem.\n\n"
    109 
    110     elif echo "$1" | grep -qi "is not an encrypted device"; then
    111         printf "\n  ERROR: This device is not an encrypted device.\n\n"
    112 
    113     elif echo "$1" | grep -qi "is already unlocked"; then
    114         printf "\n  ERROR: This device is already unlocked.\n\n"
    115 
    116     elif echo "$1" | grep -qi "Operation not permitted"; then
    117         printf "\n  ERROR: Incorrect password.\n\n"
    118 
    119     elif echo "$1" | grep -qi "Error looking up object"; then
    120         printf "\n  ERROR: Could not find object/device.\n\n"
    121 
    122     elif echo "$1" | grep -qi "Error powering off drive"; then
    123         printf "\n  ERROR: Cannot power off the device, device still in use.\n"
    124         printf "  Please unmount (and lock if needed) the partitions still in use.\n\n"
    125 
    126     elif echo "$1" | grep -qi "Error locking"; then
    127         printf "\n  ERROR: Cannot lock the device, device still in use.\n"
    128         printf "  Please unmount the mapped device first (e.g. unmount dm-0).\n\n"
    129 
    130     elif echo "$1" | grep -qi "Error unmounting"; then
    131         printf "\n  ERROR: Cannot unmount the device, device still in use.\n\n"
    132 
    133     elif echo "$1" | grep -qi "does not exist"; then
    134         printf "\n ERROR: Device appears to have been removed mid-operation.\n\n"
    135 
    136     elif echo "$1" | grep -qi "Error"; then
    137         printf "\n  ERROR: Unhandled error: \n\n"
    138         echo "$1"
    139 
    140     # Prints success messages in green
    141     else
    142         tput setaf 2
    143         if [ "$prettycmd" = "Power-off" ]; then
    144             echo "Powered off $device" | sed 's/^/  /'
    145         else
    146             echo "$1" | sed 's/^/  /'
    147         fi
    148         echo ""
    149         previousDevice="$device"
    150     fi
    151 
    152     # Reset the colours/other properties back to default
    153     tput sgr0
    154     return 0
    155 }
    156 
    157 # Takes one parameter: the command to execute
    158 execute_cmd()
    159 {
    160     cmd="$1"
    161 
    162     # Act on a previously used device if no device given by the user
    163     if [ "$device" = "" ]; then
    164         if [ ! "$previousDevice" = "" ]; then
    165             device="$previousDevice"
    166         else
    167             tput setaf 3
    168             tput bold
    169             printf "\n  Please enter a device name.\n\n"
    170             tput sgr0
    171             return 1
    172         fi
    173     fi
    174 
    175     # Presents the currently executing action to the user in a prettier way
    176     if [ "$cmd" = "power-off" ] || [ "$cmd" = "poweroff" ]; then
    177         suffix=""
    178         cmd="power-off"
    179     elif [ "$cmd" = "info" ]; then
    180         suffix=" for"
    181     else
    182         if [ "$cmd" = "umount" ]; then
    183             cmd="unmount"
    184         fi
    185         suffix="ing"
    186     fi
    187     prettycmd=$(echo "$cmd" | sed 's/./\u&/')
    188     printf "\n  %s /dev/%s...\n" "$prettycmd" "$device"
    189 
    190     # Check if encrypted filesystem and unlock+mount if needed
    191     echo "$(lsblk -o KNAME,FSTYPE | grep -i -- "$device ")" \
    192         | grep -qi "crypto_LUKS"
    193     cryptCheck=$?
    194 
    195     # Make the "Passphrase:" prompt prettier
    196     tput setaf 6
    197     if [ "$cmd" = "unlock" ]; then
    198         printf "  "
    199     fi
    200 
    201     # Execute the needed command(s)
    202     if [ "$1" = "mount" -a "$cryptCheck" = "0" ]; then
    203         unlock_and_mount "$device"
    204     else
    205         retMsg=$(udisksctl "$cmd" -b /dev/"$device" 2>&1)
    206     fi
    207 
    208     # Check the output of udisksctl for errors
    209     # (unlock_and_mount will set retMsg too)
    210     check_output "$retMsg"
    211     return 0
    212 }
    213 
    214 cmd_prompt()
    215 {
    216     retMsg=""
    217     printf "Enter a command, or ? for help:\n"
    218     read -er -p "  ($previousDevice)>>> " cmd device
    219 
    220     # Check if EOF (Ctrl-D) was given to read()
    221     readRetCode=$?
    222     if [ "$readRetCode" = "1" ]; then
    223         echo ""
    224         exit 1
    225 
    226     # "Special" commands/cases
    227     elif [ "$cmd" = "" ]; then
    228         return 1
    229     elif [ "$cmd" = "?" ]; then
    230         print_help
    231     elif [ "$cmd" = "ls" ]; then
    232         print_dev_list
    233     elif [ "$cmd" = "v" ]; then
    234         printf "\n  Version: $version\n\n"
    235     elif [ "$cmd" = "q" ]; then
    236         exit 0
    237 
    238     # Regular supported commands
    239     elif [  "$cmd" = "mount"     \
    240          -o "$cmd" = "unmount"   \
    241          -o "$cmd" = "umount"    \
    242          -o "$cmd" = "lock"      \
    243          -o "$cmd" = "unlock"    \
    244          -o "$cmd" = "info"      \
    245          -o "$cmd" = "power-off" \
    246          -o "$cmd" = "poweroff"  \
    247          ]; then
    248         execute_cmd "$cmd"
    249 
    250     else
    251         tput setaf 1
    252         tput bold
    253         printf "\n  ERROR: Unknown or unsupported command.\n\n"
    254         tput sgr0
    255     fi
    256 }
    257 
    258 previousDevice=""
    259 tput bold
    260 printf "\n  usrmnt $version Copyright (C) 2019  Jake Bauer
    261   This program comes with ABSOLUTELY NO WARRANTY.
    262   This is free software, licensed under the GNU GPLv3-or-later.
    263   You are welcome to redistribute it under certain conditions.\n"
    264 tput sgr0
    265 print_dev_list
    266 while true; do
    267     cmd_prompt
    268 done