Robert Yang | 76d84ff | 2013-10-13 22:09:12 -0400 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | # |
| 3 | # This script uses debugfs command to populate the ext2/3/4 filesystem |
| 4 | # from a given directory. |
| 5 | # |
| 6 | |
| 7 | do_usage () { |
| 8 | cat << _EOF |
| 9 | Usage: populate-extfs.sh <source> <device> |
| 10 | Create an ext2/ext3/ext4 filesystem from a directory or file |
| 11 | |
| 12 | source: The source directory or file |
| 13 | device: The target device |
| 14 | |
| 15 | _EOF |
| 16 | exit 1 |
| 17 | } |
| 18 | |
| 19 | [ $# -ne 2 ] && do_usage |
| 20 | |
| 21 | SRCDIR=${1%%/} |
| 22 | DEVICE=$2 |
| 23 | |
| 24 | # Find where is the debugfs command if not found in the env. |
| 25 | if [ -z "$DEBUGFS" ]; then |
| 26 | CONTRIB_DIR=$(dirname $(readlink -f $0)) |
| 27 | DEBUGFS="$CONTRIB_DIR/../debugfs/debugfs" |
| 28 | fi |
| 29 | |
| 30 | { |
| 31 | CWD="/" |
| 32 | find $SRCDIR | while read FILE; do |
| 33 | TGT="${FILE##*/}" |
| 34 | DIR="${FILE#$SRCDIR}" |
| 35 | DIR="${DIR%$TGT}" |
| 36 | |
| 37 | # Skip the root dir |
| 38 | [ ! -z "$DIR" ] || continue |
| 39 | [ ! -z "$TGT" ] || continue |
| 40 | |
| 41 | if [ "$DIR" != "$CWD" ]; then |
| 42 | echo "cd $DIR" |
| 43 | CWD="$DIR" |
| 44 | fi |
| 45 | |
| 46 | # Only stat once since stat is a time consuming command |
| 47 | STAT=$(stat -c "TYPE=\"%F\";DEVNO=\"0x%t 0x%T\";MODE=\"%f\";U=\"%u\";G=\"%g\"" $FILE) |
| 48 | eval $STAT |
| 49 | |
| 50 | case $TYPE in |
| 51 | "directory") |
| 52 | echo "mkdir $TGT" |
| 53 | ;; |
| 54 | "regular file" | "regular empty file") |
| 55 | echo "write $FILE $TGT" |
| 56 | ;; |
| 57 | "symbolic link") |
| 58 | LINK_TGT=$(readlink $FILE) |
| 59 | echo "symlink $TGT $LINK_TGT" |
| 60 | ;; |
| 61 | "block special file") |
| 62 | echo "mknod $TGT b $DEVNO" |
| 63 | ;; |
| 64 | "character special file") |
| 65 | echo "mknod $TGT c $DEVNO" |
| 66 | ;; |
| 67 | "fifo") |
| 68 | echo "mknod $TGT p" |
| 69 | ;; |
| 70 | *) |
| 71 | echo "Unknown/unhandled file type '$TYPE' file: $FILE" 1>&2 |
| 72 | ;; |
| 73 | esac |
| 74 | |
| 75 | # Set the file mode |
| 76 | echo "sif $TGT mode 0x$MODE" |
| 77 | |
| 78 | # Set uid and gid |
| 79 | echo "sif $TGT uid $U" |
| 80 | echo "sif $TGT gid $G" |
| 81 | done |
| 82 | |
| 83 | # Handle the hard links. |
| 84 | # Save the hard links to a file, use the inode number as the filename, for example: |
| 85 | # If a and b's inode number is 6775928, save a and b to /tmp/tmp.VrCwHh5gdt/6775928. |
| 86 | INODE_DIR=`mktemp -d` || exit 1 |
| 87 | for i in `find $SRCDIR -type f -links +1 -printf 'INODE=%i###FN=%p\n'`; do |
| 88 | eval `echo $i | sed 's$###$ $'` |
| 89 | echo ${FN#$SRCDIR} >>$INODE_DIR/$INODE |
| 90 | done |
| 91 | # Use the debugfs' ln and "sif links_count" to handle them. |
| 92 | for i in `ls $INODE_DIR`; do |
| 93 | # The link source |
| 94 | SRC=`head -1 $INODE_DIR/$i` |
| 95 | # Remove the files and link them again except the first one |
| 96 | for TGT in `sed -n -e '1!p' $INODE_DIR/$i`; do |
| 97 | echo "rm $TGT" |
| 98 | echo "ln $SRC $TGT" |
| 99 | done |
| 100 | LN_CNT=`cat $INODE_DIR/$i | wc -l` |
| 101 | # Set the links count |
| 102 | echo "sif $SRC links_count $LN_CNT" |
| 103 | done |
| 104 | rm -fr $INODE_DIR |
| 105 | } | $DEBUGFS -w -f - $DEVICE |