| #!/bin/sh -x |
| |
| # SPDX-License-Identifier: Apache-2.0 |
| # Copyright 2020 IBM Corp. |
| |
| set -eu |
| |
| ARG_IF= |
| ARG_OF= |
| ARG_BS= |
| ARG_COUNT= |
| ARG_SKIP= |
| ARG_SEEK= |
| ARG_APPEND= |
| ARG_CONV_NOTRUNC= |
| DD=/bin/dd |
| |
| for arg in "$@" |
| do |
| case "$arg" in |
| if=*) |
| ARG_IF="${arg#*=}" |
| ;; |
| of=*) |
| ARG_OF="${arg#*=}" |
| ;; |
| bs=*) |
| ARG_BS="${arg#*=}" |
| ;; |
| count=*) |
| ARG_COUNT="${arg#*=}" |
| ;; |
| skip=*) |
| ARG_SKIP="${arg#*=}" |
| ;; |
| seek=*) |
| ARG_SEEK="${arg#*=}" |
| ;; |
| conv=notrunc) |
| ARG_CONV_NOTRUNC=1 |
| ;; |
| *) |
| ARG_APPEND+="${arg#*=}" |
| ;; |
| esac |
| done |
| |
| # If conv=notrunc isn't supplied, invoke system dd |
| if [ -z "$ARG_CONV_NOTRUNC" ] |
| then |
| exec $DD "$@" |
| fi |
| |
| # If conv=notrunc is supplied and system dd supports it, invoke system dd |
| if $DD conv=notrunc < /dev/null > /dev/null 2> /dev/null |
| then |
| exec $DD "$@" |
| fi |
| |
| # Otherwise, emulate conv=notrunc support |
| |
| # Examples: |
| # |
| # Inject foo into bar at offset 100: |
| # |
| # $ dd if=foo of=bar bs=1 seek=100 conv=notrunc |
| if [ "$ARG_IF" = "$ARG_OF" ] |
| then |
| >&2 echo "Add support for self-modification" |
| exit 1 |
| fi |
| |
| cleanup() |
| { |
| rm -f $OF_FILE |
| } |
| |
| filesize() |
| { |
| # busybox stat(1) doesn't support --format=%s |
| wc -c "$1" | awk '{print $1}' |
| } |
| |
| trap cleanup EXIT |
| |
| if [ -z "$ARG_OF" ] |
| then |
| DATA_SOURCE= |
| else |
| DATA_SOURCE='if='$ARG_OF |
| fi |
| |
| # Intermediate output file |
| OF_FILE=$(mktemp) |
| |
| # Generate the prefix |
| if [ -z "$ARG_SEEK" ] |
| then |
| PREFIX_COUNT= |
| INSERT_SEEK= |
| else |
| PREFIX_COUNT='count='$ARG_SEEK |
| INSERT_SEEK='seek='$ARG_SEEK |
| fi |
| |
| if [ -z "$ARG_BS" ] |
| then |
| PREFIX_BS= |
| INSERT_BS= |
| else |
| PREFIX_BS='bs='$ARG_BS |
| INSERT_BS='bs='$ARG_BS |
| fi |
| |
| if [ -z "$ARG_SKIP" ] |
| then |
| INSERT_SKIP= |
| else |
| INSERT_SKIP='skip='$ARG_SKIP |
| fi |
| |
| if [ -z "$ARG_IF" ] |
| then |
| INSERT_IF= |
| else |
| INSERT_IF='if='$ARG_IF |
| fi |
| |
| if [ -z "$ARG_COUNT" ] |
| then |
| INSERT_COUNT= |
| else |
| INSERT_COUNT='count='$ARG_COUNT |
| fi |
| |
| # Create the prefix |
| $DD $DATA_SOURCE of="$OF_FILE" $PREFIX_BS $PREFIX_COUNT $ARG_APPEND |
| OF_UPDATE_OFF=$(filesize "$OF_FILE") |
| |
| # Append the source data |
| dd "$INSERT_IF" of="$OF_FILE" $INSERT_BS $INSERT_COUNT $INSERT_SEEK $INSERT_SKIP |
| OF_SUFFIX_OFF=$(filesize "$OF_FILE") |
| |
| if [ -z "$ARG_OF" ] |
| then |
| OF_SUFFIX_OFF=$(($OF_SUFFIX_OFF - $OF_UPDATE_OFF)) |
| fi |
| |
| # Append the suffix |
| $DD $DATA_SOURCE of="$OF_FILE" bs=1 skip=$OF_SUFFIX_OFF seek=$OF_SUFFIX_OFF $ARG_APPEND |
| |
| mv "$OF_FILE" "$ARG_OF" |