qemu-mount - Tools for mounting QEMU images

qemu-mount 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 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. getopt=`getopt -n "$prog" -s sh p:rt:u "$@"` || usage ""
  52. eval set -- "$getopt"
  53. partition=1
  54. read_only=
  55. fstype=
  56. set_uid=
  57. while [ $# -ge 1 ]; do
  58. case "$1" in
  59. -p) partition="$2"; shift
  60. echo $partition | grep -q -x "[0-9][0-9]*"
  61. [ $? -ne 0 ] && error "partition number must be numeric"
  62. ;;
  63. -r) read_only=1 ;;
  64. -t) fstype="$2"; shift ;;
  65. -u) set_uid=1 ;;
  66. --) shift; break ;;
  67. esac
  68. shift
  69. done
  70. [ $# -ne 2 ] && usage "wrong number of arguments"
  71. image="$1"
  72. mdir="$2"
  73. # check file types
  74. [ -e "$image" ] || error "$image: no such file"
  75. [ -f "$image" ] || error "$image must be a regular file"
  76. [ -e "$mdir" ] || error "$mdir: no such directory"
  77. [ -d "$mdir" ] || error "$mdir must be a directory"
  78. full_image=`readlink -f "$image"`
  79. full_mdir=`readlink -f "$mdir"`
  80. img_fmt=`qemu-img info "$image" | sed -n 's/^file format: \(.*\)/\1/p'`
  81. [ -n "$img_fmt" ] || error "$image has unknown format"
  82. # load kernel module, check if sudo works
  83. $SUDO modprobe nbd || exit $?
  84. # load FAT filesystem module
  85. $SUDO modprobe vfat 2> /dev/null
  86. # lock
  87. umask=`umask`; umask 0
  88. (
  89. flock -w 5 9 || error "Can't get mount lock"
  90. umask $umask
  91. # already in use?
  92. grep -q -F -x "$full_image" /tmp/nbd*.mount 2> /dev/null &&
  93. error "$image already mounted"
  94. grep -q -F -x "$full_mdir" /tmp/nbd*.mount 2> /dev/null &&
  95. error "$mdir already in use"
  96. # find free nbd device
  97. nbd_size=1
  98. for nbd in /sys/class/block/nbd*; do
  99. nbd_size=`cat ${nbd}/size`
  100. [ $nbd_size -gt 0 ] || break
  101. done
  102. [ $nbd_size -gt 0 ] && error "no free nbd devices"
  103. nbd=`basename $nbd`
  104. # reserve nbd device
  105. echo "${full_image}\n${full_mdir}" > "/tmp/${nbd}.mount" || exit $?
  106. # qemu-nbd
  107. opt_part=
  108. [ $partition -gt 0 ] && opt_part="-P $partition"
  109. $SUDO qemu-nbd -c "/dev/$nbd" -f "$img_fmt" $opt_part "$full_image"
  110. ret=$?
  111. if [ $ret -ne 0 ]; then
  112. rm -f "/tmp/${nbd}.mount"
  113. exit $ret
  114. fi
  115. # mount
  116. options=
  117. [ -n "$read_only" ] && options="$options,ro"
  118. [ -n "$set_uid" ] && options="$options,uid=`id -u`,gid=`id -g`"
  119. [ -n "$options" ] && options="-o ${options#,}"
  120. [ -n "$fstype" ] && options="-t $fstype $options"
  121. $SUDO mount $options "/dev/$nbd" "$full_mdir"
  122. ret=$?
  123. if [ $ret -ne 0 ]; then
  124. sync
  125. $SUDO qemu-nbd -d "/dev/$nbd" > /dev/null 2>&1
  126. rm -f "/tmp/${nbd}.mount"
  127. fi
  128. exit $ret
  129. ) 9>> /var/lock/qemu-mount.lock