qemu-mount - Tools for mounting QEMU images
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

qemu-mount 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/bin/sh
  2. #
  3. # mount qemu image file into a directory
  4. #
  5. prog=$(basename "$0")
  6. # use sudo for unprivileged users
  7. SUDO=
  8. [ "$(id -u)" -ne 0 ] && SUDO=sudo
  9. # print error message
  10. error() {
  11. echo "$prog:" "$@" 2>&1
  12. exit 1
  13. }
  14. # print usage
  15. usage() {
  16. if [ $# -ge 1 ]; then
  17. [ -n "$*" ] && echo "$prog:" "$@" 2>&1
  18. echo 2>&1
  19. fi
  20. cat << EOF >&2
  21. Mount the qemu image file into a directory.
  22. Usage: $prog [OPTIONS] qemu_image mount_point
  23. Options:
  24. -p partition_number select, which partition to mount, default #1
  25. -r mount read-only
  26. -t fstype set filesystem type
  27. -u set owner to current user
  28. Without arguments it prints a list of mounted images.
  29. EOF
  30. exit 1
  31. }
  32. # Without arguments: print mounted images
  33. if [ $# -eq 0 ]; then
  34. for file in /tmp/nbd*.mount; do
  35. nbd=$(basename "$file" .mount)
  36. [ "$nbd" = "nbd*" ] && exit 0
  37. image=
  38. while read -r line; do
  39. if [ -z "$image" ]; then
  40. image="$line"
  41. else
  42. mdir="$line"
  43. echo "$nbd: $image -> $mdir"
  44. break
  45. fi
  46. done < "$file"
  47. done
  48. exit 0
  49. fi
  50. # parse command line
  51. partition=1
  52. read_only=
  53. fstype=
  54. set_uid=
  55. while getopts ":p:rt:u" opt; do
  56. case $opt in
  57. p) partition="$OPTARG"
  58. echo "$partition" | grep -q -x "[0-9][0-9]*" || \
  59. error "partition number must be numeric" ;;
  60. r) read_only=1 ;;
  61. t) fstype=$OPTARG ;;
  62. u) set_uid=1 ;;
  63. \?) usage "illegal option -- $OPTARG" ;;
  64. :) usage "option requires an argument -- $OPTARG" ;;
  65. esac
  66. done
  67. shift $((OPTIND-1)) # remove parsed options and args from $@ list
  68. [ $# -ne 2 ] && usage "wrong number of arguments"
  69. image="$1"
  70. mdir="$2"
  71. # check file types
  72. [ -e "$image" ] || error "$image: no such file"
  73. [ -f "$image" ] || error "$image must be a regular file"
  74. [ -e "$mdir" ] || error "$mdir: no such directory"
  75. [ -d "$mdir" ] || error "$mdir must be a directory"
  76. full_image=$(readlink -f "$image")
  77. full_mdir=$(readlink -f "$mdir")
  78. img_fmt=$(qemu-img info "$image" | sed -n 's/^file format: \(.*\)/\1/p')
  79. [ -n "$img_fmt" ] || error "$image has unknown format"
  80. # load kernel module, check if sudo works
  81. $SUDO modprobe nbd || exit $?
  82. # load FAT filesystem module
  83. $SUDO modprobe vfat 2> /dev/null
  84. # lock
  85. umask=$(umask); umask 0
  86. (
  87. flock -w 5 9 || error "Can't get mount lock"
  88. umask "$umask"
  89. # already in use?
  90. grep -q -F -x "$full_image" /tmp/nbd*.mount 2> /dev/null &&
  91. error "$image already mounted"
  92. grep -q -F -x "$full_mdir" /tmp/nbd*.mount 2> /dev/null &&
  93. error "$mdir already in use"
  94. # find free nbd device
  95. nbd_size=1
  96. for nbd in /sys/class/block/nbd*; do
  97. nbd_size=$(cat "${nbd}/size")
  98. [ "$nbd_size" -gt 0 ] || break
  99. done
  100. [ "$nbd_size" -gt 0 ] && error "no free nbd devices"
  101. nbd=$(basename "$nbd")
  102. # reserve nbd device
  103. printf "%s\n%s\n" "$full_image" "$full_mdir" > "/tmp/${nbd}.mount" || exit $?
  104. # qemu-nbd
  105. opt_part=
  106. [ "$partition" -gt 0 ] && opt_part="-P $partition"
  107. $SUDO qemu-nbd -c "/dev/$nbd" -f "$img_fmt" $opt_part "$full_image"
  108. ret=$?
  109. if [ $ret -ne 0 ]; then
  110. rm -f "/tmp/${nbd}.mount"
  111. exit $ret
  112. fi
  113. # mount
  114. options=
  115. [ -n "$read_only" ] && options="$options,ro"
  116. [ -n "$set_uid" ] && options="$options,uid=$(id -u),gid=$(id -g)"
  117. [ -n "$options" ] && options="-o ${options#,}"
  118. [ -n "$fstype" ] && options="-t $fstype $options"
  119. $SUDO mount $options "/dev/$nbd" "$full_mdir"
  120. ret=$?
  121. if [ $ret -ne 0 ]; then
  122. sync
  123. $SUDO qemu-nbd -d "/dev/$nbd" > /dev/null 2>&1
  124. rm -f "/tmp/${nbd}.mount"
  125. fi
  126. exit $ret
  127. ) 9>> /var/lock/qemu-mount.lock