blob: a1808b3b3f54b163018147f1c159e0c15c332a63 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#!/bin/sh
do_usage () {
cat << _EOF
Usage: populate-extfs.sh <source> <device>
Create an ext2/ext3/ext4 filesystem from a directory or file
source: The source directory or file
device: The target device
_EOF
exit 1
}
[ $# -ne 2 ] && do_usage
SRCDIR=${1%%/}
DEVICE=$2
DEBUGFS="debugfs"
{
CWD="/"
find $SRCDIR | while read FILE; do
TGT="${FILE##*/}"
DIR="${FILE#$SRCDIR}"
# Skip the root dir
[ ! -z "$DIR" ] || continue
[ ! -z "$TGT" ] || continue
DIR="$(dirname "$DIR")"
# debugfs handles the quotation mark differently from other special marks like {
# If FILE contains quotation marks in its name, then we have to replace " with ""
# so that debugfs could correclty recognize them. In this script, we use the prefix
# of D_ to denote the file names that should be used by debugfs.
#
# The usage of case statements here is to avoid performace impact.
case $FILE in
*\"*)
D_FILE="$(echo $FILE | sed -e 's#\"#\"\"#g')"
;;
*)
D_FILE="$FILE"
;;
esac
case $DIR in
*\"*)
D_DIR="$(echo $DIR | sed -e 's#\"#\"\"#g')"
;;
*)
D_DIR="$DIR"
;;
esac
case $TGT in
*\"*)
D_TGT="$(echo $TGT | sed -e 's#\"#\"\"#g')"
;;
*)
D_TGT="$TGT"
;;
esac
if [ "$DIR" != "$CWD" ]; then
echo "cd \"$D_DIR\""
CWD="$DIR"
fi
# Only stat once since stat is a time consuming command
STAT=$(stat -c "TYPE=\"%F\";DEVNO=\"0x%t 0x%T\";MODE=\"%f\";U=\"%u\";G=\"%g\";AT=\"%x\";MT=\"%y\";CT=\"%z\"" "$FILE")
eval $STAT
case $TYPE in
"directory")
echo "mkdir \"$D_TGT\""
;;
"regular file" | "regular empty file")
echo "write \"$D_FILE\" \"$D_TGT\""
;;
"symbolic link")
LINK_TGT=$(readlink "$FILE")
D_LINK_TGT="$(echo $LINK_TGT | sed -e 's#\"#\"\"#g')"
echo "symlink \"$D_TGT\" \"$D_LINK_TGT\""
;;
"block special file")
echo "mknod \"$D_TGT\" b $DEVNO"
;;
"character special file")
echo "mknod \"$D_TGT\" c $DEVNO"
;;
"fifo")
echo "mknod \"$D_TGT\" p"
;;
*)
echo "Unknown/unhandled file type '$TYPE' file: $FILE" 1>&2
;;
esac
# Set the file mode
echo "sif \"$D_TGT\" mode 0x$MODE"
# Set uid and gid
echo "sif \"$D_TGT\" uid $U"
echo "sif \"$D_TGT\" gid $G"
# Set atime, mtime and ctime
AT=`echo $AT | cut -d'.' -f1 | sed -e 's#[- :]##g'`
MT=`echo $MT | cut -d'.' -f1 | sed -e 's#[- :]##g'`
CT=`echo $CT | cut -d'.' -f1 | sed -e 's#[- :]##g'`
echo "sif \"$D_TGT\" atime $AT"
echo "sif \"$D_TGT\" mtime $MT"
echo "sif \"$D_TGT\" ctime $CT"
done
# Handle the hard links.
# Save the hard links to a file, use the inode number as the filename, for example:
# If a and b's inode number is 6775928, save a and b to /tmp/tmp.VrCwHh5gdt/6775928.
INODE_DIR=`mktemp -d` || exit 1
for i in `find $SRCDIR -type f -links +1 -printf 'INODE=%i###FN=%p\n'`; do
eval `echo $i | sed 's$###$ $'`
echo ${FN#$SRCDIR} >>$INODE_DIR/$INODE
done
# Use the debugfs' ln and "sif links_count" to handle them.
for i in `ls $INODE_DIR`; do
# The link source
SRC="$(head -1 $INODE_DIR/$i)"
D_SRC="$(echo $SRC | sed -e 's#\"#\"\"#g')"
# Remove the files and link them again except the first one
sed -n -e '1!p' $INODE_DIR/$i | while read TGT; do
D_TGT="$(echo $TGT | sed -e 's#\"#\"\"#g')"
echo "rm \"$D_TGT\""
echo "ln \"$D_SRC\" \"$D_TGT\""
done
LN_CNT=`cat $INODE_DIR/$i | wc -l`
# Set the links count
echo "sif \"$D_SRC\" links_count $LN_CNT"
done
rm -fr $INODE_DIR
} | $DEBUGFS -w -f - $DEVICE 2>&1 1>/dev/null | grep '.*: .*'
if [ $? = 0 ]; then
echo "Some error occured while executing [$DEBUGFS -w -f - $DEVICE]"
exit 1
fi
|