github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/binary/test-fixtures/capture-snippet.sh (about)

     1  #!/bin/bash
     2  
     3  # Default values for length and prefix length
     4  LENGTH=100
     5  PREFIX_LENGTH=20
     6  SEARCH_FOR=''
     7  GROUP_NAME=''
     8  
     9  # Function to show usage
    10  usage() {
    11      echo "Usage: $0 <path-to-binary> <version> [--search-for <pattern>] [--length <length>] [--prefix-length <prefix_length>] [--group <name>]"
    12      exit 1
    13  }
    14  
    15  # Parse arguments
    16  while [[ $# -gt 0 ]]; do
    17      key="$1"
    18  
    19      case $key in
    20  	--search-for)
    21  	    SEARCH_FOR="$2"
    22  	    shift # past argument
    23              shift # past value
    24  	    ;;
    25          --length)
    26              LENGTH="$2"
    27              shift # past argument
    28              shift # past value
    29              ;;
    30          --group)
    31              GROUP_NAME="$2"
    32              shift # past argument
    33              shift # past value
    34              ;;
    35          --prefix-length)
    36              PREFIX_LENGTH="$2"
    37              shift # past argument
    38              shift # past value
    39              ;;
    40          *)
    41              if [ -z "$BINARY_FILE" ]; then
    42                  BINARY_FILE="$1"
    43              elif [ -z "$VERSION" ]; then
    44                  VERSION="$1"
    45              else
    46                  echo "Unknown option: $1"
    47                  usage
    48              fi
    49              shift # past argument
    50              ;;
    51      esac
    52  done
    53  
    54  LENGTH=$(expr "$LENGTH" + "$PREFIX_LENGTH")
    55  
    56  # check if binary file and pattern are provided
    57  if [ -z "$BINARY_FILE" ] || [ -z "$VERSION" ]; then
    58      usage
    59  fi
    60  
    61  # if group name is empty use the binary filename
    62  if [ -z "$GROUP_NAME" ]; then
    63      GROUP_NAME=$(basename "$BINARY_FILE")
    64  fi
    65  
    66  # check if xxd is even installed
    67  if ! command -v xxd &> /dev/null; then
    68      echo "xxd not found. Please install xxd."
    69      exit 1
    70  fi
    71  
    72  
    73  PATTERN=${SEARCH_FOR:-$VERSION}
    74  
    75  echo "Using binary file:      $BINARY_FILE"
    76  echo "Searching for pattern:  $PATTERN"
    77  echo "Capture length:         $LENGTH bytes"
    78  echo "Capture prefix length:  $PREFIX_LENGTH bytes"
    79  
    80  PATTERN_RESULTS=$(strings -t d "$BINARY_FILE" | grep "$PATTERN")
    81  RESULT_COUNT=$(echo "$PATTERN_RESULTS" | wc -l)
    82  
    83  CONTINUE_LOOP=true
    84  
    85  while $CONTINUE_LOOP; do
    86  
    87    # if there are multiple matches, prompt the user to select one
    88    if [ $RESULT_COUNT -gt 1 ]; then
    89        echo "Multiple string matches found in the binary:"
    90        echo ""
    91  
    92        # show result lines one at a time (in a numbered list)
    93        # but only show everything after the first field (not the offset)
    94        echo "$PATTERN_RESULTS" | cut -d ' ' -f 2- | nl -w 1 -s ') '
    95  
    96  
    97        echo ""
    98        read -p "Please select a match: " SELECTION
    99  
   100        # if the selection is not a number, exit
   101        if ! [[ "$SELECTION" =~ ^[0-9]+$ ]]; then
   102            echo "Invalid selection."
   103            exit 1
   104        fi
   105  
   106        # if the selection is out of bounds, exit
   107        if [ "$SELECTION" -gt $(echo "$PATTERN_RESULTS" | wc -l) ]; then
   108            echo "Invalid selection."
   109            exit 1
   110        fi
   111  
   112        # select the line from the results
   113        SELECTED_RESULT=$(echo "$PATTERN_RESULTS" | sed -n "${SELECTION}p")
   114    else
   115      SELECTED_RESULT="$PATTERN_RESULTS"
   116    fi
   117  
   118    # search for the pattern in the binary file and capture the offset
   119    OFFSET=$(echo "${SELECTED_RESULT}" | cut -d ' ' -f 1)
   120  
   121    if [ -z "$OFFSET" ]; then
   122        echo "Pattern not found."
   123        exit 1
   124    fi
   125  
   126    # adjust the offset to capture prefix length before the match
   127    OFFSET=$(expr "$OFFSET" - "$PREFIX_LENGTH")
   128  
   129    # use xxd to capture the specified length from the calculated offset
   130    SNIPPET=$(xxd -l "$LENGTH" -s "$OFFSET" "$BINARY_FILE")
   131  
   132    # display the output and prompt the user
   133    echo ""
   134    echo "$SNIPPET"
   135    echo ""
   136    read -p "Does this snippet capture what you need? (Y/n/q) " RESPONSE
   137  
   138    RESPONSE=${RESPONSE:-y}
   139  
   140    if [ "$RESPONSE" == "y" ]; then
   141      CONTINUE_LOOP=false
   142    elif [ $RESULT_COUNT -eq 1 ] || [ "$RESPONSE" == "q" ]; then
   143      echo "Exiting with no action taken."
   144      exit 0
   145    fi
   146  
   147  done
   148  
   149  go run ./manager write-snippet "$BINARY_FILE" --offset "$OFFSET" --length "$LENGTH" --name "$GROUP_NAME" --version "$VERSION"