feat(user/bkotslu):v0.0.1: Add OTS lookup script
[BK-2020-03.git] / user / bkotslu
CommitLineData
aa8be4bf
SBS
1#!/bin/bash
2# Desc: Utility for backing up and retrieving ots files
3# Version: 0.0.1
4
5OTS_FCACHE_DIR="$HOME/.cache/bkotslu/";
6MAX_FIND_DEPTH=12;
7
8yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
9die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
10must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
11vbm() {
12 # Description: Prints verbose message ("vbm") to stderr if opVerbose is set to "true".
13 # Usage: vbm "DEBUG :verbose message here"
14 # Version 0.2.0
15 # Input: arg1: string
16 # vars: opVerbose
17 # Output: stderr
18 # Depends: bash 5.1.16, GNU-coreutils 8.30 (echo, date)
19
20 if [ "$opVerbose" = "true" ]; then
21 functionTime="$(date --iso-8601=ns)"; # Save current time in nano seconds.
22 echo "[$functionTime]:$0:""$*" 1>&2; # Display argument text.
23 fi
24
25 # End function
26 return 0; # Function finished.
27}; # Displays message if opVerbose true
28showUsage() {
29 # Desc: Display script usage information
30 # Usage: showUsage
31 # Version 0.0.2
32 # Input: none
33 # Output: stdout
34 # Depends: GNU-coreutils 8.30 (cat)
35 cat <<'EOF'
36 USAGE:
37 bkotslu [ options ] [FILE...]
38
39 OPTIONS:
40 -h, --help
41 Display help information.
42 --version
43 Display script version.
44 -v, --verbose
45 Display debugging info.
46 -i, --input-file
47 Define input file path for file to add ots file to.
48 -O, --output-dir
49 Define output directory path for storing ots backup files.
50 DEFAULT: $HOME/.cache/bkotslu/
51 --
52 Indicate end of options.
53
54 EXAMPLE:
55 Hash foo.txt and lookup matching ots file
56 bkotslu -i foo.txt
57
58 Archive ots files from home directory
59 bkotslu -I $HOME/
60
61EOF
62}; # Display information on how to use this script.
63showVersion() {
64 # Desc: Displays script version and license information.
65 # Usage: showVersion
66 # Version: 0.0.2
67 # Input: scriptVersion var containing version string
68 # Output: stdout
69 # Depends: vbm(), yell, GNU-coreutils 8.30
70
71 # Initialize function
72 vbm "DEBUG:showVersion function called."
73
74 cat <<'EOF'
75bkotslu 0.0.1
76Copyright (C) 2024 Steven Baltakatei Sandoval
77License GPLv3: GNU GPL version 3
78This is free software; you are free to change and redistribute it.
79There is NO WARRANTY, to the extent permitted by law.
80
81 GNU Coreutils 8.32
82 Copyright (C) 2020 Free Software Foundation, Inc.
83 License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
84 This is free software: you are free to change and redistribute it.
85 There is NO WARRANTY, to the extent permitted by law.
86EOF
87
88 # End function
89 vbm "DEBUG:showVersion function ended."
90 return 0; # Function finished.
91}; # Display script version.
92processArgs() {
93 # Desc: Processes arguments provided to script.
94 # Usage: processArgs "$@"
95 # Version: 1.0.0
96 # Input: "$@" (list of arguments provided to the function)
97 # Output: Sets following variables used by other functions:
98 # opVerbose Indicates verbose mode enable status. (ex: "true", "false")
99 # pathDirOut1 Path to output directory.
100 # pathDirIn1 Path to input directory.
101 # pathFileIn1 Path to input file.
102 # arrayPosArgs Array of remaining positional argments
103 # Depends:
104 # yell() Displays messages to stderr.
105 # vbm() Displays messsages to stderr if opVerbose set to "true".
106 # showUsage() Displays usage information about parent script.
107 # showVersion() Displays version about parent script.
108 # arrayPosArgs Global array for storing non-option positional arguments (i.e. arguments following the `--` option).
109 # External dependencies: bash (5.1.16), echo
110 # Ref./Attrib.:
111 # [1]: Marco Aurelio (2014-05-08). "echo that outputs to stderr". https://stackoverflow.com/a/23550347
112 # [2]: "Handling positional parameters" (2018-05-12). https://wiki.bash-hackers.org/scripting/posparams
113
114 # Initialize function
115 vbm "DEBUG:processArgs function called."
116
117 # Perform work
118 if [ $# -le 0 ]; then yell "FATAL:No arguments provided."; showUsage; fi;
119 while [ ! $# -eq 0 ]; do # While number of arguments ($#) is not (!) equal to (-eq) zero (0).
120 #yell "DEBUG:Starting processArgs while loop." # Debug stderr message. See [1].
121 #yell "DEBUG:Provided arguments are:""$*" # Debug stderr message. See [1].
122 case "$1" in
123 -h | --help) showUsage; exit 1;; # Display usage.
124 --version) showVersion; exit 1;; # Show version
125 -v | --verbose) opVerbose="true"; vbm "DEBUG:Verbose mode enabled.";; # Enable verbose mode. See [1].
126 -i | --input-file) # Define input file path
127 if [ -f "$2" ]; then # If $2 is file that exists, set pathFileIn1 to $2, pop $2.
128 pathFileIn1="$2";
129 vbm "DEBUG:Input file pathFileIn1 set to:${pathFileIn1}";
130 shift;
131 else
132 die "FATAL: Specified input file does not exist:$2";
133 fi;;
134 -I | --input-dir) # Define input directory path
135 if [ -d "$2" ]; then # If $2 is dir that exists, set pathDirIn1 to $2, pop $2.
136 pathDirIn1="$2";
137 vbm "DEBUG:Input directory pathDirIn1 set to:${pathDirIn1}";
138 shift;
139 else # Display error if $2 is not a valid dir.
140 die "FATAL:Specified input directory does not exist:$2";
141 fi;;
142 -O | --output-dir) # Define output directory path
143 if [ -d "$2" ]; then # If $2 is dir that exists, set pathDirOut1 to $2, pop $2
144 pathDirOut1="$2";
145 vbm "DEBUG:Output directory pathDirOut1 set to:${pathDirOut1}";
146 shift;
147 else
148 die "FATAL:Specified output directory is not valid:$2";
149 fi;;
150 --) # End of all options. See [2].
151 shift;
152 for arg in "$@"; do
153 vbm "DEBUG:adding to arrayPosArgs:$arg";
154 arrayPosArgs+=("$arg");
155 done;
156 break;;
157 -*) showUsage; die "FATAL: Unrecognized option.";; # Display usage
158 *) showUsage; die "FATAL: Unrecognized argument.";; # Handle unrecognized options. See [1].
159 esac;
160 shift;
161 done;
162
163 ## Identify ots file cache dir
164 if [[ -z "$pathDirOut1" ]]; then
165 vbm "STATUS:No output directory for caching OTS files specified.";
166 pathDirOut1="$OTS_FCACHE_DIR";
167 vbm "STATUS:Assuming OTS files to be cached in:${pathDirOut1}";
168 fi;
169 ## Create cache dir if necessary
170 if [[ ! -d "$pathDirOut1" ]]; then
171 vbm "STATUS:Creating OTS file cache directory:${pathDirOut1}";
172 must mkdir -p "$pathDirOut1";
173 fi;
174
175 # End function
176 vbm "DEBUG:processArgs function ended.";
177 return 0; # Function finished.
178}; # Evaluate script options from positional arguments (ex: $1, $2, $3, etc.).
179get_ots_filehash() {
180 # Desc: Gets hash of an opentimestamp'd file from ots file
181 # Usage: get_ots_filehash FILE
182 # Example: get_ots_filehash foo.txt.ots
183 # Depends: ots 0.7.0, GNU grep 3.7, GNU Coreutils 8.32
184 # vbm() verbose output
185 # BK-2020-03 yell()
186 # Input: arg1 OTS file path
187 # Output: stdout sha256 file hash (lowercase)
188 local output;
189
190 vbm "DEBUG:Starting get_ots_filehash() on:$1";
191 if output="$( "$(which ots)" info "$1" | \
192 grep -E "^File sha256 hash: " | \
193 head -n1 | \
194 sed -E -e 's/(^File sha256 hash: )([0-9a-f]+$)/\2/g'; )" && \
195 [[ -n "$output" ]]; then
196 vbm "STATUS:Read file hash via ots from:$1";
197 printf "%s" "$output";
198 return 0;
199 else
200 yell "ERROR:Encountered problem getting file hash via ots from:$1";
201 return 1;
202 fi;
203}; # Gets hash of file from ots file
204get_ots_oldestblock() {
205 # Desc: Gets earliest Bitcoin block number from ots file
206 # Usage: get_ots_oldestblock FILE
207 # Example: get_ots_oldestblock foo.txt.ots
208 # Input: arg1 path OTS file path
209 # Output: stdout int Bitcoin block number
210 # Depends: OpenTimestamps 0.7.0, GNU grep 3.7, GNU Coreutils 8.32
211 # vbm()
212 # BK-2020-03: yell()
213 local output;
214
215 vbm "DEBUG:Starting get_ots_oldestblock() on:$1";
216 if output="$( "$(which ots)" info "$1" | \
217 grep -E "verify BitcoinBlockHeaderAttestation\([0-9]+\)" | \
218 sort | head -n1 | \
219 sed -E -e 's/(^ verify BitcoinBlockHeaderAttestation)\(([0-9]+)(\))/\2/g'; )" && \
220 [[ -n "$output" ]]; then
221 vbm "STATUS:Retrieved Bitcoin block via ots from:$1";
222 printf "%s" "$output";
223 return 0;
224 else
225 yell "ERROR:Encountered problem getting Bitcoin block number via ots from:$1";
226 return 1;
227 fi;
228}; # Gets oldest Bitcoin block from ots file
229cache_ots_file() {
230 # Desc: Scans and caches an OTS file for storing
231 if fhash="$(must get_ots_filehash "$line")" && \
232 block="$(must get_ots_oldestblock "$line")"; then
233 fout="${fhash}_${block}.otsu"; # file name out
234 pout="${pathDirOut1}/${fout}"; # file path out
235 vbm "STATUS:Found OTS file at ${line} with hash ${fhash} and block ${block} and saving to ${pout}";
236 must cp -n "$line" "$pout";
237 else
238 yell "ERROR:Problem analyzing file with OpenTimestamps:${line}";
239 fi;
240}; # Scans a single OTS file
241
242main() {
243 processArgs "$@";
244
245
246 # Scan provided dir for OTS files to cache.
247 if [[ -n "$pathDirIn1" ]]; then
248 while read -r line; do
249 line="$(readlink -f "$line")";
250 cache_ots_file;
251 done < <(find "$pathDirIn1" -maxdepth "$MAX_FIND_DEPTH" -type f -name "*.ots");
252 fi;
253
254 # Lookup OTS file from archive for provided file.
255 if [[ -n "$pathFileIn1" ]]; then
256 :
257 fi;
258
259
260
261
262}; # main program
263
264main "$@";