#!/bin/sh # genext2fs wrapper calculating needed blocks/inodes values if not specified set -e export LC_ALL=C CALC_BLOCKS=1 CALC_INODES=1 EXT_OPTS= EXT_OPTS_O= while getopts x:d:D:b:i:N:m:g:e:zfqUPhVv f do case $f in b) CALC_BLOCKS=0 ;; N) CALC_INODES=0; INODES=$OPTARG ;; d) TARGET_DIR=$OPTARG ;; esac done eval IMG="\"\${${OPTIND}}\"" # calculate needed inodes if [ $CALC_INODES -eq 1 ]; then INODES=$(find $TARGET_DIR | wc -l) INODES=$(expr $INODES + 400) set -- $@ -N $INODES fi # calculate needed blocks if [ $CALC_BLOCKS -eq 1 ]; then # size ~= superblock, block+inode bitmaps, inodes (8 per block), blocks # we scale inodes / blocks with 10% to compensate for bitmaps size + slack BLOCKS=$(du -s -c -k $TARGET_DIR | grep total | sed -e "s/total//") BLOCKS=$(expr 500 + \( $BLOCKS + $INODES / 8 \) \* 11 / 10) # we add 1300 blocks (a bit more than 1 MiB, assuming 1KiB blocks) for # the journal if ext3/4 # Note: I came to 1300 blocks after trial-and-error checks. YMMV. if [ ${GEN} -ge 3 ]; then BLOCKS=$(expr 1300 + $BLOCKS ) fi set -- $@ -b $BLOCKS fi e2tunefsck() { # Upgrade the file system if [ $# -ne 0 ]; then tune2fs "$@" "${IMG}" fi # genext2fs does not generate a UUID, but fsck will whine if one is # is missing, so we need to add a UUID. # Of course, this has to happend _before_ we run fsck. # Although a random UUID may seem bad for reproducibility, there # already are so many things that are not reproducible in a # filesystem: file dates, file ordering, content of the files... tune2fs -U random "${IMG}" # After changing filesystem options, running fsck is required # (see: man tune2fs). Running e2fsck in other cases will ensure # coherency of the filesystem, although it is not required. # 'e2fsck -pDf' means: # - automatically repair # - optimise and check for duplicate entries # - force checking # Sending output to oblivion, as e2fsck can be *very* verbose, # especially with filesystems generated by genext2fs. # Exit codes 1 & 2 are OK, it means fs errors were successfully # corrected, hence our little trick with $ret. ret=0 e2fsck -pDf "${IMG}" >/dev/null || ret=$? case ${ret} in 0|1|2) ;; *) exit ${ret};; esac printf "\ne2fsck was successfully run on '%s' (ext%d)\n\n" \ "${IMG##*/}" "${GEN}" # Remove count- and time-based checks, they are not welcome # on embedded devices, where they can cause serious boot-time # issues by tremendously slowing down the boot. tune2fs -c 0 -i 0 "${IMG}" } # Check we know what generation to generate case "${GEN}:${REV}" in 2:0|2:1|3:1|4:1) ;; *) printf "%s: unknown ext generation '%s' and/or revision '%s'\n" \ "${0##*/}" "${GEN}" "${REV}" >&2 exit 1 ;; esac # Upgrade to rev1 if needed if [ ${REV} -ge 1 ]; then EXT_OPTS_O="${EXT_OPTS_O},filetype" fi # Add a journal for ext3 and above if [ ${GEN} -ge 3 ]; then EXT_OPTS="${EXT_OPTS} -j -J size=1" fi # Add ext4 specific features if [ ${GEN} -ge 4 ]; then EXT_OPTS_O="${EXT_OPTS_O},extents,uninit_bg,dir_index" fi # Add our -O options (there will be at most one leading comma, remove it) if [ -n "${EXT_OPTS_O}" ]; then EXT_OPTS="${EXT_OPTS} -O ${EXT_OPTS_O#,}" fi # Generate and upgrade the filesystem genext2fs "$@" e2tunefsck ${EXT_OPTS}