fix(bklog):Add missing function dateTimeShort()
[EVA-2020-02.git] / exec / bklog
index 7dff30dddcb6392ab672939a8ef12567adf693d6..f2652711b08d891d21a79ee195887177113b39d7 100644 (file)
@@ -11,7 +11,7 @@ dirTmpDefault="/dev/shm"; # Default parent of working directory
 
 # Script Metadata
 scriptName="bklog";             # Define basename of script file.
-scriptVersion="0.1.8";          # Define version of script.
+scriptVersion="0.1.11";          # Define version of script.
 scriptURL="https://gitlab.com/baltakatei/ninfacyzga-01"; # Define wesite hosting this script.
 scriptTimeStart="$(date +%Y%m%dT%H%M%S.%N)"; # YYYYmmddTHHMMSS.NNNNNNNNN
 scriptHostname=$(hostname);     # Save hostname of system running this script.
@@ -284,6 +284,46 @@ checkAgePubkey() {
        return 1;
     fi;
 } # Check age pubkey
+checkMakeTar() {
+    # Desc: Checks that a valid tar archive exists, creates one otherwise
+    # Usage: checkMakeTar [ path ]
+    # Version: 1.0.2
+    # Input: arg1: path of tar archive
+    # Output: exit code 0 : tar readable
+    #         exit code 1 : tar missing; created
+    #         exit code 2 : tar not readable; moved; replaced
+    # Depends: bash 5, date 8, tar 1, try()
+    local pathTar returnFlag0 returnFlag1 returnFlag2
+    pathTar="$1";
+
+    # Check if file is a valid tar archive
+    if tar --list --file="$pathTar" 1>/dev/null 2>&1; then
+       ## T1: return success
+       returnFlag0="tar valid";
+    else
+       ## F1: Check if file exists
+       if [[ -f "$pathTar" ]]; then
+           ### T: Rename file
+           try mv "$pathTar" "$pathTar""--broken--""$(date +%Y%m%dT%H%M%S)" && \
+               returnFlag1="tar moved";
+       else
+           ### F: -
+           :
+       fi;
+       ## F2: Create tar archive, return 0
+       try tar --create --file="$pathTar" --files-from=/dev/null && \
+           returnFlag2="tar created";
+    fi;
+    
+    # Determine function return code
+    if [[ "$returnFlag0" = "tar valid" ]]; then
+       return 0;
+    elif [[ "$returnFlag2" = "tar created" ]] && ! [[ "$returnFlag1" = "tar moved" ]]; then
+       return 1; # tar missing so created
+    elif [[ "$returnFlag2" = "tar created" ]] && [[ "$returnFlag1" = "tar moved" ]]; then
+       return 2; # tar not readable so moved; replaced
+    fi;
+} # checks if arg1 is tar; creates one otherwise
 dateShort(){
     # Desc: Date without separators (YYYYmmdd)
     # Usage: dateShort ([str date])
@@ -315,6 +355,37 @@ dateShort(){
     dateCurrentShort="$(date -d "$timeInput" +%Y%m%d)"; # Produce separator-less current date with resolution 1 day.
     echo "$dateCurrentShort";
 } # Get YYYYmmdd
+dateTimeShort(){
+    # Desc: Timestamp without separators (YYYYmmddTHHMMSS+zzzz)
+    # Usage: dateTimeShort ([str date])
+    # Version 1.1.1
+    # Input: arg1: 'date'-parsable timestamp string (optional)
+    # Output: stdout: timestamp (ISO-8601, no separators)
+    # Depends: yell
+    local argTime timeCurrent timeInput timeCurrentShort
+
+    argTime="$1";
+    # Get Current Time
+    timeCurrent="$(date --iso-8601=seconds)" ; # Produce `date`-parsable current timestamp with resolution of 1 second.
+    # Decide to parse current or supplied date
+    ## Check if time argument empty
+    if [[ -z "$argTime" ]]; then
+       ## T: Time argument empty, use current time
+       timeInput="$timeCurrent";
+    else
+       ## F: Time argument exists, validate time
+       if date --date="$argTime" 1>/dev/null 2>&1; then
+           ### T: Time argument is valid; use it
+           timeInput="$argTime";
+       else
+           ### F: Time argument not valid; exit
+           yell "ERROR:Invalid time argument supplied. Exiting."; exit 1;
+       fi
+    fi
+    # Construct and deliver separator-les date string
+    timeCurrentShort="$(date -d "$timeInput" +%Y%m%dT%H%M%S%z)";
+    echo "$timeCurrentShort";
+} # Get YYYYmmddTHHMMSS±zzzz
 setTimeZoneEV(){
     # Desc: Set time zone environment variable TZ
     # Usage: setTimeZoneEV arg1
@@ -624,6 +695,73 @@ timeDuration(){
     fi
 
 } # Get duration (ex: PT10M4S )
+timeUntilNextDay(){
+    # Desc: Report seconds until next day.
+    # Version: 1.0.2
+    # Output: stdout: integer seconds until next day
+    # Output: exit code 0 if stdout > 0; 1 if stdout = 0; 2 if stdout < 0
+    # Usage: timeUntilNextDay
+    # Usage: if ! myTTL="$(timeUntilNextDay)"; then yell "ERROR in if statement"; exit 1; fi
+    # Depends: date 8, echo 8, yell, try
+    
+    local returnState timeCurrent timeNextDay secondsUntilNextDay returnState
+    timeCurrent="$(date --iso-8601=seconds)" ; # Produce `date`-parsable current timestamp with resolution of 1 second.
+    timeNextDay="$(date -d "$timeCurrent next day" --iso-8601=date)"; # Produce timestamp of beginning of tomorrow with resolution of 1 second.
+    secondsUntilNextDay="$(( $(date +%s -d "$timeNextDay") - $(date +%s -d "$timeCurrent") ))" ; # Calculate seconds until closest future midnight (res. 1 second).
+    if [[ "$secondsUntilNextDay" -gt 0 ]]; then
+       returnState="true";
+    elif [[ "$secondsUntilNextDay" -eq 0 ]]; then
+       returnState="warning_zero";
+       yell "WARNING:Reported time until next day exactly zero.";
+    elif [[ "$secondsUntilNextDay" -lt 0 ]]; then
+       returnState="warning_negative";
+       yell "WARNING:Reported time until next day is negative.";
+    fi
+
+    try echo "$secondsUntilNextDay"; # Report
+    
+    # Determine function return code
+    if [[ "$returnState" = "true" ]]; then
+       return 0;
+    elif [[ "$returnState" = "warning_zero" ]]; then
+       return 1;
+    elif [[ "$returnState" = "warning_negative" ]]; then
+       return 2;
+    fi
+} # Report seconds until next day
+timeUntilNextHour(){
+    # Desc: Report seconds until next hour
+    # Version 1.0.1
+    # Output: stdout: integer seconds until next hour
+    # Output: exit code 0 if stdout > 0; 1 if stdout = 0; 2 if stdout < 0
+    # Usage: timeUntilNextHour
+    # Usage: if ! myTTL="$(timeUntilNextHour)"; then yell "ERROR in if statement"; exit 1; fi
+    
+    local returnState timeCurrent timeNextHour secondsUntilNextHour
+    timeCurrent="$(date --iso-8601=seconds)"; # Produce `date`-parsable current timestamp with resolution of 1 second.
+    timeNextHour="$(date -d "$timeCurrent next hour" --iso-8601=hours)"; # Produce `date`-parsable current time stamp with resolution of 1 second.
+    secondsUntilNextHour="$(( $(date +%s -d "$timeNextHour") - $(date +%s -d "$timeCurrent") ))"; # Calculate seconds until next hour (res. 1 second).
+    if [[ "$secondsUntilNextHour" -gt 0 ]]; then
+       returnState="true";
+    elif [[ "$secondsUntilNextHour" -eq 0 ]]; then
+       returnState="warning_zero";
+       yell "WARNING:Reported time until next hour exactly zero.";
+    elif [[ "$secondsUntilNextHour" -lt 0 ]]; then
+       returnState="warning_negative";
+       yell "WARNING:Reported time until next hour is negative.";
+    fi;
+
+    try echo "$secondsUntilNextHour"; # Report
+    
+    # Determine function return code
+    if [[ "$returnState" = "true" ]]; then
+       return 0;
+    elif [[ "$returnState" = "warning_zero" ]]; then
+       return 1;
+    elif [[ "$returnState" = "warning_negative" ]]; then
+       return 2;
+    fi;
+} # Report seconds until next hour
 validateInput() {
     # Desc: Validates Input
     # Usage: validateInput [str input] [str input type]
@@ -689,7 +827,8 @@ magicInitWorkingDir() {
     # Parse '-t' option (user-specified temporary working dir)
     ## Set dir_tmp_parent to user-specified value if specified
     local dir_tmp_parent
-    
+
+    vbm "Starting magicInitWorkingDir() function.";
     if [[ "$optionTmpDir" = "true" ]]; then
        if [[ -d "$argTempDirPriority" ]]; then
            dir_tmp_parent="$argTempDirPriority"; 
@@ -711,6 +850,7 @@ magicInitWorkingDir() {
     fi;
     ## Set dir_tmp using dir_tmp_parent and nonce (scriptTimeStart)
     dir_tmp="$dir_tmp_parent"/"$scriptTimeStart""..bkgpslog" && vbm "DEBUG:Set dir_tmp to:$dir_tmp"; # Note: removed at end of main().
+    vbm "Finished magicInitWorkingDir() function.";
 } # Sets working dir
 magicInitCheckTar() {
     # Desc: Initializes or checks output tar
@@ -719,6 +859,7 @@ magicInitCheckTar() {
     # output: vars: pathout_tar
     # depends: Bash 5.0.3, vbm(), dateShort(), checkMakeTar(), magicWriteVersion()
 
+    vbm "Starting magicInitCheckTar() function.";
     # Form pathout_tar
     pathout_tar="$dirOut"/"$(dateShort "$(date --date="$bufferTTL seconds ago" --iso-8601=seconds)")".."$scriptHostname""$label""$cmd_compress_suffix""$cmd_encrypt_suffix".tar && \
        vbm "STATUS:Set pathout_tar to:$pathout_tar";
@@ -726,25 +867,29 @@ magicInitCheckTar() {
     checkMakeTar "$pathout_tar";
     ## Add VERSION file if checkMakeTar had to create a tar (exited 1) or replace one (exited 2)
     vbm "exit status before magicWriteVersion:$?"
-    if [[ $? -eq 1 ]] || [[ $? -eq 2 ]]; then magicWriteVersion; fi    
+    if [[ $? -eq 1 ]] || [[ $? -eq 2 ]]; then magicWriteVersion; fi
+    vbm "Finished magicInitCheckTar() function.";
 } # Initialize tar, set pathout_tar
 magicParseCompressionArg() {
     # Desc: Parses compression arguments specified by '-c' option
     # Input:  vars: optionCompress
     # Output: cmd_compress, cmd_compress_suffix
     # Depends: processArguments(), vbm(), checkapp(), gzip 1.9
+
+    vbm "Starting magicParseCompressionArg() function.";
     if [[ "$optionCompress" = "true" ]]; then # Check if compression option active
        if checkapp gzip; then # Check if gzip available
            cmd_compress="gzip " && vbm "cmd_compress:$cmd_compress";
            cmd_compress_suffix=".gz" && vbm "cmd_compress_suffix:$cmd_compress_suffix";
        else
            yell "ERROR:Compression enabled but \"gzip\" not found. Exiting."; exit 1;
-       fi
+       fi;
     else
        cmd_compress="tee /dev/null " && vbm "cmd_compress:$cmd_compress";
        cmd_compress_suffix="" && vbm "cmd_compress_suffix:$cmd_compress_suffix";
        vbm "DEBUG:Compression not enabled.";
-    fi    
+    fi;
+    vbm "Starting magicParseCompressionArg() function.";
 } # Form compression cmd string and filename suffix
 magicParseCustomTTL() {
     # Desc: Set user-specified TTLs for buffer and script
@@ -755,6 +900,7 @@ magicParseCustomTTL() {
     # Output: bufferTTL (integer), scriptTTL_TE (string)
     # Depends: Bash 5.0.3, yell(), vbm(), validateInput(), showUsage()
 
+    vbm "Starting magicParseCustomTTL() function.";
     # React to '-b, --buffer-ttl' option
     if [[ "$optionCustomBufferTTL" = "true" ]]; then
        ## T: Check if argCustomBufferTTL is an integer
@@ -779,7 +925,8 @@ magicParseCustomTTL() {
            yell "ERROR:Invalid time element argument for custom script time-to-live."; showUsage; exit 1;
        fi;
        ## F: do not change scriptTTL_TE
-    fi;    
+    fi;
+    vbm "Starting magicParseCustomTTL() function.";
 } # Sets custom script or buffer TTL if specified
 magicParseLabel() {
     # Desc: Parses -l option to set label
@@ -859,7 +1006,7 @@ magicParseProcessStrings() {
        if [[ -z "$element" ]]; then yell "ERROR:Empty output file extension specified. Exiting."; exit 1; fi; done
     ## Make sure that no process string starts with '-' (ex: if only one arg supplied after '-p' option)
     for element in "${argProcStrings[@]}"; do
-       if [[ ! "$element" =~ ^[-][[:print:]]*$ ]] && [[ "$element" =~ ^[[:print:]]*$ ]]; then
+       if [[ "$element" =~ ^[-][[:print:]]*$ ]] && [[ ! "$element" =~ ^[[:print:]]*$ ]]; then
            yell "ERROR:Illegal character '-' at start of process string element:\"$element\"";
            exit 1; fi; done;
     vbm "STATUS:Quick check shows argProcStrings and argProcFileExts appear to have valid contents.";
@@ -876,6 +1023,7 @@ magicParseRecipientArgs() {
     # Depends: processArguments(), yell(), vbm(), checkapp(), checkAgePubkey(), validateInput()
     local recipients
 
+    vbm "Starting magicParseRecipientArgs() function.";
     # Check if encryption option active.
     if [[ "$optionEncrypt" = "true" ]] && [[ "$optionRecipients" = "true" ]]; then 
        if checkapp age; then # Check that age is available.
@@ -913,7 +1061,8 @@ magicParseRecipientArgs() {
        yell "ERROR:\\'-e\\' set but no \\'-r\\' or \\'-R\\' set."; exit 1; fi;
     # Catch case if '-r' or '-R' set but '-e' is not
     if [[ ! "$optionEncrypt" = "true" ]] && [[ "$optionRecipients" = "true" ]]; then
-       yell "ERROR:\\'-r\\' or \\'-R\\' set but \\'-e\\' is not set."; exit 1; fi; 
+       yell "ERROR:\\'-r\\' or \\'-R\\' set but \\'-e\\' is not set."; exit 1; fi;
+    vbm "Finished magicParseRecipientArgs() function.";
 } # Populate recPubKeysValid with argRecPubKeys; form encryption cmd string and filename suffix
 magicParseRecipientDir() {
     # Desc: Updates recPubKeysValid with pubkeys in dir specified by '-R' option ("recipient directory")
@@ -924,6 +1073,7 @@ magicParseRecipientDir() {
     local recipientDir recFileLine updateRecipients 
     declare -a candRecPubKeysValid
 
+    vbm "Starting magicParseRecipientDir() function.";
     # Check that '-e' and '-R' set
     if [[ "$optionEncrypt" = "true" ]] && [[ "$optionRecDir" = "true" ]]; then
        ### Check that argRecDir is a directory.
@@ -959,6 +1109,7 @@ magicParseRecipientDir() {
     # Handle case if '-R' set but '-e' not set
     if [[ ! "$optionEncrypt" = "true" ]] && [[ "$optionRecDir" = "true" ]]; then
        yell "ERROR: \\'-R\\' is set but \\'-e\\' is not set."; fi;
+    vbm "Finished magicParseRecipientDir() function.";
 } # Update recPubKeysValid with argRecDir
 magicSetScriptTTL() {
     #Desc: Sets script_TTL seconds from provided time_element string argument
@@ -967,7 +1118,8 @@ magicSetScriptTTL() {
     #Output: var: scriptTTL (integer seconds)
     #Depends: timeUntilNextHour, timeUntilNextDay
     local argTimeElement
-    
+
+    vbm "Starting magicSetScriptTTL() function.";
     argTimeElement="$1";
     if [[ "$argTimeElement" = "day" ]]; then
            # Set script lifespan to end at start of next day
@@ -990,6 +1142,7 @@ magicSetScriptTTL() {
     else
        yell "ERROR:Invalid argument for setScriptTTL function:$argTimeElement"; exit 1;
     fi;
+    vbm "Finished magicSetScriptTTL() function.";
 } # Set scriptTTL in seconds until next (day|hour).
 magicWriteVersion() {
     # Desc: Appends time-stamped VERSION to pathout_tar
@@ -1000,7 +1153,8 @@ magicWriteVersion() {
     # Output: appends tar (pathout_tar)
     # Depends: bash 5.0.3, dateTimeShort(), appendArgTar()
     local fileoutVersion contentVersion pubKeyIndex pubKeyIndex
-    
+
+    vbm "Starting magicWriteVersion() function.";
     # Set VERSION file name
     fileoutVersion="$(dateTimeShort)..VERSION";
 
@@ -1023,6 +1177,7 @@ magicWriteVersion() {
 
     # Write contentVersion as file fileoutVersion and write-append to pathout_tar
     appendArgTar "$contentVersion" "$fileoutVersion" "$pathout_tar" "$dir_tmp";
+    vbm "Finished magicWriteVersion() function.";
 } # write version data to pathout_tar via appendArgTar()
 magicProcessWriteBuffer() {
     # Desc: process and write buffer
@@ -1108,8 +1263,6 @@ main() {
     magicParseProcessStrings; # Sets arrays: procStrings, procFileExts
     ## React to "-l" (output file label) option
     magicParseLabel; # sets label (ex: "_location")
-    ## React to "-w" (how to name raw stdin file) option
-    magicParseStoreRaw; # sets raw_suffix
 
     # Perform secondary setup operations
     ## Set script lifespan (scriptTTL from scriptTTL_TE)
@@ -1129,16 +1282,12 @@ main() {
     # MAIN LOOP: Run until script TTL seconds pass
     bufferRound=0;
     while [[ $SECONDS -lt "scriptTTL" ]]; do
+       vbm "DEBUG:Starting buffer round:$bufferRound";
        bufferTOD="$((SECONDS + bufferTTL))"; # Set buffer round time-of-death
-       lineCount=0; # Debug counter
        # Consume stdin to fill buffer until buffer time-of-death (TOD) arrives
        while read -r -t "$bufferTTL" line && [[ $SECONDS -lt "$bufferTOD" ]]; do
            # Append line to buffer array
            buffer+=("$line");
-           echo "DEBUG:Processing line:$lineCount";
-           echo "DEBUG:Current line   :$line";
-           echo "DEBUG:buf elem count :${#buffer[@]}";
-           ((lineCount++));
        done;
        # Create dir_tmp if missing
        if ! [[ -d "$dir_tmp" ]]; then yell "ERROR:dir_tmp existence failure:$dir_tmp"; try mkdir "$dir_tmp" && vbm "DEBUG:Working dir recreated dir_tmp:$dir_tmp"; fi