--- /dev/null
+# SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+# Example usage:
+#
+# {
+# tar_print_member "date.txt" "It's $(date +"%Y")"
+# tar_print_trailer
+# } > test.tar
+
+__tar_print_padding() {
+ dd if=/dev/zero bs=1 count=$1 2>/dev/null
+}
+
+tar_print_member() {
+ local name="$1"
+ local content="$2"
+ local mtime="${3:-$(date +%s)}"
+ local mode=644
+ local uid=0
+ local gid=0
+ local size=${#content}
+ local type=0
+ local link=""
+ local username="root"
+ local groupname="root"
+
+ # 100 byte of padding bytes, using 0x01 since the shell does not tolerate null bytes in strings
+ local pad=$'\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1'
+
+ # validate name (strip leading slash if present)
+ name=${name#/}
+
+ # truncate string header values to their maximum length
+ name=${name:0:100}
+ link=${link:0:100}
+ username=${username:0:32}
+ groupname=${groupname:0:32}
+
+ # construct header part before checksum field
+ local header1="${name}${pad:0:$((100 - ${#name}))}"
+ header1="${header1}$(printf '%07d\1' $mode)"
+ header1="${header1}$(printf '%07o\1' $uid)"
+ header1="${header1}$(printf '%07o\1' $gid)"
+ header1="${header1}$(printf '%011o\1' $size)"
+ header1="${header1}$(printf '%011o\1' $mtime)"
+
+ # construct header part after checksum field
+ local header2="$(printf '%d' $type)"
+ header2="${header2}${link}${pad:0:$((100 - ${#link}))}"
+ header2="${header2}ustar ${pad:0:1}"
+ header2="${header2}${username}${pad:0:$((32 - ${#username}))}"
+ header2="${header2}${groupname}${pad:0:$((32 - ${#groupname}))}"
+
+ # calculate checksum over header fields
+ local checksum=0
+ for byte in $(printf '%s%8s%s' "$header1" "" "$header2" | tr '\1' '\0' | hexdump -ve '1/1 "%u "'); do
+ checksum=$((checksum + byte))
+ done
+
+ # print member header, padded to 512 byte
+ printf '%s%06o\0 %s' "$header1" $checksum "$header2" | tr '\1' '\0'
+ __tar_print_padding 183
+
+ # print content data, padded to multiple of 512 byte
+ printf "%s" "$content"
+ __tar_print_padding $((512 - (size % 512)))
+}
+
+tar_print_trailer() {
+ __tar_print_padding 1024
+}