#!/bin/sh

. /usr/lib/lib-fliwi/fliwi-drives.sh

smartCtl="/usr/sbin/smartctl"

MAX_SHORT_TEST_AGE_IN_HOURS=24
MAX_EXTENDED_TEST_AGE_IN_HOURS=168
DEFAULT_SUCCESSFUL_SELFTEST_GREP_STRING=' Completed without error '

if [ ! -f "$smartCtl" ]; then
  echo "$smartCtl not found" 1>&2
  exit 1
fi

fliwirunsmartselftest_do_cleanup()
{
  if [ -n "$smart_temp_info_file" ] && \
     [ -f "$smart_temp_info_file" ]; then
    rm -f $smart_temp_info_file
  fi

  if [ -n "$smart_temp_attributes_file" ] && \
     [ -f "$smart_temp_attributes_file" ]; then
    rm -f $smart_temp_attributes_file
  fi

  if [ -n "$smart_temp_selftest_file" ] && \
     [ -f "$smart_temp_selftest_file" ]; then
    rm -f $smart_temp_selftest_file
  fi
}

smart_temp_info_file=$(tempfile --prefix 'fliwi_' --suffix '_run_smart_info')
if [ ! -f "$smart_temp_info_file" ]; then
  echo "Problem creating a tempfile for smart-info..." 1>&2
  fliwirunsmartselftest_do_cleanup
  exit 1
fi

smart_temp_attributes_file=$(tempfile --prefix 'fliwi_' --suffix '_run_smart_attributes')
if [ ! -f "$smart_temp_attributes_file" ]; then
  echo "Problem creating a tempfile for smart-attributes..." 1>&2
  fliwirunsmartselftest_do_cleanup
  exit 1
fi

smart_temp_selftest_file=$(tempfile --prefix 'fliwi_' --suffix '_run_smart_selftest')
if [ ! -f "$smart_temp_selftest_file" ]; then
  echo "Problem creating a tempfile for smart-selftests..." 1>&2
  fliwirunsmartselftest_do_cleanup
  exit 1
fi

disks="$($smartCtl --scan | awk '{print $1}') $(fliwi_get_non_block_device_disks)"
for disk in $disks
do
  SUCCESSFUL_SELFTEST_GREP_STRING="$DEFAULT_SUCCESSFUL_SELFTEST_GREP_STRING"
  LC_ALL=C $smartCtl -i $disk | sed 's/^[[:space:]]*//' > $smart_temp_info_file
  if [ $(cat $smart_temp_info_file | grep -c -F 'SMART support is: Available') -eq 1 ]; then
    if [ $(cat $smart_temp_info_file | grep -c -F "SMART support is: Enabled") -ne 1 ]; then
      test=$($smartCtl --smart=on $disk)
      if [ $? -ne 0 ]; then
        echo "Problem while enabling smart on $disk - not trying to start any selftest" 1>&2
        continue
      fi
    fi

    if [ $(cat $smart_temp_info_file | sed -r 's/[[:space:]]+/ /g' | grep -c -F "Device Model: SAMSUNG HD753LJ") -eq 1 ] && \
       [ $(cat $smart_temp_info_file | sed -r 's/[[:space:]]+/ /g' | grep -c -F "Firmware Version: 1AA01113") -eq 1 ]; then
      SUCCESSFUL_SELFTEST_GREP_STRING='( Completed without error )|(^# [^1] .* Aborted by host[[:space:]]+00%)'
    fi

    if [ $($smartCtl -H $disk| grep -c -F 'PASSED') -ne 1 ]; then
      echo "Disk $disk is about to fail - not starting any selftest..." 1>&2
      continue
    fi

    if [ $(LC_ALL=C $smartCtl -c $disk | grep -F 'Self-test execution status' | grep -F 'The previous self-test routine completed' | grep -v -F 'Self-test routine in progress...' | wc -l ) -ne 1 ]; then
      echo "Disk $disk is already running a selftest - not starting a new one..." 1>&2
      continue
    fi

    disk_last_successful_extended_offine_test_poh=0
    disk_last_successful_short_offine_test_poh=0

    LC_ALL=C $smartCtl -l selftest $disk | sed -r 's/[[:space:]]+/ /g' > $smart_temp_selftest_file

    for selftest_type in "Extended offline" "Short offline"
    do
      tmp_latest_extended_offline_test_string=$(cat $smart_temp_selftest_file | grep -F " $selftest_type " | grep -v -F ' in progress' | head -n 1)
      if [ -n "$tmp_latest_extended_offline_test_string" ] && \
         [ $(echo $tmp_latest_extended_offline_test_string | grep -c -E -e "$SUCCESSFUL_SELFTEST_GREP_STRING") -ne 1 ]; then
        echo "Latest '$selftest_type'-check on disk $disk failed  - not starting any new selftest..." 1>&2
        continue 1
      elif [ -n "$tmp_latest_extended_offline_test_string" ]; then
        temp_check_age=$(echo $tmp_latest_extended_offline_test_string | grep -E -e "$SUCCESSFUL_SELFTEST_GREP_STRING" | sed -r 's/.*% ([0-9]+) .*/\1/' | head -n 1 | sed -r 's/[^0-9]//g')
        if [ -n "$temp_check_age" ] && \
           [ $temp_check_age -gt 0 ]; then
          if [ "$selftest_type" = "Extended offline" ]; then
            disk_last_successful_extended_offine_test_poh=$temp_check_age
          elif [ "$selftest_type" = "Short offline" ]; then
            disk_last_successful_short_offine_test_poh=$temp_check_age
          fi
        fi
      fi
    done

    $smartCtl -A $disk | sed 's/^[[:space:]]*//' | grep -e "^[0-9].*" | sed 's/ \+/##/g' > $smart_temp_attributes_file

    power_on_hours=$(cat $smart_temp_attributes_file | sed 's/^[[:space:]]*//' | grep -e "^[0-9].*" | sed 's/ \+/##/g' | grep Power_On_Hours | awk -F "##" '{print $10}' | sed -r 's/[^0-9]//g')
    if [ -z "$power_on_hours" ]; then
      power_on_hours=0
    fi

    if [ $power_on_hours -gt 0 ]; then
      if [ $(expr $disk_last_successful_short_offine_test_poh + $MAX_SHORT_TEST_AGE_IN_HOURS) -lt $power_on_hours ]; then
        ### We need to run a short offline test
        echo "Starting a short-offline check on disk $disk..." 1>&2
        $smartCtl -t short $disk
      elif [ $(expr $disk_last_successful_extended_offine_test_poh + $MAX_EXTENDED_TEST_AGE_IN_HOURS) -lt $power_on_hours ]; then
        echo "Starting an extended-offline check on disk $disk..." 1>&2
        $smartCtl -t long $disk
      fi
    fi
  fi
done

fliwirunsmartselftest_do_cleanup


exit 0
