github.com/StackExchange/blackbox/v2@v2.0.1-0.20220331193400-d84e904973ab/bin/_stack_lib.sh (about) 1 # Library functions for bash scripts at Stack Exchange. 2 3 # NOTE: This file is open sourced. Do not put Stack-proprietary code here. 4 5 # Usage: 6 # 7 # set -e 8 # . _stack_lib.sh 9 10 # ----- Utility Functions ----- 11 12 function debugmsg() { 13 # Log to stderr. 14 echo 1>&2 LOG: "$@" 15 : 16 } 17 18 function logit() { 19 # Log to stderr. 20 echo 1>&2 LOG: "$@" 21 } 22 23 function fail_out() { 24 echo "FAILED:" "$*" 25 echo 'Exiting...' 26 exit 1 27 } 28 29 # on_exit and add_on_exit from http://www.linuxjournal.com/content/use-bash-trap-statement-cleanup-temporary-files 30 # Usage: 31 # add_on_exit rm -f /tmp/foo 32 # add_on_exit echo "I am exiting" 33 # tempfile=$(mktemp) 34 # add_on_exit rm -f "$tempfile" 35 function on_exit() 36 { 37 for i in "${on_exit_items[@]}" 38 do 39 eval $i 40 done 41 } 42 43 function add_on_exit() 44 { 45 local n=${#on_exit_items[*]} 46 on_exit_items[$n]="$*" 47 if [[ $n -eq 0 ]]; then 48 trap on_exit EXIT 49 fi 50 } 51 52 function create_self_deleting_tempfile() { 53 local filename 54 55 case $(uname -s) in 56 Darwin | FreeBSD ) 57 : "${TMPDIR:=/tmp}" ; 58 filename=$(mktemp -t _stacklib_.XXXXXXXX ) 59 ;; 60 Linux | CYGWIN* | MINGW* | NetBSD | SunOS ) 61 filename=$(mktemp) 62 ;; 63 * ) 64 echo 'ERROR: Unknown OS. Exiting. (create_self_deleting_tempfile)' 65 exit 1 66 ;; 67 esac 68 69 add_on_exit rm -f "$filename" 70 echo "$filename" 71 } 72 73 function create_self_deleting_tempdir() { 74 local filename 75 76 case $(uname -s) in 77 Darwin | FreeBSD ) 78 : "${TMPDIR:=/tmp}" ; 79 filename=$(mktemp -d -t _stacklib_.XXXXXXXX ) 80 ;; 81 Linux | CYGWIN* | MINGW* | NetBSD | SunOS ) 82 filename=$(mktemp -d) 83 ;; 84 * ) 85 echo 'ERROR: Unknown OS. Exiting. (create_self_deleting_tempdir)' 86 exit 1 87 ;; 88 esac 89 90 add_on_exit rm -rf "$filename" 91 echo "$filename" 92 } 93 94 # Securely and portably create a temporary file that will be deleted 95 # on EXIT. $1 is the variable name to store the result. 96 function make_self_deleting_tempfile() { 97 local __resultvar="$1" 98 local name 99 100 case $(uname -s) in 101 Darwin | FreeBSD ) 102 : "${TMPDIR:=/tmp}" ; 103 name=$(mktemp -t _stacklib_.XXXXXXXX ) 104 ;; 105 Linux | CYGWIN* | MINGW* | NetBSD | SunOS ) 106 name=$(mktemp) 107 ;; 108 * ) 109 echo 'ERROR: Unknown OS. Exiting. (make_self_deleting_tempfile)' 110 exit 1 111 ;; 112 esac 113 114 add_on_exit rm -f "$name" 115 eval $__resultvar="$name" 116 } 117 118 function make_tempdir() { 119 local __resultvar="$1" 120 local name 121 122 case $(uname -s) in 123 Darwin | FreeBSD ) 124 : "${TMPDIR:=/tmp}" ; 125 # The full path to the temp directory must be short. 126 # This is used by blackbox's testing suite to make a fake GNUPGHOME, 127 # which needs to fit within sockaddr_un.sun_path (see unix(7)). 128 name=$(mktemp -d -t SO ) 129 ;; 130 Linux | CYGWIN* | MINGW* | NetBSD | SunOS ) 131 name=$(mktemp -d) 132 ;; 133 * ) 134 echo 'ERROR: Unknown OS. Exiting. (make_tempdir)' 135 exit 1 136 ;; 137 esac 138 139 eval $__resultvar="$name" 140 } 141 142 function make_self_deleting_tempdir() { 143 local __resultvar="$1" 144 local dname 145 146 make_tempdir dname 147 148 add_on_exit rm -rf "$dname" 149 eval $__resultvar="$dname" 150 } 151 152 function fail_if_not_running_as_root() { 153 if [[ $EUID -ne 0 ]]; then 154 echo 'ERROR: This command should only be run as root.' 155 echo 'Exiting...' 156 exit 1 157 fi 158 } 159 160 function fail_if_in_root_directory() { 161 # Verify nobody has tricked us into being in "/". 162 case $(uname -s) in 163 Darwin | FreeBSD | NetBSD ) 164 if [[ $(stat -f'%i' / ) == $(stat -f'%i' . ) ]] ; then 165 echo 'SECURITY ALERT: The current directory is the root directory.' 166 echo 'Exiting...' 167 exit 1 168 fi 169 ;; 170 Linux | CYGWIN* | MINGW* | SunOS ) 171 if [[ $(stat -c'%i' / ) == $(stat -c'%i' . ) ]] ; then 172 echo 'SECURITY ALERT: The current directory is the root directory.' 173 echo 'Exiting...' 174 exit 1 175 fi 176 ;; 177 * ) 178 echo 'ERROR: Unknown OS. Exiting. (fail_if_in_root_directory)' 179 exit 1 180 ;; 181 esac 182 } 183 184 function semverParseInto() { 185 local RE='[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)' 186 #MAJOR 187 eval $2=`echo $1 | sed -e "s#$RE#\1#"` 188 #MINOR 189 eval $3=`echo $1 | sed -e "s#$RE#\2#"` 190 #MINOR 191 eval $4=`echo $1 | sed -e "s#$RE#\3#"` 192 #SPECIAL 193 eval $5=`echo $1 | sed -e "s#$RE#\4#"` 194 } 195 196 function semverEQ() { 197 local MAJOR_A=0 198 local MINOR_A=0 199 local PATCH_A=0 200 local SPECIAL_A=0 201 202 local MAJOR_B=0 203 local MINOR_B=0 204 local PATCH_B=0 205 local SPECIAL_B=0 206 207 semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A 208 semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B 209 210 if [ $MAJOR_A -ne $MAJOR_B ]; then 211 return 1 212 fi 213 214 if [ $MINOR_A -ne $MINOR_B ]; then 215 return 1 216 fi 217 218 if [ $PATCH_A -ne $PATCH_B ]; then 219 return 1 220 fi 221 222 if [[ "_$SPECIAL_A" != "_$SPECIAL_B" ]]; then 223 return 1 224 fi 225 226 227 return 0 228 229 } 230 231 function semverLT() { 232 local MAJOR_A=0 233 local MINOR_A=0 234 local PATCH_A=0 235 local SPECIAL_A=0 236 237 local MAJOR_B=0 238 local MINOR_B=0 239 local PATCH_B=0 240 local SPECIAL_B=0 241 242 semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A 243 semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B 244 245 if [ $MAJOR_A -lt $MAJOR_B ]; then 246 return 0 247 fi 248 249 if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -lt $MINOR_B ]]; then 250 return 0 251 fi 252 253 if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -le $MINOR_B && $PATCH_A -lt $PATCH_B ]]; then 254 return 0 255 fi 256 257 if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then 258 return 1 259 fi 260 if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" != "_" ]] ; then 261 return 1 262 fi 263 if [[ "_$SPECIAL_A" != "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then 264 return 0 265 fi 266 267 if [[ "_$SPECIAL_A" < "_$SPECIAL_B" ]]; then 268 return 0 269 fi 270 271 return 1 272 273 } 274 275 function semverGT() { 276 semverEQ $1 $2 277 local EQ=$? 278 279 semverLT $1 $2 280 local LT=$? 281 282 if [ $EQ -ne 0 ] && [ $LT -ne 0 ]; then 283 return 0 284 else 285 return 1 286 fi 287 } 288