"Fossies" - the Fresh Open Source Software Archive

Member "ext3undel-0.1.6/gabi" (16 Jul 2008, 12107 Bytes) of package /linux/misc/old/ext3undel-0.1.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/bin/bash
    2 #==============================================================================
    3 # G.A.B.I. (Get All Back Immediatly)     (c) 2008 by Itzchak Rehberg & IzzySoft
    4 #------------------------------------------------------------------------------
    5 # Gabi is just a shell script that wraps around PhotoRec (or foremost -
    6 # depending on what is found on your system) to help you restoring all
    7 # files from an ext2/ext3 file system you may have (accidentally) deleted.
    8 # It will probably work for other file systems as well.
    9 #------------------------------------------------------------------------------
   10 # Requires: photorec OR foremost
   11 #------------------------------------------------------------------------------
   12 # PhotoRec: http://www.cgsecurity.org/wiki/PhotoRec
   13 # foremost: http://foremost.sourceforge.net/
   14 #==============================================================================
   15 # $Id: gabi 40 2008-07-16 08:59:20Z izzy $
   16 
   17 #==========================================================[ Configuration ]===
   18 # for explanation of the options, see ext3undelrc
   19 #-------------------------------------------------[ File Systems and Paths ]---
   20 TMPDIR=/tmp
   21 MNTFILE=${TMPDIR}/undel_FIFO
   22 RESTDIR=recover
   23 
   24 #--------------------------------------------------------[ runtime options ]---
   25 SILENT=0
   26 DEBUG=0
   27 
   28 #-------------------------------------------------------[ foremost options ]---
   29 USETS=1
   30 USEQUICK=1
   31 USEQUIET=0
   32 READONLY=0
   33 VERBOSE=1
   34 ALLHEAD=1
   35 
   36 #-------------------------------------------------------[ photorec options ]---
   37 WHOLESPACE=0
   38 
   39 RECOPROG=photorec
   40 FILESPEC="everything"
   41 
   42 #-----------------------------------------------[ Read configuration files ]---
   43 [ -e /etc/ext3undel/ext3undelrc ] && . /etc/ext3undel/ext3undelrc
   44 [ -e $HOME/.ext3undel/ext3undelrc ] && . $HOME/.ext3undel/ext3undelrc
   45 
   46 #===================================================[ Helper / SubRoutines ]===
   47 shopt -s extglob
   48 trap "cleanUp ; exit 2" 2 3 15
   49 #-----------------------------------[ Check whether we are running as root ]---
   50 function checkRoot() {
   51   local uid=`id -u`
   52   [ $uid -gt 0 ] && {
   53     echo "This script must be run as root (or at least with sudo)."
   54     exit 1
   55   }
   56 }
   57 
   58 #-------------------------------[ Make sure needed binaries exist in $PATH ]---
   59 function checkBins() {
   60   [ "$RECOPROG" = "photorec" -a -z "`which photorec`" ] && RECOPROG=foremost
   61   [ "$RECOPROG" = "foremost" -a -z "`which foremost`" ] && {
   62     echo
   63     echo "Neither the 'photorec' nor the 'foremost' executable could be found"
   64     echo "in your \$PATH - but we need one of them. They usually ship in a"
   65     echo "package with the same name (i.e. 'photorec' or 'foremost')."
   66     echo
   67     exit 2
   68   }
   69   FLS=1
   70   [ -z "`which fls`" ] && {
   71     FLS=0
   72     echo
   73     echo "Could not find the 'fls' executable. This is not crucial - but without it"
   74     echo "we cannot list up file names. Your 'lost files' still will be recovered with"
   75     echo "a cryptic name (which is done by 'foremost') - but we cannot give you any"
   76     echo "hint on how it may have been named before. If you want these hints, please"
   77     echo "install sleuthkit."
   78     echo
   79   }
   80 }
   81 
   82 #--------------------------------------------------[ Display help and exit ]---
   83 function syntax() {
   84   echo
   85   echo "Syntax:"
   86   echo "  $0 [--help]"
   87   echo
   88   exit 0
   89 }
   90 
   91 #-------------------------------[ Remove leading and trailing white spaces ]---
   92 function trim() {
   93   echo "$1"|sed 's/^\s*//;s/\s*$//'
   94 }
   95 
   96 #--------------------------------------------------------[ Output progress ]---
   97 function li1() {
   98   [ $SILENT -eq 0 ] && echo "* $1"
   99 }
  100 
  101 #-----------------------------------------------[ Output debug information ]---
  102 function debugMsg() {
  103   [ $DEBUG -gt 0 ] && echo "# debug: $1"
  104 }
  105 
  106 #-------------------------------------------[ Print header for Mount Table ]---
  107 function printMountTabHead() {
  108   echo
  109   printf "%2s| %-7s| %-15s| %-32s| %-16s\n" "ID" "Type" "Device" "MountPoint" "Size"
  110   echo "--+--------+----------------+---------------------------------+----------------"
  111 }
  112 
  113 #---------------------------------------------[ Read a number (user input) ]---
  114 # $1: Prompt message
  115 # opt $2: Min
  116 # opt $3: Max
  117 function readnum() {
  118   read -p "$1" rd
  119   local tn=`echo $rd|sed 's/[0-9]//g'`
  120   local min=$2
  121   local max=$3
  122   [ -n "$tn" ] && {
  123     echo "Please enter only digits!"
  124     readnum "$1" "$2" "$3"
  125   }
  126   [ -z "$min" ] && min=0
  127   [ -z "$max" ] && max=99999999
  128   [ $rd -lt $min -o $rd -gt $max ] && {
  129     echo "Please enter a number between $2 and $3!"
  130     readnum "$1" "$2" "$3"
  131   }
  132 }
  133 
  134 #---------------------------------------------------------[ Read Y/N input ]---
  135 function readyn() {
  136   read -n 1 rd
  137   echo
  138   rd=`echo $rd|tr [:upper:] [:lower:]`
  139   if [ "$rd" = "y" -o "$rd" = "j" ]; then
  140     rd=1
  141   elif [ "$rd" = "n" ]; then
  142     rd=0
  143   else
  144     echo -n "Please enter 'y' for 'yes', 'n' for 'no' - or press Ctrl-C to abort: "
  145     readyn
  146   fi
  147 }
  148 
  149 #-----------------------------------------------[ Select Source MountPoint ]---
  150 function selSrc() {
  151   echo
  152   echo "Please select the ID of the FileSystem to recover from:"
  153   printMountTabHead
  154   typeset -i i=0
  155   local uLINE=""
  156   local SKIP=1
  157   mounts[0]=""
  158   mkfifo $MNTFILE
  159   df -h -l -T >$MNTFILE &
  160   while read line; do
  161     [ $SKIP -eq 1 ] && { # skip the header
  162       SKIP=0
  163       continue
  164     }
  165     if [ -n "$(trim "$uLINE")" ]; then # wrapped line continued
  166       line="${uLINE} $line"
  167     else
  168       [ -z "$(trim "`echo $line|awk '{print $7}'`" )" ] && { # line wrapped?
  169         uLINE="$line"
  170     continue
  171       }
  172     fi
  173     uLINE=""
  174     if [[ "$line" == /dev* ]]; then # skip pseudo filesystems
  175       i+=1
  176       echo "$i $line"|awk '{printf "%2d| %-7s| %-15s| %-32s| %-16s\n", $1, $3, $2, $8, $4 }'
  177       mounts[$i]=`echo $line|awk '{print $1}'`
  178       uFSTYPE[$i]=`echo $line|awk '{print $2}'`
  179     fi
  180   done<$MNTFILE
  181   rm -f $MNTFILE
  182   echo
  183   readnum "ID: " 1 $i
  184   SRC_ID=$rd
  185   echo
  186   recoFrom=${mounts[$SRC_ID]}
  187   FSTYPE=${uFSTYPE[$SRC_ID]}
  188 }
  189 
  190 #-------------------------------------------[ Select Destination directory ]---
  191 function selDest() {
  192   local rd
  193   echo
  194   echo "Please select the file system to store the recovered files to."
  195   echo "(This must be on a different device than you restore from)"
  196   printMountTabHead
  197   typeset -i i=0
  198   local SKIP=1
  199   local uLINE=""
  200   mkfifo $MNTFILE
  201   df -h -l -T >$MNTFILE &
  202   while read line; do
  203     [ $SKIP -eq 1 ] && { # skip the header
  204       SKIP=0
  205       continue
  206     }
  207     if [ -n "$(trim "$uLINE")" ]; then # wrapped line continued
  208       line="${uLINE} $line"
  209     else
  210       [ -z "$(trim "`echo $line|awk '{print $7}'`" )" ] && { # line wrapped?
  211         uLINE="$line"
  212     continue
  213       }
  214     fi
  215     uLINE=""
  216     if [[ "$line" == /dev* ]]; then # skip pseudo filesystems
  217       i+=1
  218       [ $i -ne $SRC_ID ] && echo "$i $line"|awk '{printf "%2d| %-7s| %-15s| %-32s| %-16s\n", $1, $3, $2, $8, $4 }'
  219       stores[$i]=`echo $line|awk '{print $7}'`
  220     fi
  221   done<$MNTFILE
  222   rm -f $MNTFILE
  223   readnum "Destination ID: " 1 $i
  224   if [ $rd -eq $SRC_ID ]; then
  225     echo "Invalid selection: Source and Target file systems must not be identical!"
  226     echo "This way you may destroy your lost data permanently. Are you sure to"
  227     echo -n "proceed (y/n)? "
  228     readyn
  229     echo
  230     if [ $rd -eq 1 ]; then
  231       recoTo=${stores[$rd]}/$RESTDIR
  232     else
  233       echo "Aborting on user request."
  234       cleanUp
  235       exit 0
  236     fi
  237   else
  238     recoTo=${stores[$rd]}/$RESTDIR
  239   fi
  240   echo
  241 }
  242 
  243 #----------------------------------------------[ Select File Specification ]---
  244 function selFSpec() {
  245   local rd
  246   echo
  247   echo "Please specify the type of file(s) to recover. This is usually the"
  248   echo "extension of the file (jpg, wav, mpg) or 'everything'."
  249   read -p "FileSpec ($FILESPEC): " rd
  250   [ -n "$rd" ] && FILESPEC="$rd"
  251   echo
  252 }
  253 
  254 #-----------------------------------------------[ Print yes/no for boolean ]---
  255 function printYN() {
  256   [ $SILENT -eq 0 ] && {
  257     if [ $2 -eq 1 ]; then
  258       echo "$1: Yes"
  259     else
  260       echo "$1: No"
  261     fi
  262   }
  263 }
  264 
  265 #----------------------------------------------------------------[ CleanUp ]---
  266 function cleanUp() {
  267   echo
  268   li1 "Cleaning up..."
  269   rm -f $MNTFILE
  270 }
  271 
  272 #------------------------------------------------[ List possible FileNames ]---
  273 function listNames() {
  274   [ $FLS -eq 0 ] && return
  275   echo
  276   echo "Unfortunately, we cannot automatically obtain the name of a deleted file"
  277   echo "from Unix file systems - since the connection between the iNode (which"
  278   echo "holds the MetaData, including the file name) and the real data is dropped"
  279   echo "on deletion. However, we can obtain a list of names from the deleted files."
  280   echo -n "Do you want to display a list of possible file names (y/n)? "
  281   readyn
  282   echo
  283   if [ $rd -eq 1 ]; then
  284     cmd="fls -r -d $recoFrom |grep -v '(realloc)'|grep 'r/r'"
  285     [ "$FILESPEC" != "everything" ] && cmd="$cmd |grep '.$FILESPEC'"
  286     debugMsg ""
  287     debugMsg "Running: $cmd"
  288     debugMsg ""
  289     eval $cmd
  290   else
  291     echo "OK - skipping file list..."
  292   fi
  293 }
  294 
  295 #---------------------------------------------------[ Get PhotoRec Version ]---
  296 function photoRecVer() {
  297   local TMP="${TMPDIR}/undel_xFIFO.$$"
  298   mkfifo $TMP
  299   photorec --help>$TMP &
  300   while read line; do
  301     local ver=`echo $line|awk '{print $2}'`
  302     break
  303   done<$TMP
  304   pr_maj=${ver%.*}
  305   pr_min=${ver#*.}
  306   pr_min=${pr_min%,*}
  307   [ "$pr_min" != "${pr_min%-*}" ] && let pr_min=${pr_min%-*}-1
  308   rm -f $TMP
  309 }
  310 
  311 #=================================================[ Setting up the command ]===
  312 checkRoot
  313 checkBins
  314 case "$1" in
  315   "-h"|"--help"|"-?") syntax;;
  316   *)
  317   ;;
  318 esac
  319 
  320 #-------------------------------------------------------------[ User Input ]---
  321 selSrc
  322 selDest
  323 selFSpec
  324 cleanUp
  325 
  326 #-----------------------------------------------------[ Setting up Options ]---
  327 case "$RECOPROG" in
  328   "foremost")
  329     li1 "Using foremost"
  330     cmd="foremost "
  331     [ $USEQUICK -eq 1 ] && cmd="$cmd -q"
  332     [ $USETS -eq 1 ] && cmd="$cmd -T"
  333     [ $USEQUIET -eq 1 ] && cmd="$cmd -Q"
  334     [ $READONLY -eq 1 ] && cmd="$cmd -w"
  335     [ $VERBOSE -eq 1 ] && cmd="$cmd -v"
  336     [ $ALLHEAD -eq 1 ] && cmd="$cmd -a"
  337     if [ "$FILESPEC" = "everything" ]; then
  338       cmd="$cmd -t all -o $recoTo $recoFrom"
  339     else
  340       cmd="$cmd -t $FILESPEC -o $recoTo $recoFrom"
  341     fi
  342     ;;
  343   "photorec")
  344     photoRecVer
  345     li1 "Using PhotoRec v${pr_maj}.${pr_min}"
  346     cmd="photorec /d $recoTo /cmd $recoFrom partition_i386"
  347     [ "$FSTYPE" = "ext3" -o "$FSTYPE" = "ext2" ] && cmd="${cmd},options,mode_ext2"
  348     if [ $pr_maj -gt 6 -o $pr_maj -eq 6 -a $pr_min -ge 9 ]; then
  349       cmd="${cmd},fileopt"
  350       if [ "$FILESPEC" != "everything" ]; then
  351         cmd="${cmd},everything,disable,$FILESPEC,enable,search"
  352       else
  353         cmd="${cmd},everything,enable,search"
  354       fi
  355       if [ $WHOLESPACE -eq 0 ]; then
  356         cmd="${cmd},freespace"
  357       else
  358         cmd="${cmd},wholespace"
  359       fi
  360     else
  361       [ "$FILESPEC" != "everything" ] && cmd="${cmd},fileopt,$FILESPEC,enable"
  362       cmd="${cmd},search"
  363     fi
  364     ;;
  365   *) echo "Ooops - no recovery tool specified???"
  366      echo "You normally should not see this message - there seems to be some bug in the script..."
  367     ;;
  368 esac
  369 
  370 #=============================================================[ Go for it! ]===
  371 #------------------------------------------------------[ Last confirmation ]---
  372 li1 "Recovering files of type '$FILESPEC' from '$recoFrom' to '$recoTo'."
  373 li1 "File System on source drive: '$FSTYPE'."
  374 [ "$RECOPROG" = "foremost" ] && {
  375   li1 "Special settings:"
  376   echo
  377   printYN "Quick Mode" $USEQUICK
  378   printYN "TimeStamped Directories" $USETS
  379   printYN "Be Quiet" $USEQUIET
  380   printYN "Log Only (w/o restore)" $READONLY
  381   printYN "Verbose Mode" $VERBOSE
  382   printYN "Print All Headers" $ALLHEAD
  383 }
  384 echo
  385 li1 "Prepared command:"
  386 echo "  $cmd"
  387 echo
  388 
  389 echo -n "Ready to go (y/n)? "
  390 readyn
  391 echo
  392 echo
  393 if [ $rd -eq 1 ]; then
  394   echo "Please be patient - this may take some time (or even longer on large devices)..."
  395   echo
  396   $cmd
  397   rc=$?
  398   if [ $rc -ne 0 ]; then
  399     echo
  400     echo "Looks like we had no success: $RECOPROG exited with code $rc, sorry..."
  401     exit $rc
  402   else
  403     listNames
  404   fi
  405 else
  406   echo "User requested to abort - so we quit and do nothing."
  407   cleanUp
  408   exit 0
  409 fi