aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/e2fsprogs/e2fsprogs-1.42.8/populate-extfs.sh
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