├── README.md ├── build_dm.sh └── install.sh /README.md: -------------------------------------------------------------------------------- 1 | Microsoft SQL Server ODBC Driver 1.0 for Linux Fixed Install Scripts 2 | ====================================================================== 3 | 4 | I named this repository in hopes that SEO would help it out a bit. One 5 | of my most popular posts on my blog is a how to detailing the steps 6 | needed for installing the Microsoft SQL Server ODBC Driver for linux 7 | on Ubuntu. Why is an install tutorial/how-to necessary? Because 8 | Microsoft released some half-baked install scripts. 9 | 10 | The shell scripts they include contain the Microsoft Copyright, so I'm 11 | not sure of the license - which is why I didn't choose one for this 12 | repository - I just want the changes I made to be available to those 13 | that need them. 14 | 15 | If you're seeing this Microsoft - please feel free to use any of this 16 | in your own distributions. It's painful to see half-baked install 17 | scripts when so little work is necessary to support so much more of 18 | your audience. 19 | 20 | These are just some adjusted scripts to work on Debian/Ubuntu servers. 21 | These are tested working on Ubuntu 12.04 and 14.04 LTS - and they're supposed to 22 | work out of the box on Red Hat Enterprise Linux 6 though I do not 23 | have access to an actual Red Hat Enterprise Linux 6 system so I've not 24 | 100% tested their stated functionality. Running on 25 | [dash](http://en.wikipedia.org/wiki/Debian_Almquist_shell) the hashbang 26 | needed to change to bash in order to support the array syntax used. 27 | 28 | `install_dm.sh` is adjusted to pull [unixODBC](http://www.unixodbc.org/) 29 | version 2.3.2 from the web. Once the driver is installed, don't forget to enable Multiple Active Result-sets (MARS) in your ODBC connection as that's a great feature that this driver provides. `MARS_Connection = Yes` 30 | 31 | 32 | ##Usage 33 | 34 | ###unixODBC Driver Manager Install - build_dm.sh 35 | 36 | ``` 37 | $ sudo ./build_dm.sh --libdir=/usr/lib/x86_64-linux-gnu 38 | ``` 39 | 40 | You can also pass a path to where you've placed a gzipped tarball of 41 | unixODBC (including newer versions) using the `--download-url` parameter: 42 | 43 | ``` 44 | $ sudo ./build_dm.sh --download-url=file:///home/MYUSER/unixODBC-2.3.2.tar.gz --libdir=/usr/lib/x86_64-linux-gnu 45 | ``` 46 | 47 | ###SQL Server ODBC Driver Installer - install.sh 48 | 49 | For the driver installer - `install.sh` - `install`, `verify`, `--force`, `--force-debian`, `--force-redhat`, and `--help` 50 | are available parameters: 51 | 52 | ``` 53 | $ sudo ./install.sh install 54 | ``` 55 | 56 | If you are using a Debian based/compatible distribution that is not detected properly (the current list is Debian, 57 | Ubuntu, and LinuxMint), you may want to use the `--force-debian` install flag like this: 58 | 59 | ``` 60 | $ sudo ./install.sh install --force-debian 61 | ``` 62 | 63 | You can use verify to check the status of an existing installation: 64 | 65 | ``` 66 | $ sudo ./install.sh verify 67 | ``` 68 | -------------------------------------------------------------------------------- /build_dm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Microsoft SQL Server ODBC Driver V1.0 for Linux Build unixODBC DriverManager script 3 | # Copyright Microsoft Corp. 4 | 5 | # driver name 6 | driver_name="Microsoft SQL Server ODBC Driver V1.0 for Linux" 7 | 8 | # required constants 9 | req_os="Linux"; 10 | req_proc="x86_64"; 11 | req_software=( "wget" "tar" "make" ) 12 | 13 | # Create a temp directory for intermediate files 14 | tmp=${TMPDIR-/tmp} 15 | tmp=$tmp/"unixODBC".$RANDOM.$RANDOM.$RANDOM 16 | (umask 077 && mkdir $tmp) || { 17 | echo "Could not create temporary directory for the log file." 2>&1 18 | exit 1 19 | } 20 | 21 | # driver manager constants 22 | dm_name="unixODBC 2.3.2 DriverManager" 23 | dm_dir="unixODBC-2.3.2" 24 | dm_package='unixODBC-2.3.2.tar.gz' 25 | dm_url="ftp://ftp.unixodbc.org/pub/unixODBC/$dm_package" 26 | dm_package_path=$tmp/$dm_package 27 | dm_build_msg="" 28 | 29 | libdir='/usr/lib64' 30 | prefixdir='/usr' 31 | sysconfdir='/etc' 32 | 33 | log_file=$tmp/build_dm.log 34 | 35 | # warning accepted by user or overridden by command line option 36 | warning_accepted=0 37 | 38 | function log() 39 | { 40 | local msg=$*; 41 | local date=$(date); 42 | echo "["$date"]" $msg >> $log_file 43 | } 44 | 45 | # format a message and status for an 80 character terminal 46 | # this assumes the msg has already been output and this used 47 | # only for printing the status correctly 48 | function echo_status_aligned 49 | { 50 | local msg=$1 51 | local status=$2 52 | # 2 spaces in between the status and the message 53 | local total_len=$(( ${#msg} + ${#status} + 2 )) 54 | 55 | if [ $total_len -gt 80 ]; then 56 | echo "Cannot show a message longer than 80 characters" 57 | exit 1 58 | fi 59 | 60 | local dots="................................................................................" 61 | local dot_count=$(( 80 - $total_len )) 62 | 63 | local status_msg=" $(expr substr "$dots" 1 $dot_count) $status" 64 | echo $status_msg 65 | 66 | return 0 67 | } 68 | 69 | # verify that the installation is on a 64 bit OS 70 | function check_for_Linux_x86_64 () 71 | { 72 | log "Verifying if on a 64 bit Linux compatible OS" 73 | 74 | local proc=$(uname -m); 75 | if [ $proc != $req_proc ]; then 76 | log "This installation of the" $dm_name "may only be installed" 77 | log "on a 64 bit Linux compatible operating system." 78 | return 1; 79 | fi 80 | 81 | local os=$(uname -s); 82 | if [ $os != $req_os ]; then 83 | log "This installation of the" $dm_name "may only be installed" 84 | log "on a 64 bit Linux compatible operating system." 85 | return 1; 86 | fi 87 | 88 | return 0; 89 | } 90 | 91 | 92 | function check_wget 93 | { 94 | log "Checking that wget is installed" 95 | 96 | # if using a file url, wget is not necessary 97 | if [ "${dm_url##file://}" != "$dm_url" ]; then 98 | return 0; 99 | fi 100 | 101 | hash wget &> /dev/null 102 | if [ $? -eq 1 ]; then 103 | log "'wget' required to download $dm_name" 104 | return 1; 105 | fi 106 | 107 | return 0 108 | } 109 | 110 | function check_tar 111 | { 112 | log "Checking that tar is installed" 113 | 114 | hash tar &> /dev/null 115 | if [ $? -eq 1 ]; then 116 | log "'tar' required to unpack $dm_name" 117 | return 1; 118 | fi 119 | 120 | return 0 121 | } 122 | 123 | function check_make 124 | { 125 | log "Checking that make is installed" 126 | 127 | hash make &> /dev/null 128 | if [ $? -eq 1 ]; then 129 | log "'make' required to build $dm_name" 130 | return 1; 131 | fi 132 | 133 | return 0 134 | } 135 | 136 | 137 | function download 138 | { 139 | log "Downloading $dm_url" 140 | 141 | # if they use a file:// url then just point the package at that path and return 142 | # since wget doesn't support file urls 143 | if [ ${dm_url##file://} != $dm_url ]; then 144 | dm_package_path=${dm_url##file://} 145 | dm_dir=`tar tzf $dm_package_path | head -1 | sed -e 's/\/.*//'` 146 | dm_name="Custom unixODBC $dm_dir" 147 | log "Using $dm_name" 148 | make_build_msg 149 | return 0 150 | fi 151 | 152 | $(wget -a $log_file -P $tmp $dm_url ) 153 | 154 | if [ ! -e $dm_package_path ]; then 155 | log "Failed to retrieve $dm_name from $dm_url." 156 | return 1; 157 | fi 158 | 159 | return 0 160 | } 161 | 162 | function unpack 163 | { 164 | log "Unpacking $dm_package_path to $tmp" 165 | 166 | $(tar --directory=$tmp -xvzf $dm_package_path >> $log_file 2>&1) 167 | 168 | if [ $? -ne 0 ]; then 169 | log "Unpacking $dm_package_path failed." 170 | return 1 171 | fi 172 | 173 | return 0 174 | } 175 | 176 | function configure_dm 177 | { 178 | log "Configuring" 179 | 180 | # As per https://msdn.microsoft.com/en-US/library/hh568449(v=sql.110).aspx 181 | # we set this here rather than at the top to delay the eval of 182 | # the variables in the string 183 | local config_options=( 184 | "--enable-gui=no" 185 | "--enable-drivers=no" 186 | "--enable-iconv" 187 | "--with-iconv-char-enc=UTF8" 188 | "--with-iconv-ucode-enc=UTF16LE" 189 | "--libdir=$libdir" 190 | "--prefix=$prefixdir" 191 | "--sysconfdir=$sysconfdir" 192 | "CPPFLAGS=-DSIZEOF_LONG_INT=8" 193 | ) 194 | 195 | $(cd $tmp/$dm_dir >> $log_file 2>&1; ./configure ${config_options[@]} >> $log_file 2>&1) 196 | 197 | if [ $? -ne 0 ]; then 198 | log "Failed to configure $dm_name" 199 | return 1 200 | fi 201 | 202 | return 0 203 | } 204 | 205 | function make_dm 206 | { 207 | log "Building" 208 | 209 | $(cd $tmp/$dm_dir >> $log_file 2>&1 ; make >> $log_file 2>&1) 210 | 211 | if [ $? -ne 0 ]; then 212 | log "Failed to make $dm_name" 213 | return 1 214 | fi 215 | 216 | return 0 217 | } 218 | 219 | function install_dm 220 | { 221 | log "Installing" 222 | 223 | $(cd $tmp/$dm_dir >> $log_file 2>&1 ; make install >> $log_file 2>&1) 224 | 225 | if [ $? -ne 0 ]; then 226 | log "Failed to make install $dm_name" 227 | return 1 228 | fi 229 | 230 | return 0 231 | } 232 | 233 | function make_build_msg 234 | { 235 | dm_build_msg=( 236 | "Verifying processor and operating system" 237 | "Verifying wget is installed" 238 | "Verifying tar is installed" 239 | "Verifying make is installed" 240 | "Downloading $dm_name" 241 | "Unpacking $dm_name" 242 | "Configuring $dm_name" 243 | "Building $dm_name" 244 | "Installing $dm_name" 245 | ) 246 | } 247 | 248 | function build 249 | { 250 | local build_steps=( check_for_Linux_x86_64 check_wget check_tar check_make download unpack configure_dm make_dm install_dm ) 251 | make_build_msg 252 | local build_neutral=( "NOT ATTEMPTED" "NOT ATTEMPTED" "NOT ATTEMPTED" "NOT ATTEMPTED" "NOT ATTEMPTED" "NOT ATTEMPTED" "NOT ATTEMPTED" "NOT ATTEMPTED" "NOT ATTEMPTED" ) 253 | local build_success=( 'OK' 'OK' 'OK' 'OK' 'OK' 'OK' 'OK' 'OK' 'OK' ) 254 | local build_fail=( 'FAILED' 'FAILED' 'FAILED' 'FAILED' 'FAILED' 'FAILED' 'FAILED' 'FAILED' 'FAILED' ) 255 | 256 | # asserts for the arrays above 257 | if [ ${#build_steps[@]} -ne ${#dm_build_msg[@]} ]; then 258 | echo "Build steps and build message array out of sync" 259 | exit 1 260 | fi 261 | 262 | if [ ${#build_steps[@]} -ne ${#build_neutral[@]} ]; then 263 | echo "Build steps and build message array out of sync" 264 | exit 1 265 | fi 266 | 267 | if [ ${#build_steps[@]} -ne ${#build_success[@]} ]; then 268 | echo "Build steps and build message array out of sync" 269 | exit 1 270 | fi 271 | 272 | if [ ${#build_steps[@]} -ne ${#build_fail[@]} ]; then 273 | echo "Build steps and build message array out of sync" 274 | exit 1 275 | fi 276 | 277 | local status=0 278 | 279 | for (( i = 0; i < ${#build_steps[@]}; i++ )) 280 | do 281 | 282 | local fn=${build_steps[$i]} 283 | local status_msg="${build_neutral[$i]}" 284 | 285 | echo -n "${dm_build_msg[$i]} " 286 | 287 | if [ $status -eq 0 ]; then 288 | 289 | $fn 290 | 291 | if [ $? -ne 0 ]; then 292 | status_msg="${build_fail[$i]}" 293 | status=1 294 | else 295 | status_msg="${build_success[$i]}" 296 | fi 297 | fi 298 | 299 | echo_status_aligned "${dm_build_msg[$i]} " "$status_msg" 300 | 301 | done 302 | 303 | return $status 304 | } 305 | 306 | function print_usage 307 | { 308 | echo "Usage: build_dm.sh [options]" 309 | echo 310 | echo "This script downloads, configures, builds and installs $dm_name" 311 | echo 312 | echo "Valid options are --help, --download-url, --prefix, --libdir, --sysconfdir, --accept-warning" 313 | echo " --help - prints this message" 314 | echo " --download-url=url | file:// - Specify the location (and name) of unixODBC-2.3.0.tar.gz." 315 | echo " For example, if unixODBC-2.3.0.tar.gz is in the current directory, specify " 316 | echo " --download-url=file://unixODBC-2.3.0.tar.gz." 317 | echo " --prefix - directory to install $dm_package to." 318 | echo " --libdir - directory where ODBC drivers will be placed" 319 | echo " --sysconfdir - directory where $dm_name configuration files are placed" 320 | echo " --accept-warning - indicate that you have read and accept the warning to download the file" 321 | echo 322 | 323 | # prevent the script from continuing 324 | exit 0 325 | } 326 | 327 | function approve_download 328 | { 329 | log "Accept the WARNING about download of unixODBC" 330 | 331 | if [ ! -f "./WARNING" ]; then 332 | log "WARNING file not found." 333 | echo "Cannot display download warning. Please refer to the original archive for the" 334 | echo "WARNING file and then use the --accept-warning option to run this script." 335 | exit 1 336 | fi 337 | 338 | hash more &> /dev/null 339 | 340 | if [ $? -ne 0 ]; then 341 | log "more program not found. Cannot display the build warning without more." 342 | echo "Cannot display license agreement. Please read the license agreement in LICENSE and" 343 | echo "re-run the install with the --accept-license parameter." 344 | exit 1 345 | fi 346 | 347 | more ./WARNING 348 | 349 | echo 350 | read -p "Enter 'YES' to have this script continue: " accept 351 | echo 352 | 353 | if [ "$accept" == "YES" ]; then 354 | log "Warning accepted" 355 | warning_accepted=1 356 | return 0 357 | fi 358 | 359 | log "Warning not accepted" 360 | echo "Exiting because warning not accepted" 361 | exit 1 362 | } 363 | 364 | echo 365 | echo "Build and Install $dm_name script" 366 | echo "Copyright Microsoft Corp." 367 | echo 368 | 369 | while [ "$1" ] 370 | do 371 | case "$1" in 372 | --download-url=*) 373 | dm_url=${1##--download-url=} 374 | log "$dm_name URL: $dm_url" 375 | ;; 376 | --prefix=*) 377 | prefixdir=${1##--prefix=} 378 | log "Installing $dm_name to $prefixdir" 379 | ;; 380 | --libdir=*) 381 | libdir=${1##--libdir=} 382 | log "Drivers configured to be placed at $libdir" 383 | ;; 384 | --sysconfdir=*) 385 | sysconfdir=${1##--sysconfdir=} 386 | log "Configuration directory set to $sysconfdir" 387 | ;; 388 | --help) 389 | print_usage 390 | ;; 391 | --accept-warning) 392 | warning_accepted=1 393 | ;; 394 | *) 395 | echo "Unknown option $1" 396 | print_usage 397 | exit 1 398 | ;; 399 | esac 400 | shift 401 | done 402 | 403 | echo "PLEASE NOTE THAT THIS WILL POTENTIALLY INSTALL THE NEW DRIVER MANAGER OVER ANY" 404 | echo "EXISTING UNIXODBC DRIVER MANAGER. IF YOU HAVE ANOTHER COPY OF UNIXODBC INSTALLED," 405 | echo "THIS MAY POTENTIALLY OVERWRITE THAT COPY." 406 | echo 407 | read -p "Would you like to proceed? (YES/NO): " accept 408 | echo 409 | 410 | if [ "$accept" == "YES" ]; then 411 | log "Accepted overwrite warning." 412 | else 413 | log "Declined overwrite warning." 414 | echo "The script is now ending and no actions will be taken." 415 | echo 416 | exit 0 417 | fi 418 | 419 | if [ $warning_accepted -ne 1 ]; then 420 | approve_download 421 | fi 422 | 423 | build $* 424 | 425 | if [ $? -ne 0 ]; then 426 | echo "Errors occurred. See the $log_file file for more details." 427 | exit 1 428 | fi 429 | 430 | echo "Successfully installed $dm_name. Please see $log_file for additional information." 431 | 432 | exit 0 433 | 434 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Microsoft ODBC Driver 11 for SQL Server Installer 3 | # Copyright Microsoft Corp. 4 | 5 | # Set to 1 for debugging information/convenience. 6 | debug=0 7 | 8 | # Strings listed here 9 | driver_name="Microsoft ODBC Driver 11 for SQL Server"; 10 | driver_version="11.0.2270.0" 11 | driver_dm_name="ODBC Driver 11 for SQL Server" 12 | driver_short_name="msodbcsql" 13 | 14 | 15 | # Requirements listed here 16 | req_os="Linux"; 17 | req_proc="x86_64"; 18 | req_dm_ver="2.3.2"; 19 | dm_name="unixODBC $req_dm_ver"; 20 | os_dist_id=`lsb_release -is` 21 | is_this_debian_based="/etc/debian_version" 22 | 23 | req_libs="" 24 | real_deb_req_libs=( "libc6" "libkrb5-3" "e2fsprogs" "openssl" ) 25 | 26 | #this should get renamed to ubuntu_req_libs or something 27 | deb_req_libs=( '~i"^libc6$"' '~i"libkrb5\-[0-9]$"' '~i"^e2fsprogs$"' '~i"^openssl$"' ) 28 | 29 | red_req_libs=( glibc e2fsprogs krb5-libs openssl ) 30 | 31 | if [ $os_dist_id == "Ubuntu" ] || [ $os_dist_id == "Debian" ] || [ $os_dist_id == "LinuxMint" ] || [ -e "$is_this_debian_based" ]; then 32 | hash aptitude &> /dev/null 33 | has_aptitude=$? 34 | if [ $os_dist_id == "Ubuntu" ] || [ $os_dist_id == "LinuxMint" ] || [ $has_aptitude -eq 0 ]; then 35 | req_libs=("${deb_req_libs[@]}") 36 | else 37 | req_libs=("${real_deb_req_libs[@]}") 38 | fi 39 | else 40 | req_libs=("${red_req_libs[@]}") 41 | fi 42 | 43 | #language of the install 44 | lang_id="en_US"; 45 | 46 | # files to be copied by directory 47 | driver_file="libmsodbcsql-11.0.so.2270.0" 48 | 49 | lib_files=( "lib64/$driver_file" ) 50 | lib_perms=( 0755 ) 51 | 52 | bin_files=( "bin/bcp-11.0.2270.0" 53 | "bin/sqlcmd-11.0.2270.0" ) 54 | bin_sym=( bcp sqlcmd ) 55 | bin_perms=( 0755 0755 ) 56 | 57 | sup_files=( install.sh build_dm.sh README LICENSE WARNING ) 58 | sup_perms=( 0755 0755 0644 0644 0644 ) 59 | 60 | rll_files=( "bin/bcp.rll" 61 | "bin/SQLCMD.rll" 62 | "bin/BatchParserGrammar.dfa" 63 | "bin/BatchParserGrammar.llr" 64 | "lib64/msodbcsqlr11.rll" ) 65 | rll_perms=( 0644 0644 0644 0644 0644 ) 66 | 67 | doc_files=( "docs/en_US.tar.gz" ) 68 | doc_perms='$(printf "0644 %.0s" {1..'${#doc_files[@]}'})' 69 | doc_perms=( $(eval "echo $doc_perms") ) 70 | 71 | inc_files=( "include/msodbcsql.h" ) 72 | inc_perms='$(printf "0644 %.0s" {1..'${#inc_files[@]}'})' 73 | inc_perms=( $(eval "echo $inc_perms") ) 74 | 75 | dirs=( bin_dir lib_dir sup_dir rll_dir doc_dir inc_dir ) 76 | sym_dirs=( bin_sym_dir lib_sym_dir sup_sym_dir rll_sym_dir doc_sym_dir inc_sym_dir ) 77 | file_sets=( bin_files lib_files sup_files rll_files doc_files inc_files ) 78 | link_sets=( bin_sym "null" "null" "null" "null" "null" ) 79 | file_perm_sets=( bin_perms lib_perms sup_perms rll_perms doc_perms inc_perms ) 80 | link_perm_sets=( bin_perms lib_perms sup_perms rll_perms doc_perms inc_perms ) 81 | 82 | # "assertions" that the file and sym link arrays are sane 83 | if [ ${#lib_files[@]} -ne ${#lib_perms[@]} ]; then 84 | echo "Lib files and permission sets don't match" 85 | exit 1; 86 | fi 87 | if [ ${#bin_files[@]} -ne ${#bin_sym[@]} ]; then 88 | echo "Bin files and sym links don't match" 89 | exit 1; 90 | fi 91 | if [ ${#bin_files[@]} -ne ${#bin_perms[@]} ]; then 92 | echo "Bin files and permission sets don't match" 93 | exit 1; 94 | fi 95 | if [ ${#sup_files[@]} -ne ${#sup_perms[@]} ]; then 96 | echo "Supplemental files and permission sets don't match" 97 | exit 1; 98 | fi 99 | if [ ${#rll_files[@]} -ne ${#rll_perms[@]} ]; then 100 | echo "RLL files and permission sets don't match" 101 | exit 1; 102 | fi 103 | if [ ${#dirs[@]} -ne ${#file_sets[@]} ]; then 104 | echo "Directories and file sets don't match" 105 | exit 1; 106 | fi 107 | if [ ${#file_sets[@]} -ne ${#link_sets[@]} ]; then 108 | echo "File and link sets don't match" 109 | exit 1; 110 | fi 111 | if [ ${#file_sets[@]} -ne ${#file_perm_sets[@]} ]; then 112 | echo "File and permission sets don't match" 113 | exit 1; 114 | fi 115 | if [ ${#link_sets[@]} -ne ${#link_perm_sets[@]} ]; then 116 | echo "Link and permission sets don't match" 117 | exit 1; 118 | fi 119 | if [ ${#doc_files[@]} -ne ${#doc_perms[@]} ]; then 120 | echo "Doc files and permission sets don't match" 121 | exit 1; 122 | fi 123 | if [ ${#inc_files[@]} -ne ${#inc_perms[@]} ]; then 124 | echo "Include files and permission sets don't match" 125 | exit 1; 126 | fi 127 | 128 | # directories to hold the file categories 129 | bin_dir=""; 130 | lib_dir=""; 131 | sup_dir="/opt/microsoft/$driver_short_name/$driver_version"; 132 | rll_dir=""; 133 | doc_dir=""; 134 | inc_dir=""; 135 | 136 | # Force installation flag (--force parameter) default is not to force 137 | force=0 138 | 139 | # Accept the license flag (--accept-license) default is that they must accept the license via a prompt 140 | license_accepted=0 141 | 142 | # Log file in the temp directory 143 | tmp=${TMPDIR-/tmp} 144 | tmp="$tmp/$driver_short_name.$RANDOM.$RANDOM.$RANDOM" 145 | (umask 077 && mkdir $tmp) || { 146 | echo "Could not create temporary directory for the log file." 2>&1 147 | exit 1 148 | } 149 | log_file=$tmp/install.log 150 | 151 | # for debugging purposes 152 | [ $debug -eq 1 ] && log_file="install.log" 153 | [ $debug -eq 1 ] && rm -f install.log 154 | 155 | echo 156 | echo "$driver_name Installation Script" 157 | echo "Copyright Microsoft Corp." 158 | echo 159 | echo "Starting install for $driver_name" 160 | echo 161 | 162 | 163 | function print_usage() 164 | { 165 | echo "Usage: install.sh [global options] command [command options]" 166 | echo 167 | echo "Global options:" 168 | echo " --help - prints this message" 169 | echo "Valid commands are verify and install" 170 | echo " install) install the driver (also verifies before installing and registers" 171 | echo " with the driver manager)" 172 | echo " verify) check to make sure the unixODBC DriverManager configuration is" 173 | echo " correct before installing" 174 | echo "install command take the following options:" 175 | echo " --bin-dir= - location to create symbolic links for bcp and sqlcmd utilities," 176 | echo " defaults to the /usr/bin directory" 177 | echo " --lib-dir= - location to deposit the Microsoft SQL Server ODBC Driver for Linux," 178 | echo " defaults to the /opt/microsoft/msodbcsql/lib directory" 179 | echo " --force - continues installation even if an error occurs" 180 | echo " --accept-license - forgoes showing the EULA and implies agreement with its contents" 181 | echo " --force-debian - forces the install to continue as a debian based/compatible linux distribution" 182 | echo " --force-ubuntu - forces the install to continue as a ubuntu based/compatible linux distribution" 183 | echo " --force-redhat - forces the install to continue as a redhat based/compatible linux distribution" 184 | echo 185 | 186 | # don't return if we're printing the usage 187 | exit 0; 188 | } 189 | 190 | function log() 191 | { 192 | local msg=$*; 193 | local date=$(date); 194 | echo "["$date"]" $msg >> $log_file 195 | } 196 | 197 | # format a message and status for an 80 character terminal 198 | function format_status 199 | { 200 | local msg=$1 201 | local status=$2 202 | # 2 spaces in between the status and the message 203 | local total_len=$(( ${#msg} + ${#status} + 2 )) 204 | 205 | if [ $total_len -gt 80 ]; then 206 | echo "Cannot show a message longer than 80 characters" 207 | exit 1 208 | fi 209 | 210 | local dots="................................................................................" 211 | local dot_count=$(( 80 - $total_len )) 212 | 213 | local full_msg="$msg $(expr substr "$dots" 1 $dot_count) $status" 214 | echo $full_msg 215 | 216 | return 0 217 | } 218 | 219 | function report_config() 220 | { 221 | format_status "Checking for 64 bit Linux compatible OS" "$1" 222 | format_status "Checking required libs/locale(en_US.utf8) are installed" "$2" 223 | format_status "unixODBC utilities (odbc_config and odbcinst) installed" "$3" 224 | format_status "unixODBC Driver Manager version $req_dm_ver installed" "$4" 225 | format_status "unixODBC Driver Manager configuration correct" "$5" 226 | format_status "$driver_name already installed" "$6" 227 | } 228 | 229 | # verify that the installation is on a 64 bit OS 230 | function check_for_Linux_x86_64 () 231 | { 232 | log "Verifying on a 64 bit Linux compatible OS" 233 | local proc=$(uname -m); 234 | # bash string bugs: http://www.tldp.org/LDP/abs/html/comparison-ops.html 235 | if [[ "x$proc" != "x$req_proc" ]]; then 236 | log "This installation of the $driver_name may only be installed" 237 | log "on a 64 bit Linux compatible operating system." 238 | return 1; 239 | fi 240 | 241 | local os=$(uname -s); 242 | if [ $os != $req_os ]; then 243 | log "This installation of the $driver_name may only be installed" 244 | log "on a 64 bit Linux compatible operating system." 245 | return 1; 246 | fi 247 | 248 | return 0; 249 | } 250 | 251 | # verify required locale is present 252 | function check_required_locale 253 | { 254 | log "Checking that required locales are installed" 255 | has_en_utf8_locale=$(locale -a | grep "en_US.utf8") 256 | if [ -z ${has_en_utf8_locale} ]; then 257 | log "The en_US.utf8 locale is required. Please add the locale to your system before continuing." 258 | log "Adding locales can be as simple as 'sudo locale-gen en_US.utf8 && sudo dpkg-reconfigure locales'." 259 | log "Please see your distribution's manual for more details regarding adding locales." 260 | return 1; 261 | fi 262 | } 263 | 264 | # verify that the required libs are on the system 265 | function check_required_libs 266 | { 267 | log "Checking that required libraries are installed" 268 | 269 | for lib in ${req_libs[@]} 270 | do 271 | hash rpm &> /dev/null 272 | has_rpm=$? 273 | hash aptitude &> /dev/null 274 | has_aptitude=$? 275 | hash dpkg &> /dev/null 276 | has_dpkg=$? 277 | local present="" 278 | if [ $has_rpm -eq 0 ]; then 279 | log "Checking for $lib" 280 | present=$(rpm -q -a $lib) >> $log_file 2>&1 281 | elif [ $has_aptitude -eq 0 ]; then 282 | log "Checking for $lib" 283 | present=$(aptitude search $lib ) >> $log_file 2>&1 284 | elif [ $has_dpkg -eq 0 ]; then 285 | present=$(dpkg --get-selections $lib ) >> $log_file 2>&1 286 | fi 287 | if [ "$present" == "" ]; then 288 | log "The $lib library was not found installed in the RPM database." 289 | log "See README for which libraries are required for the $driver_name." 290 | return 1; 291 | fi 292 | done 293 | 294 | return 0; 295 | } 296 | 297 | # verify that the driver manager utilities are runnable so we may 298 | # check the configuration and install the driver. 299 | function find_odbc_config () 300 | { 301 | log "Verifying if unixODBC is present" 302 | # see if odbc_config is installed 303 | hash odbc_config &> /dev/null 304 | if [ $? -eq 1 ]; then 305 | log "odbc_config from unixODBC was not found. It is required to properly install the $driver_name"; 306 | return 1; 307 | fi 308 | 309 | hash odbcinst &> /dev/null 310 | if [ $? -eq 1 ]; then 311 | log "odbcinst from unixODBC was not found. It is required to properly install the $driver_name"; 312 | return 1; 313 | fi 314 | 315 | return 0; 316 | } 317 | 318 | function is_already_installed() 319 | { 320 | log "Checking if $driver_name is already installed in $dm_name" 321 | odbcinst -q -d -n "$driver_dm_name" -v >> $log_file 322 | if [ $? -eq 0 ]; then 323 | log "The $driver_name is already installed." 324 | log "Use --force to reinstall the driver again."; 325 | return 1; 326 | fi 327 | 328 | return 0; 329 | } 330 | 331 | function verify_dm_version () 332 | { 333 | log "Verifying that unixODBC is version $req_dm_ver" 334 | 335 | # verify version 336 | local version=$(odbc_config --version); 337 | if [ $? -ne 0 ]; then 338 | log "Cannot determine version of installed unixODBC."; 339 | return 1; 340 | fi 341 | local maj_ver_num=`echo $version | cut -d'.' -f1` 342 | local min_ver_num=`echo $version | cut -d'.' -f2` 343 | local pat_ver_num=`echo $version | cut -d'.' -f3` 344 | if [ "$maj_ver_num" -eq "2" ] && [ "$min_ver_num" -ge "3" ] && [ "$pat_ver_num" -ge "0" ]; then 345 | log "unixODBC version is >= 2.3.0"; 346 | else 347 | log "unixODBC version must be" $req_dm_ver ". See README for more information."; 348 | return 1; 349 | fi 350 | 351 | return 0; 352 | } 353 | 354 | function verify_dm_config() 355 | { 356 | local config=$(odbc_config --cflags) 357 | 358 | local sizeof_long_int=${config/SIZEOF_LONG_INT\=8/} 359 | local legacy_64bit_mode=${config/BUILD_LEGACY_64_BIT_MODE/} 360 | 361 | # configuration must have this flag set, so it should be deleted from sizeof_long_int 362 | if [ "$config" == "$sizeof_long_int" ]; then 363 | log "unixODBC must have the configuration SIZEOF_LONG_INT=8." 364 | log "This will probably require a rebuild of the unixODBC Driver Manager." 365 | log "See README for more information." 366 | return 1; 367 | fi 368 | 369 | # configuration shouldn't have this flag set, so it should not be deleted (be the same) 370 | if [ "$config" != "$legacy_64bit_mode" ]; then 371 | log "unixODBC must not have BUILD_LEGACY_64_BIT_MODE configuration flag set." 372 | log "This will probably require a rebuild of the unixODBC Driver Manager." 373 | log "See README for more information." 374 | return 1; 375 | fi 376 | 377 | return 0; 378 | } 379 | 380 | 381 | # verify all configuration prerequisites and print the status of each. 382 | # 0 means all checks pass, 1 means one or more items has failed 383 | 384 | function verify_config 385 | { 386 | local proc_os_okay="NOT CHECKED" 387 | local locale_installed="NOT CHECKED" 388 | local libs_installed="NOT CHECKED" 389 | local odbc_config="NOT CHECKED" 390 | local already_installed="NOT CHECKED" 391 | local version_dm_okay="NOT CHECKED" 392 | local dm_config_okay="NOT CHECKED" 393 | 394 | verify_steps=( check_for_Linux_x86_64 check_required_locale check_required_libs find_odbc_config verify_dm_version verify_dm_config is_already_installed ) 395 | verify_status_vars=( proc_os_okay locale_installed libs_installed odbc_config version_dm_okay dm_config_okay already_installed ) 396 | verify_success=( 'OK' 'OK' 'OK' 'OK' 'OK' 'OK*' 'NOT FOUND' ) 397 | verify_fail=( 'FAILED' 'NOT FOUND' 'NOT FOUND' 'FAILED' 'FAILED' 'FAILED' 'INSTALLED' ) 398 | 399 | if [ ${#verify_steps[@]} -ne ${#verify_status_vars[@]} ]; then 400 | echo "Error in verify script 1" 401 | exit 1; 402 | fi 403 | if [ ${#verify_steps[@]} -ne ${#verify_success[@]} ]; then 404 | echo "Error in verify script 2" 405 | exit 1; 406 | fi 407 | if [ ${#verify_steps[@]} -ne ${#verify_fail[@]} ]; then 408 | echo "Error in verify script 3" 409 | exit 1; 410 | fi 411 | 412 | local i=0 413 | 414 | for (( i = 0 ; i < ${#verify_steps[@]} ; i++ )) 415 | do 416 | local fn=${verify_steps[$i]} 417 | local status_var=${verify_status_vars[$i]} 418 | 419 | eval $status_var="\"${verify_success[$i]}\"" 420 | 421 | $fn 422 | if [ $? -ne 0 ]; then 423 | if [ $force -ne 1 ]; then 424 | status=1; 425 | fi 426 | eval $status_var="\"${verify_fail[$i]}\"" 427 | break 428 | fi 429 | 430 | done 431 | 432 | report_config "$proc_os_okay" "$locale_installed" "$libs_installed" "$odbc_config" "$version_dm_okay" "$dm_config_okay" "$already_installed" 433 | 434 | return $status 435 | } 436 | 437 | # installation 438 | 439 | function copy_files 440 | { 441 | log "Copying files" 442 | 443 | local i=0 444 | 445 | for (( i = 0 ; i < ${#dirs[@]} ; i++ )) 446 | do 447 | local dir="${dirs[$i]}" 448 | local files="${file_sets[$i]}" 449 | local perms="${file_perm_sets[$i]}" 450 | 451 | # evaluate the contents of the variables and assign them back 452 | eval dir=\$$dir 453 | eval files=\(\$\{$files\[\@\]\}\) 454 | eval perms=\(\$\{$perms\[\@\]\}\) 455 | 456 | mkdir -p $dir 457 | 458 | local j=0 459 | 460 | for (( j = 0; j < ${#files[@]}; j++ )) 461 | do 462 | 463 | local f=${files[$j]} 464 | local p=${perms[$j]} 465 | 466 | log "Copying $f to $dir" 467 | cp $f $dir >> $log_file 2>&1 468 | 469 | if [ $? -ne 0 ]; then 470 | log "Failed to copy $f to $dir." 471 | if [ $force -ne 1 ]; then 472 | return 1; 473 | fi 474 | fi 475 | 476 | f=${f##*/} 477 | log "Setting permissions on $f" 478 | chmod $p $dir/$f >> $log_file 2>&1 479 | 480 | if [ $? -ne 0 ]; then 481 | log "Failed to set the permission of $f to $p." 482 | if [ $force -ne 1 ]; then 483 | return 1; 484 | fi 485 | fi 486 | 487 | done 488 | done 489 | 490 | return 0; 491 | } 492 | 493 | # it tries to remove all the files regardless of the outcome of a removal, 494 | # as such it always returns 0 for "success" 495 | function remove_files 496 | { 497 | log "Removing files" 498 | 499 | local i=0 500 | 501 | for (( i = 0 ; i < ${#dirs[@]} ; i++ )) 502 | do 503 | local dir="${dirs[$i]}" 504 | local files="${file_sets[$i]}" 505 | local links="${link_sets[$i]}" 506 | 507 | # evaluate the contents of the variables and assign them back 508 | eval dir=\$$dir 509 | eval files=\( \$\{$files\[\@\]\} \) 510 | eval links=\( \$\{$links\[\@\]\} \) 511 | 512 | for l in ${links[@]} 513 | do 514 | [ "$l" == "null" ] && continue 515 | 516 | log "Removing $dir/$l" 517 | rm -f $dir/$l >> $log_file 2>&1 518 | 519 | if [ $? -ne 0 ]; then 520 | log "Non fatal error: Failed to remove $l to $dir." 521 | fi 522 | done 523 | 524 | for f in ${files[@]} 525 | do 526 | log "Removing $dir/$f" 527 | rm -f $dir/$f >> $log_file 2>&1 528 | 529 | if [ $? -ne 0 ]; then 530 | log "Non fatal error: Failed to remove $f to $dir." 531 | fi 532 | done 533 | done 534 | 535 | return 0; 536 | } 537 | 538 | function register_driver 539 | { 540 | log "Registering the $driver_name driver" 541 | 542 | # write INI file for driver installation in the temp directory 543 | local template_ini="$tmp/$driver_short_name.ini" 544 | 545 | # for debugging purposes 546 | [ $debug -eq 1 ] && template_ini="$driver_short_name.ini" 547 | 548 | echo "[$driver_dm_name]" > $template_ini 549 | echo "Description = $driver_name" >> $template_ini 550 | echo "Driver = $lib_dir/$driver_file" >> $template_ini 551 | echo "Threading = 1" >> $template_ini 552 | echo "" >> $template_ini 553 | 554 | if [ $? -ne 0 ]; then 555 | log "Failed to create ini file $template_ini used to install the driver" 556 | return 1; 557 | fi 558 | 559 | # install the driver using odbcinst 560 | odbcinst -i -d -f "$template_ini" 2>&1 >> $log_file 561 | 562 | if [ $? -ne 0 ]; then 563 | log "Failed installing driver $driver_name with $dm_name" 564 | return 1; 565 | fi 566 | 567 | # copy the template ini file to the supplemental directory 568 | cp $template_ini $sup_dir 2>> $log_file 569 | 570 | if [ $? -ne 0 ]; then 571 | log "Warning: $template_ini could not be copied to $sup_dir" 572 | fi 573 | 574 | return 0; 575 | } 576 | 577 | function extract_docs 578 | { 579 | local doc_file="$doc_dir/$lang_id.tar.gz" 580 | 581 | log "Extracting documentation from $doc_file" 582 | 583 | local cwd=$(pwd) 584 | 585 | cd $doc_dir 586 | if [ $? -ne 0 ]; then 587 | log "Couldn't enter the directory $doc_dir to extract documentation." 588 | return 1 589 | fi 590 | 591 | tar xvzf $doc_file 2>&1 >> $log_file 592 | if [ $? -ne 0 ]; then 593 | log "Couldn't extract documentation from $doc_file" 594 | return 1 595 | fi 596 | 597 | rm $doc_file 2>&1 >> $log_file 598 | if [ $? -ne 0 ]; then 599 | log "Couldn't erase documentation archive after extraction" 600 | return 1 601 | fi 602 | 603 | return 0; 604 | } 605 | 606 | function create_symlinks 607 | { 608 | log "Creating symbolic links" 609 | 610 | local i=0 611 | local j=0 612 | 613 | for (( i = 0 ; i < ${#dirs[@]} ; i++ )) 614 | do 615 | local dir="${dirs[$i]}" 616 | local sym_dir="${sym_dirs[i]}" 617 | local files="${file_sets[$i]}" 618 | local links="${link_sets[$i]}" 619 | 620 | [ "$links" == "null" ] && continue 621 | 622 | # evaluate the contents of the variables and assign them back 623 | eval dir=\$$dir 624 | eval sym_dir=\$$sym_dir 625 | eval files=\( \$\{$files\[\@\]\} \) 626 | eval links=\( \$\{$links\[\@\]\} \) 627 | 628 | # assertion that the links and files are the same length 629 | if [ ${#files[@]} -ne ${#links[@]} ]; then 630 | log "Fatal: file and link lists do not match." 631 | exit 1; 632 | fi 633 | 634 | # if there is no symbolic link dir, then there are no symlinks 635 | [ "$sym_dir" == "" ] && continue 636 | 637 | local j=0 638 | 639 | for (( j = 0 ; j < ${#files[@]} ; j++ )) 640 | do 641 | local f="${files[$j]##*/}" 642 | local l="${links[$j]}" 643 | 644 | #if the "link" is null, then skip it 645 | [ "$l" == "null" ] && continue 646 | 647 | if [ $force -ne 0 ]; then 648 | log "Removing previous link due to force flag" 649 | rm $sym_dir/$l >> $log_file 2>&1 650 | fi 651 | 652 | log "Linking $l to $f" 653 | ln -s $dir/$f $sym_dir/$l >> $log_file 2>&1 654 | 655 | if [ $? -ne 0 ]; then 656 | log "Failed to link $l to $f." 657 | if [ $force -ne 1 ]; then 658 | return 1; 659 | fi 660 | fi 661 | done 662 | done 663 | 664 | # This has been tested in Ubuntu 12.04 and 14.04 LTS 665 | log "Creating symlinks needed in Ubuntu." 666 | hash aptitude &> /dev/null 667 | local has_aptitude=$? 668 | hash dpkg &> /dev/null 669 | local has_dpkg=$? 670 | local deb_os_id=$(cat /etc/debian_version); 671 | local os_id=$(lsb_release -si); 672 | 673 | if [ $has_aptitude -eq 0 ] && [ "$os_id" == "Ubuntu" ]; then 674 | if [ $force -eq 1 ]; then 675 | if [ -h /usr/lib/x86_64-linux-gnu/libcrypto.so.10 ]; then 676 | rm /usr/lib/x86_64-linux-gnu/libcrypto.so.10; 677 | fi 678 | if [ -h /usr/lib/x86_64-linux-gnu/libssl.so.10 ]; then 679 | rm /usr/lib/x86_64-linux-gnu/libssl.so.10; 680 | fi 681 | if [ -h /usr/lib/x86_64-linux-gnu/libodbcinst.so.1 ]; then 682 | rm /usr/lib/x86_64-linux-gnu/libodbcinst.so.1; 683 | fi 684 | if [ -h /usr/lib/x86_64-linux-gnu/libodbc.so.1 ]; then 685 | rm /usr/lib/x86_64-linux-gnu/libodbc.so.1; 686 | fi 687 | fi 688 | ln -s /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 /usr/lib/x86_64-linux-gnu/libcrypto.so.10 >> $log_file 2>&1; 689 | ln -s /lib/x86_64-linux-gnu/libssl.so.1.0.0 /usr/lib/x86_64-linux-gnu/libssl.so.10 >> $log_file 2>&1; 690 | if [ -f /usr/lib/x86_64-linux-gnu/libodbcinst.so.2.0.0 ]; then 691 | ln -s /usr/lib/x86_64-linux-gnu/libodbcinst.so.2.0.0 /usr/lib/x86_64-linux-gnu/libodbcinst.so.1 >> $log_file 2>&1; 692 | else 693 | log "proper libodbcinst.so not found. You will need to create the symlink manually" 694 | fi 695 | if [ -f /usr/lib/x86_64-linux-gnu/libodbc.so.2.0.0 ]; then 696 | ln -s /usr/lib/x86_64-linux-gnu/libodbc.so.2.0.0 /usr/lib/x86_64-linux-gnu/libodbc.so.1 >> $log_file 2>&1; 697 | else 698 | log "proper libodbc.so not found. You will need to create the symlink manually" 699 | fi 700 | elif [ $has_dpkg -eq 0 ] && [ "$deb_os_id" == "8.1" ] ; then 701 | if [ $force -eq 1 ]; then 702 | if [ -h /usr/lib/x86_64-linux-gnu/libcrypto.so.10 ]; then 703 | rm /usr/lib/x86_64-linux-gnu/libcrypto.so.10; 704 | fi 705 | if [ -h /usr/lib/x86_64-linux-gnu/libssl.so.10 ]; then 706 | rm /usr/lib/x86_64-linux-gnu/libssl.so.10; 707 | fi 708 | if [ -h /usr/lib/x86_64-linux-gnu/libodbcinst.so.1 ]; then 709 | rm /usr/lib/x86_64-linux-gnu/libodbcinst.so.1; 710 | fi 711 | if [ -h /usr/lib/x86_64-linux-gnu/libodbc.so.1 ]; then 712 | rm /usr/lib/x86_64-linux-gnu/libodbc.so.1; 713 | fi 714 | fi 715 | ln -s /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 /usr/lib/x86_64-linux-gnu/libcrypto.so.10 >> $log_file 2>&1; 716 | ln -s /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 /usr/lib/x86_64-linux-gnu/libssl.so.10 >> $log_file 2>&1; 717 | if [ -f /usr/lib/x86_64-linux-gnu/libodbcinst.so.2.0.0 ]; then 718 | ln -s /usr/lib/x86_64-linux-gnu/libodbcinst.so.2.0.0 /usr/lib/x86_64-linux-gnu/libodbcinst.so.1 >> $log_file 2>&1; 719 | else 720 | log "proper libodbcinst.so not found. You will need to create the symlink manually" 721 | fi 722 | if [ -f /usr/lib/x86_64-linux-gnu/libodbc.so.2.0.0 ]; then 723 | ln -s /usr/lib/x86_64-linux-gnu/libodbc.so.2.0.0 /usr/lib/x86_64-linux-gnu/libodbc.so.1 >> $log_file 2>&1; 724 | else 725 | log "proper libodbc.so not found. You will need to create the symlink manually" 726 | fi 727 | else 728 | SCRIPTPATH=$( cd "$(dirname "$0")" ; pwd -P ) 729 | log "You need to create some symlinks manually. Use the following command to find out more:" 730 | log "ldd $SCRIPTPATH/lib64/libmsodbcsql-11.0.so.2270.0" 731 | fi 732 | 733 | return 0; 734 | } 735 | 736 | function report_install() 737 | { 738 | format_status "$driver_name files copied" "$1" 739 | format_status "Symbolic links for bcp and sqlcmd created" "$2" 740 | format_status "$driver_name registered" "$3" 741 | } 742 | 743 | function process_params 744 | { 745 | # process parameters 746 | while [ "$1" ] 747 | do 748 | case "$1" in 749 | --force) 750 | force=1 751 | ;; 752 | --force-ubuntu) 753 | req_libs=("${deb_req_libs[@]}") 754 | ;; 755 | --force-debian) 756 | req_libs=("${real_deb_req_libs[@]}") 757 | ;; 758 | --force-redhat) 759 | req_libs=("${red_req_libs[@]}") 760 | ;; 761 | --bin-dir=*) 762 | bin_sym_dir=${1##--bin-dir=} 763 | bin_sym_dir=${bin_sym_dir/#"~"/$HOME} 764 | log "Symbolic links to binaries created in $bin_sym_dir" 765 | ;; 766 | --lib-dir=*) 767 | lib_dir=${1##--lib-dir=} 768 | lib_dir=${lib_dir/#"~"/$HOME} 769 | log "Driver directory set to $lib_dir" 770 | ;; 771 | --accept-license) 772 | license_accepted=1 773 | log "License agreement accepted" 774 | ;; 775 | *) 776 | echo "Unknown parameter $1" 777 | print_usage 778 | exit 1 779 | ;; 780 | esac 781 | 782 | shift 783 | done 784 | 785 | return 0 786 | } 787 | 788 | function accept_license 789 | { 790 | log "Accept the license agreement" 791 | 792 | if [ ! -f "./LICENSE" ]; then 793 | log "LICENSE file not found." 794 | echo "Cannot display license agreement. Please refer to the original archive for the" 795 | echo "LICENSE file and re-run the install with the --accept-license parameter." 796 | exit 1 797 | fi 798 | 799 | hash more &> /dev/null 800 | 801 | if [ $? -ne 0 ]; then 802 | log "more program not found. Cannot display license agreement without more." 803 | echo "Cannot display license agreement. Please read the license agreement in LICENSE and" 804 | echo "re-run the install with the --accept-license parameter." 805 | exit 1 806 | fi 807 | 808 | more ./LICENSE 809 | 810 | echo 811 | read -p "Enter YES to accept the license or anything else to terminate the installation: " accept 812 | echo 813 | 814 | if [ "$accept" == "YES" ]; then 815 | log "License agreement accepted" 816 | license_accepted=1 817 | return 0 818 | fi 819 | 820 | log "License agreement not accepted" 821 | return 1 822 | } 823 | 824 | function install() 825 | { 826 | # return value 827 | local status=0 828 | 829 | process_params $* 830 | 831 | if [ $license_accepted -ne 1 ]; then 832 | accept_license 833 | fi 834 | 835 | # technically accept_license should not return if the license isn't accepted, 836 | # but this is a catch for it 837 | if [ $? -ne 0 ] || [ $license_accepted -ne 1 ]; then 838 | return 1 839 | fi 840 | 841 | verify_config 842 | 843 | local verified=$? 844 | 845 | local files_copied="NOT ATTEMPTED" 846 | local docs_extracted="NOT ATTEMPTED" 847 | local driver_registered="NOT ATTEMPTED" 848 | local symlinks_created="NOT ATTEMPTED" 849 | 850 | # if verification passed or force was specified, then call the functions to install 851 | # and register the driver 852 | if [ $verified -eq 0 ] || [ $force -eq 1 ]; then 853 | 854 | if [ "$lib_dir" == "" ]; then 855 | lib_dir="/opt/microsoft/$driver_short_name/lib64" 856 | fi 857 | 858 | bin_dir="/opt/microsoft/$driver_short_name/bin" 859 | 860 | if [ "$bin_sym_dir" == "" ]; then 861 | bin_sym_dir="/usr/bin"; 862 | fi 863 | 864 | sup_dir="/opt/microsoft/$driver_short_name/$driver_version" 865 | mkdir -p $sup_dir 866 | if [ -d $sup_dir ]; then 867 | log "$sup_dir exists" 868 | else 869 | log "Could not create $sup_dir" 870 | return 1 871 | fi 872 | 873 | rll_dir="$sup_dir/$lang_id" 874 | mkdir -p $rll_dir 875 | if [ -d $rll_dir ]; then 876 | log "$rll_dir exists" 877 | else 878 | log "Could not create $rll_dir" 879 | return 1 880 | fi 881 | 882 | doc_dir="$sup_dir/docs/$lang_id" 883 | mkdir -p $doc_dir 884 | if [ -d $doc_dir ]; then 885 | log "$doc_dir exists" 886 | else 887 | log "Could not create $doc_dir" 888 | return 1 889 | fi 890 | 891 | inc_dir="$sup_dir/include" 892 | mkdir -p $inc_dir 893 | if [ -d $inc_dir ]; then 894 | log "$inc_dir exists" 895 | else 896 | log "Could not create $inc_dir" 897 | return 1 898 | fi 899 | 900 | local install_steps=( copy_files extract_docs create_symlinks register_driver ) 901 | local install_status_vars=( files_copied docs_extracted symlinks_created driver_registered ) 902 | local install_success=( 'OK' 'OK' 'OK' 'INSTALLED' ) 903 | local install_fail=( 'FAILED' 'FAILED' 'FAILED' 'FAILED' ) 904 | 905 | # "assertions" that the variables are sane 906 | if [ ${#install_steps[@]} -ne ${#install_status_vars[@]} ]; then 907 | echo "Error in install script 1" 908 | exit 1; 909 | fi 910 | if [ ${#install_steps[@]} -ne ${#install_success[@]} ]; then 911 | echo "Error in install script 2" 912 | exit 1; 913 | fi 914 | if [ ${#install_steps[@]} -ne ${#install_fail[@]} ]; then 915 | echo "Error in install script 3" 916 | exit 1; 917 | fi 918 | 919 | local i=0 920 | 921 | for (( i = 0 ; i < ${#install_steps[@]} ; i++ )) 922 | do 923 | local fn=${install_steps[$i]} 924 | local status_var=${install_status_vars[$i]} 925 | 926 | eval $status_var="\"${install_success[$i]}\"" 927 | 928 | $fn 929 | 930 | if [ $? -ne 0 ]; then 931 | status=1 932 | eval $status_var="\"${install_fail[$i]}\"" 933 | if [ $force -ne 1 ]; then 934 | uninstall 935 | break 936 | fi 937 | fi 938 | done 939 | fi 940 | 941 | report_install "$files_copied" "$symlinks_created" "$driver_registered" 942 | 943 | return $status 944 | } 945 | 946 | function uninstall 947 | { 948 | process_params $* 949 | 950 | return 0; 951 | } 952 | 953 | command=$1 954 | shift 955 | 956 | case "$command" in 957 | install) 958 | install $* 959 | ;; 960 | verify) 961 | verify_config $* 962 | ;; 963 | --help) 964 | print_usage 965 | ;; 966 | *) 967 | echo "Unknown command given." 968 | print_usage 969 | ;; 970 | esac 971 | 972 | # if any problems, print out a final diagnostic about where to find failure reasons 973 | # and exit with status of 1 974 | if [ $? -ne 0 ]; then 975 | echo 976 | echo "See $log_file for more information about installation failures." 977 | exit 1 978 | fi 979 | 980 | echo 981 | echo "Install log created at $log_file." 982 | echo 983 | echo "One or more steps may have an *. See README for more information regarding" 984 | echo "these steps." 985 | 986 | # return success 987 | exit 0 988 | --------------------------------------------------------------------------------