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