#!/bin/bash
set -x
# Define variables
SMART_PATH="/usr/local/sbin"
SMARTCTL_PATH="$SMART_PATH/smartctl"
SMARTUPDATEDB_PATH="$SMART_PATH/update-smart-drivedb"
VERSION="7.4-1"
BASE_URL="https://sourceforge.net/projects/smartmontools/files/smartmontools/7.4"
DMG_FILE="smartmontools-${VERSION}.dmg"
MD5_FILE="smartmontools-${VERSION}.dmg.md5"
ASC_FILE="smartmontools-${VERSION}.dmg.asc"
GPG_KEY="0C9577FD2C4CFCB4B9A599640A30812EFF3AEFF5"
KEYSERVER="hkps://keys.openpgp.org"
KEY_URL="https://www.smartmontools.org/browser/trunk/www/SmartmontoolsSigningKey_2021.txt?format=txt"
KEY_DIR=$(dirname "$0")
GPG_KEYFILE="$KEY_DIR/smartmontools_key.txt"
DRIVE_DB="https://svn.code.sf.net/p/smartmontools/code/branches/RELEASE_7_3_DRIVEDB/smartmontools/drivedb.h"
# Ensure running as root
if [ "$(whoami)" != "root" ]; then
echo "Error: This script must be run with superuser privileges."
exit 1
fi
# Check if smartmontools is already installed
if command -v $SMARTCTL_PATH &> /dev/null; then
# Define the version pattern
PATTERN="sf-$VERSION"
echo "Current smartmontools version: $VERSION"
echo "Expected pattern: $PATTERN"
# Extract the installed version number
SMARTCTL_VERSION=$($SMARTCTL_PATH --version | head -1 | awk -F'[(|)]' '{print $2}')
# Check if the version matches or indicates a local build
if [[ $SMARTCTL_VERSION == *"local build"* ]]; then
echo "Version indicates a local (Homebrew) installation."
echo "Please uninstall using the appropriate package manager."
exit 1
elif [[ $SMARTCTL_VERSION == $PATTERN ]]; then
echo "Installed version matches the target version. Updating drive database only."
# Update drive database
if ! $SMARTUPDATEDB_PATH; then
echo "Failed to update drive database directly. Attempting to download updated version..."
if ! curl -sSL "$DRIVE_DB" -o "/usr/local/share/smartmontools/drivedb.h"; then
echo "Error: Failed to download updated drive database."
exit 1
fi
fi
echo "Drive database updated successfully."
exit 0
else
echo "Installed version does not match the expected pattern and is not a Homebrew installation."
fi
fi
# Function definitions for logging errors, importing GPG signatures, downloading files, and verifying downloads
log_error() {
echo "$1" | logger -t smartmontools_installation_error
exit 500
}
import_gpg_signature() {
echo "Importing GPG signature..."
curl -sSL "$1" -o "$GPG_KEYFILE" && gpg --import "$GPG_KEYFILE" || log_error "Failed to import GPG key."
}
download_file() {
echo "Downloading $2..."
curl -L "$1" -o "$2" || log_error "Failed to download $2."
}
verify_downloads() {
# Verify MD5 checksum
echo "Verifying MD5 checksum for $DMG_FILE..."
local md5_check=$(md5 -q "$DMG_FILE")
local expected_md5=$(cut -d ' ' -f1 "$MD5_FILE")
if [ "$md5_check" != "$expected_md5" ]; then
log_error "Checksum verification failed for $DMG_FILE."
fi
echo "MD5 checksum verified successfully."
# Verify GPG signature
if command -v gpg &> /dev/null; then
echo "Verifying GPG signature for $DMG_FILE..."
gpg --keyring "$GPG_KEYFILE" --verify "$ASC_FILE" "$DMG_FILE" &> /dev/null || log_error "GPG signature verification failed."
echo "GPG signature verified successfully."
fi
}
# Main script
if [ -f "$DMG_FILE" ] && [ -f "$MD5_FILE" ] && [ -f "$ASC_FILE" ]; then
# Check checksum and key before downloading
verify_downloads
else
# Download files
download_file "${BASE_URL}/${DMG_FILE}/download" "$DMG_FILE"
download_file "${BASE_URL}/${MD5_FILE}/download" "$MD5_FILE"
download_file "${BASE_URL}/${ASC_FILE}/download" "$ASC_FILE"
verify_downloads
fi
# Installation steps
# Attempt to attach the DMG file
if hdiutil attach "$DMG_FILE"; then
echo "DMG file attached successfully"
else
log_error "Failed to attach DMG file: $DMG_FILE"
fi
# Attempt to install the package
if installer -allowUntrusted -verbose -pkg "/Volumes/smartmontools/smartmontools-${VERSION}.pkg" -target /; then
echo "Installation successful"
purge
sleep 5
else
log_error "Installation failed"
hdiutil detach "/Volumes/smartmontools"
sleep 5
fi
# Attempt to detach the DMG file
if hdiutil detach "/Volumes/smartmontools"; then
echo "DMG file detached successfully"
else
log_error "Failed to detach DMG file: $DMG_FILE"
fi
# Check if smartmontools is installed
if ! command -v smartctl &> /dev/null; then
echo "Error: smartmontools is not installed. Please install it using Homebrew or another package manager."
exit 1
fi
# Check if update-smart-drivedb is available
if ! command -v update-smart-drivedb &> /dev/null; then
echo "Error: update-smart-drivedb is not available. Make sure smartmontools is properly installed."
exit 1
fi
# Update drive database
echo "Updating smartmontools drive database..."
/usr/local/sbin/update-smart-drivedb
# Check if the update was successful
if [ $? -ne 0 ]; then
echo "Error: Failed to update smartmontools drive database."
# Download the updated drivedb.h file
echo "Downloading updated drivedb.h file..."
curl -sSL "https://www.smartmontools.org/export/5597/branches/RELEASE_7_3_DRIVEDB/smartmontools/drivedb.h" -o "/usr/local/share/smartmontools/drivedb.h"
# Check if the download was successful
if [ $? -ne 0 ]; then
echo "Error: Failed to download the updated drivedb.h file."
exit 1
fi
echo "smartmontools drive database updated successfully."
fi
# Further instructions as necessary
echo "Run the test"
/usr/local/sbin/smartctl -t long /dev/disk0
echo "Get information on your drive"
/usr/local/sbin/smartctl -a /dev/disk0