Home | History | Annotate | Download | only in contrib
      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
    106