Advertisement
justin_hanekom

apt-clone-clone.sh

Mar 30th, 2019
226
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 7.87 KB | None | 0 0
  1. #!/bin/bash -
  2.  
  3. # File: apt-clone-clone.sh
  4. # Copyright (c) 2018-2019 Justin Hanekom <justin_hanekom@yahoo.com>
  5. # Licensed under the MIT License
  6.  
  7. # Permission is hereby granted, free of charge, to any person obtaining
  8. # a copy of this software and associated documentation files
  9. # (the "Software"), to deal in the Software without restriction,
  10. # including without limitation the rights to use, copy, modify, merge,
  11. # publish, distribute, sublicense, and/or sell copies of the Software,
  12. # and to permit persons to whom the Software is furnished to do so,
  13. # subject to the following conditions:
  14. #
  15. # The above copyright notice and this permission notice shall be
  16. # included in all copies or substantial portions of the Software.
  17. #
  18. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  21. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  22. # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23. # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  
  26. # Setup a safe Bash scripting environment
  27.  
  28. set -o errexit      # Exit immediately if an error occurs
  29. set -o noclobber    # Do not allow files to be overwritten via redirect
  30. set -o nounset      # Do not allow unset variables
  31.  
  32. # Set the exit code of a pipeline to the rightmost non-zero on error
  33. set -o pipefail
  34. #set -o xtrace       # Trace script execution (i.e., debug mode)
  35. # Set the internal field separator to newline or tab, but not space
  36. IFS=$'\n\t'
  37.  
  38. # Setup a secure Bash scripting environment by: setting a secure path;
  39. # clearing all aliases; clearing the command path hash; setting the hard limit
  40. # to 0 to turn off core dumps; and setting a secure umask
  41.  
  42. PATH=$(PATH='/bin:/usr/bin' getconf PATH); export PATH
  43. builtin unalias -a
  44. hash -r
  45. ulimit -H -c 0 --
  46.  
  47. UMASK=002
  48. umask ${UMASK}
  49.  
  50. # Global constant definitions
  51.  
  52. readonly OPTIONS='u:d:rvh'
  53. readonly LONGOPTS='user:,destdir:,remove,verbose,help'
  54. readonly CLONE_PREFIX='mint_'
  55. readonly TEMP_PREFIX='apt-clone-clone.'
  56. readonly TIMESTAMP=$(date '+%Y%m%d%H%M%S')
  57. readonly STARTED_AT=$(date '+%s')
  58.  
  59. # Global variable declarations
  60.  
  61. USER_NAME=''
  62. DEST_DIR=''
  63. IS_VERBOSE=''
  64. IS_REMOVE=''
  65.  
  66. ################################################################################
  67. # Function:     chomp_slash
  68. # Description:  Removes any trailing slash ("/") from a string
  69. # Arguments:    $1 :- String from which to remove any trailing slashes
  70. # Ouputs:       Prints string with trailing slashes removed
  71. function chomp_slash {
  72.     local dir="$1"
  73.     while [ "${dir:(-1)}" = '/' ]; do
  74.         dir=${dir::-1}
  75.     done
  76.     echo "${dir}"
  77. }
  78.  
  79. ################################################################################
  80. # Function:     echo_if_verbose
  81. # Description:  Prints $@ if IS_VERBOSE is not empty
  82. # Arguments:    $@ :- Content to echo if ${IS_VERBOSE} is not empty
  83. # Requires:     ${IS_VERBOSE} set to a non-empty string if verbose is on
  84. # Outputs:      Prints $@ if ${IS_VERBOSE} is not empty
  85. function echo_if_verbose {
  86.     if [ -n "${IS_VERBOSE}" ]; then
  87.         echo "$@"
  88.     fi
  89. }
  90.  
  91. ################################################################################
  92. # Function:     trim
  93. # Description:  Trims any/all whitespace from the beginning and end of a string
  94. # Arguments:    $1 :- The string from which to trim whitespace
  95. # Outputs:      Prints string with any leading/trailing whitespace removed
  96. function trim {
  97.     local str="$1"
  98.     str="${str#"${str%%[![:space:]]*}"}"
  99.    str="${str%"${str##*[![:space:]]}"}"
  100.     echo "$1"
  101. }
  102.  
  103. ################################################################################
  104. # Function:     usage_exit
  105. # Description:  Prints the usage message for this script and then exits
  106. # Arguments:    $1 :- Exit code; defaults to 1
  107. # Outputs:      Prints description of how to call this script
  108. function usage_exit {
  109.     local exit_code=1
  110.  
  111.     if [[ ${1-} =~ ^[0-9]+$ ]]; then
  112.         exit_code="$1"
  113.     fi
  114.  
  115.     cat << EOT
  116. Usage: $(basename "$0") [options]...
  117.     -u|--user       <val>   (Required) The owner of the generated clone file
  118.     -d|--destdir    <val>   (Required) The dir into which to save the new file
  119.     -r|--remove             Causes previous apt-clone files to be removed
  120.     -v|--verbose            Displays verbose output
  121.     -h|--help               Displays this message and aborts the script
  122.  
  123. NOTE: The <user> and <destdir> arguments are mandatory and *must* be supplied
  124.  
  125. EOT
  126.     exit "${exit_code}"
  127. }
  128.  
  129. ################################################################################
  130. # Function:     parse_cmdline
  131. # Description:  Parses the command-line using the enhanced version of getopt
  132. # Arguments:    $@ :- Command-line arguments (required)
  133. # Requires:     Global variables $USER_NAME, $DEST_DIR, $IS_REMOVE, and
  134. #               $IS_VERBOSE
  135. # Outputs:      Sets above-mentioned global variables based on given
  136. #               command-line arguments
  137. function parse_cmd_line {
  138.     # Ensure that the enhanced version of getopt is available
  139.  
  140.     ! getopt --test > /dev/null
  141.     if (( "${PIPESTATUS[0]}" != 4 )); then
  142.         echo "I'm sorry, the enhanced version of getopt is required. Exiting." >&2
  143.         exit 1
  144.     fi
  145.  
  146.     # Initialize the global variables
  147.  
  148.     USER_NAME=''
  149.     DEST_DIR=''
  150.     IS_VERBOSE=''
  151.     IS_REMOVE=''
  152.  
  153.     # Parse the command-line options
  154.  
  155.     if ! readonly PARSED_OPTIONS=$(getopt --options=${OPTIONS} \
  156.                                     --longoptions=${LONGOPTS} \
  157.                                     --name "$(basename "$0")" -- "$@"); then
  158.         echo 'Unknown error parsing getopt options. Exiting.' >&2
  159.         exit 2
  160.     fi
  161.  
  162.     eval set -- "${PARSED_OPTIONS}"
  163.  
  164.     # Extract and validate command-line options and their arguments, if any
  165.  
  166.     while (( $# >= 1 )); do
  167.         case "$1" in
  168.             -u|--user)
  169.                 USER_NAME=$(trim "$2") ; shift 2
  170.                 ;;
  171.             -d|--destdir)
  172.                 DEST_DIR=$(chomp_slash "$(trim "$2")") ; shift 2
  173.                 ;;
  174.             -r|--remove)
  175.                 IS_REMOVE='true' ; shift
  176.                 ;;
  177.             -v|--verbose)
  178.                 IS_VERBOSE='true' ; shift
  179.                 ;;
  180.             -h|--help)
  181.                 usage_exit 0
  182.                 ;;
  183.             --)
  184.                 shift ; break
  185.                 ;;
  186.             *)
  187.                 usage_exit 3 >&2
  188.                 ;;
  189.         esac
  190.     done
  191.  
  192.     # Ensure that required options have been supplied
  193.  
  194.     if [[ -z "${USER_NAME}" || -z "${DEST_DIR}" ]]; then
  195.         usage_exit 4 >&2
  196.     fi
  197. } # parse_cmd_line
  198.  
  199. ################################################################################
  200. # Start of program
  201.  
  202. parse_cmd_line "$@"
  203. readonly DEST_FILENAME=${DEST_DIR}/${CLONE_PREFIX}${TIMESTAMP}
  204.  
  205. # Optionally remove any previous apt-clone clone file
  206.  
  207. if [ -n "${IS_REMOVE}" ]; then
  208.     rm --force "${DEST_DIR}"/${CLONE_PREFIX}*apt-clone* &>/dev/null
  209.     echo_if_verbose "Removed: ${DEST_DIR}/${CLONE_PREFIX}*apt-clone*"
  210. fi
  211.  
  212. # Perform apt-clone clone
  213.  
  214. apt-clone clone "${DEST_FILENAME}" &>/dev/null
  215. echo_if_verbose "Performed apt-clone clone to: ${DEST_FILENAME}"
  216.  
  217. # Change the owner of the generated apt-clone output file
  218.  
  219. sudo chown "${USER_NAME}":"${USER_NAME}" \
  220.     "${DEST_DIR}"/"${CLONE_PREFIX}"*apt-clone* &>/dev/null
  221. echo_if_verbose "Changed owner of: ${DEST_DIR}/${CLONE_PREFIX}*apt-clone* \
  222. to: ${USER_NAME}"
  223.  
  224. # Report that we are done, and how long the script took
  225.  
  226. if [ -n "$IS_VERBOSE" ]; then
  227.     readonly ENDED_AT=$(date '+%s')
  228.     readonly DIFF=$(( ENDED_AT - STARTED_AT ))
  229.     echo "Done, in ${DIFF} seconds"!
  230. fi
  231.  
  232. # vim: set filetype=sh smartindent autoindent smarttab expandtab tabstop=4 softtabstop=4 shiftwidth=4 autoread
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement