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