dehydrate-fs is a family of tools for separating out files from disk images for the efficient storage of both.
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.

71 line
1.7KB

  1. #!/usr/bin/env bash
  2. set -eo pipefail
  3. image="$1"; [ -z "$1" ] && { echo "No image file specified." >&2; exit 1; }
  4. inspect () {
  5. ( #Jerry-rig error handling onto debugfs
  6. { debugfs -R "$*" "$image" 1>&3; } 2>&1 | tail -n +2 |\
  7. { if IFS= read -r line; then
  8. printf '%s\n' "$line"
  9. cat; exit 1
  10. fi; } >&2
  11. ) 3>&1 | cat #Never invoke pager.
  12. }
  13. BLOCKSIZE=`inspect stats | sed -nE 's/^Block size:\s+([0-9]+)$/\1/p'`
  14. #Prefer same filesystem for efficiency on large files
  15. TMPDIR="$(mktemp -d "`pwd`/.pool.XXXXXXXX")" || "$(mktemp -d)" || exit 1
  16. trap 'rm -rf -- "$TMPDIR"' EXIT
  17. size () {
  18. inspect stat "$1" \
  19. | head -n3 \
  20. | sed -nE 's/.*Size: ([0-9]+).*/\1/p'
  21. }
  22. extents () {
  23. remainder=$((`size $1`%BLOCKSIZE))
  24. inspect dump_extents "$1" \
  25. | tail -n +2 \
  26. | awk '{print $5, $8, $11}' \
  27. | sed '$s/$/ '$remainder'/'
  28. }
  29. THRESHOLD=${THRESHOLD:-$((1024*1024))}
  30. listall () {
  31. if [ $# -eq 0 ]; then
  32. listall "`inspect ls -p /`"
  33. wait; return
  34. fi
  35. perl -p -e 's!/\n$!/\x0!g' <<< "$1" \
  36. | while IFS=/ read -r -d $'\0' _ inode itype _ _ name isize; do
  37. case ${itype:0:3} in
  38. '100') [ $isize -ge $THRESHOLD ] && echo $inode $isize;;
  39. '040') [[ "${name}" != @(.|..) ]] && {
  40. echo "Recursing into $name" >&2;
  41. listall "`inspect ls -p "<$inode>"`" & };;
  42. esac
  43. done
  44. }
  45. mkdir -p pool
  46. {
  47. echo -e "#BLOCKSIZE=$BLOCKSIZE\n#INODE SHA256SUM\n#INDEX BLOCK LENGTH [REMAINDER]"
  48. listall \
  49. | while IFS=' ' read -r -d $'\n' inode isize; do
  50. #TODO: Make asynchronus
  51. tmp="$(mktemp -p "$TMPDIR")"
  52. sha=`inspect dump "<$inode>" /dev/stdout \
  53. | tee "$tmp" \
  54. | sha256sum \
  55. | cut -d' ' -f1`
  56. [ -f pool/$sha ] \
  57. && rm -f "$tmp" \
  58. || mv -v "$tmp" pool/$sha 1>&2
  59. echo $inode $sha
  60. extents "<$inode>"
  61. done
  62. } > ${2:-/dev/stdout}