Update catfile.py
[PyCatFile.git] / neocatfile.sh
blobcebd8fb8f7200d982160a8ab973aa4628fc9e5da
1 #!/usr/bin/env bash
3 function PackCatFile {
4 shopt -s globstar
5 declare -A inodetofile
6 declare -i curinode=0
7 numfiles=$(find "${1}" -mindepth 1 -type f,l,c,b,d,p -print | wc -l)
8 printf 'CatFile1\x00%s\x00' "${numfiles}" > "${2}"
9 tmpfile=$(mktemp)
11 for file in "${1}"/**; do
12 [ -e "$file" ] || continue # Skip if file doesn't exist
13 fname="${file%/}"
14 echo "${fname}"
15 finfo=( $(stat -c "%i %f %X %Y %Z %T %t %u %g %U %G %h %s" "${fname}") )
16 ftype=0; flinkname=""; fsize=0
17 fcurinode=$curinode
18 finode=${finfo[0]}
19 fmode=${finfo[1]}
20 fatime=$(printf "%x" ${finfo[2]})
21 fmtime=$(printf "%x" ${finfo[3]})
22 fctime=$(printf "%x" ${finfo[4]})
23 fbtime=$(printf "%x" ${finfo[4]}) # Same as ctime in this script's context
24 fdev_minor=$(printf "%x" ${finfo[5]})
25 fdev_major=$(printf "%x" ${finfo[6]})
26 fuid=$(printf "%x" ${finfo[7]})
27 fgid=$(printf "%x" ${finfo[8]})
28 funame=${finfo[9]}
29 fgname=${finfo[10]}
30 flinkcount=$(printf "%x" ${finfo[11]})
31 fsizehex=$(printf "%x" ${finfo[12]})
33 case $(stat -c %F "${fname}") in
34 'regular file') ftype=0 ;;
35 'symbolic link') ftype=2; flinkname=$(readlink -f "${fname}") ;;
36 'character special file') ftype=3 ;;
37 'block special file') ftype=4 ;;
38 'directory') ftype=5 ;;
39 'fifo') ftype=6 ;;
40 esac
42 if [ $ftype -eq 0 ] && [ -n "${inodetofile[$finode]}" ]; then
43 ftype=1
44 flinkname=${inodetofile[$finode]}
45 else
46 inodetofile[$finode]=$fname
47 ((curinode++))
50 ftypehex=$(printf "%x" $ftype)
51 finodehex=$(printf "%x" $finode)
52 printf "%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00%s\x00" "$ftypehex" "$fname" "$flinkname" "$fsizehex" "$fatime" "$fmtime" "$fctime" "$fbtime" "$fmode" "$fuid" "$funame" "$fgid" "$fgname" "$fcurinode" "$finodehex" "$flinkcount" "$fdev_minor" "$fdev_major" "$fdev_minor" "$fdev_major" "0" > "$tmpfile"
54 # Calculate checksums
55 if [ "${4}" == "none" ]; then
56 echo -n "none\x00" > "$tmpfile" # Writing directly to temporary file
57 catfileheadercshex="0"
58 catfilecontentcshex="0"
59 elif [ -z "${4}" ] || [ "${4}" == "crc32" ]; then
60 catfileheadercshex=$(crc32 "$tmpfile" | cut -d ' ' -f 1)
61 catfilecontentcshex=$(if [ -f "$fname" ]; then crc32 "$fname"; else crc32 /dev/null; fi | cut -d ' ' -f 1)
62 else
63 checksum_command="${4}sum"
64 catfileheadercshex=$($checksum_command "$tmpfile" | cut -d ' ' -f 1)
65 catfilecontentcshex=$(if [ -f "$fname" ]; then $checksum_command "$fname"; else $checksum_command /dev/null; fi | cut -d ' ' -f 1)
68 cat "$tmpfile" >> "${2}"
69 printf "%s\x00%s\x00" "$catfileheadercshex" "$catfilecontentcshex" >> "${2}"
70 [ -f "$fname" ] && cat "$fname" >> "${2}"
71 printf '\x00' >> "${2}"
72 done
74 rm -f "$tmpfile"
76 case "${3}" in
77 gzip) gzip --quiet --best "${2}" ;;
78 bzip2) bzip2 --compress --quiet --best "${2}" ;;
79 zstd) zstd -19 --rm -qq --format=zstd "${2}" ;;
80 lz4) lz4 -9 -z --rm -qq "${2}" ;;
81 lzo) lzop -9 -U -q "${2}" ;;
82 lzma) lzma --compress --quiet -9 --extreme "${2}" ;;
83 xz) xz --compress --quiet -9 --extreme "${2}" ;;
84 brotli) brotli --rm --best "${2}" ;;
85 *) echo "Unsupported compression method: ${3}" >&2 ;;
86 esac
89 PackCatFile "${1}" "${2}" "${3}" "${4}"