| # 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 | 
 | } |