#!/bin/bash

. /etc/profile
. /etc/tos/scripts/scripts
while [ 1 ]; do
  script_get_lock >/dev/null
  [ $? -eq 0 ] && break
done

processExit() {
  script_put_lock
  exit $1
}

STORAGE_DEVICE_TOOL_SOCK="/var/api/storage_device_tool.sock"
i=0
while [ ! -e "$STORAGE_DEVICE_TOOL_SOCK" ]; do
    sleep 3
    i=$(("$i"+1))
    if [ $i -eq 9 ]; then
        echo "ter_storage_device_tool have not started"
        processExit 10
    fi
done

scsi_disk_op=$1
eSATA_position=1

ntfs_mount=/usr/bin/ntfs-3g
ntfs_mount_opt="-o rw,iocharset=utf8"

exfat_mount=/sbin/mount.exfat-fuse
exfat_mount_opt="-o umask=000,iocharset=utf8,shortname=mixed,quiet,utf8,flush"

vfat_mount=/bin/mount
vfat_mount_opt="-o umask=000,iocharset=utf8,shortname=mixed,quiet,utf8,flush"

ext4_mount=/bin/mount
ext4_mount_opt="-o rw,noatime,jqfmt=vfsv1,usrjquota=quota.user,grpjquota=quota.group"

btrfs_mount=/bin/mount
btrfs_mount_opt="-o rw,noatime,datasum,datacow,barrier,space_cache=v2,noautodefrag,subvolid=5,subvol=/"

if [ -z "${scsi_disk_op}" -o -z "${2}" ]; then
  echo "eg: ${0} [insert|remove|format] [sda|sdb|sdc|...] [ntfs|vfat|ext4]"
  processExit 1
fi

blk=/dev/$2

# Keep the information of the removed hard drive to /run
if [ "${scsi_disk_op}" = "remove" ]; then
    mkdir "/run/diskCache" >/dev/null 2>&1
    cp /run/cache/diskinfo/$2 /run/diskCache/$2 >/dev/null
fi

if [ "${scsi_disk_op}" = "insert" ]; then
    # insert logger
    systemctl start disk-event-logger-insert@$blk.service >/dev/null 2>&1 &
    # Insert the hard disk
    ter_curl -v -X PUT --unix-socket $STORAGE_DEVICE_TOOL_SOCK http://storage_device_tool.sock/v1/$2?type=1
else
    # remove logger
    systemctl start disk-event-logger-remove@$blk.service >/dev/null 2>&1 &
    # Remove the hard disk
    ter_curl -v -X DELETE --unix-socket $STORAGE_DEVICE_TOOL_SOCK http://storage_device_tool.sock/v1/$2/1?type=1
fi

[ ! -b $blk ] && processExit 1

# hard standby
if [ "${scsi_disk_op}" = "insert" ]; then
  /etc/tos/scripts/spindown $blk >/dev/null &
fi

sysblock=$(readlink "/sys/block/${2}" | awk '/host6/')
if [ "$(script_get_board)" != "2538" -o -z "$sysblock" ]; then
  processExit 1
fi

mainVolume=$(get_main_volume)
if [ -z "$mainVolume" ]; then
  processExit 1
fi
esataRoot="$mainVolume/@eSATA"
[ ! -d "$esataRoot" ] && mkdir -m 777 "$esataRoot"

log_path="/tmp/scsi_${scsi_disk_op}_$2"
echo "operation ${scsi_disk_op} $2 by $(whoami) $(pwd)" >${log_path}

db_share() {
  [ -z "$1" ] && return 1
  local mntpath=$1
  local foldername=$(basename "${mntpath}")
  tersql -sql "delete from share where foldername='$foldername'"
  tersql -sql "insert into share (foldername,device,mntpath,owner,oplock,hidden,type,description,extend)\
        VALUES('$foldername', '@eSATA', '$mntpath', 'admin', '0', '0', 'LFS', '', '${2}')"
}

db_share_delete() {
  [ -z "$1" ] && return 1
  local mntpath=$1
  local foldername=$(basename "$mntpath")
  tersql -sql "delete from share where foldername='$foldername'"
}

eSATA_disk_pos() {
  # as sda, sdb, ...
  while [ 1 ]; do
    local rulepath="/Volume[0-9]+/@eSATA/eSATAshare${eSATA_position}"
    local result=$(df-json | egrep "$rulepath" | awk -v OFS=',' '{print $1,$8}')
    [ -z "$result" ] && break
    local blk=$(echo $result | awk -F',' '{print $1}')
    local mntpath=$(echo $result | awk -F',' '{print $2}')
    if [ ! -b "$blk" ]; then
      umount -fl "${mntpath}" >/dev/null 2>&1
      break
    fi
    let eSATA_position=eSATA_position+1
  done
  echo "$esataRoot/eSATAshare${eSATA_position}"
}

disk_filesystem() {
  local blk=$1
  local core=$(mdadm -E $blk | grep $TOS_CORE_SIGN)
  local swap=$(mdadm -E $blk | grep $TOS_SWAP_SIGN)
  local user=$(mdadm -E $blk | grep $TOS_USER_SIGN)
  if [ -z "${core}" -a -z "${swap}" -a -z "${user}" ]; then
    local fs=$(blkid -o value -s TYPE ${blk})
    echo "$fs"
  else
    echo "mdraid"
  fi
  return 0
}

usb_slaves_scan() {
  local blk=/dev/$1
  for sd in $(ls -1d ${blk}?); do
    slaves="${slaves} ${sd}"
  done
  [ "${slaves}X" = "X" ] && slaves=$blk
  echo $slaves
}

scsi_disk_insert() {
  local slaves=$(usb_slaves_scan ${1})
  local ctrl=0

  for device_name in $slaves; do
    local mountpath=$(eSATA_disk_pos ${1})
    umount -fl ${mountpath} >/dev/null 2>&1
    df-json | grep ${device_name} >/dev/null 2>&1
    [ $? -eq 0 -o ! -b ${device_name} ] && continue
    local fs=$(disk_filesystem ${device_name})
    [ "$fs" = "mdraid" ] && continue
    ctrl=1
    mkdir -p ${mountpath}
    chmod 777 $(dirname "${mountpath}")

    if [ "$fs" = "ntfs" ]; then
      ${ntfs_mount} ${ntfs_mount_opt} ${device_name} "${mountpath}" >>"${log_path}"
    elif [ "$fs" = "vfat" ]; then
      ${vfat_mount} ${vfat_mount_opt} ${device_name} "${mountpath}" >>"${log_path}"
    elif [ "$fs" = "exfat" ]; then
      ${exfat_mount} ${exfat_mount_opt} ${device_name} "${mountpath}" >>"${log_path}"
    elif [ "$fs" = "btrfs" ]; then
      $btrfs_mount $btrfs_mount_opt $device_name "$mountpath" >>"$log_path"
    else
      ${ext4_mount} ${ext4_mount_opt} ${device_name} "${mountpath}" >>"${log_path}"
    fi

    if [ $? -eq 0 ]; then
      db_share "${mountpath}" "${device_name}"
      echo "mount ${device_name} to ${mountpath} with $fs" >>${log_path}
      chmod 777 ${mountpath}
    else
      echo "mount ${device_name} to ${mountpath} failed with $fs" >>${log_path}
      rm -fr ${mountpath}
    fi
  done

  if [ $ctrl -eq 1 ]; then
    [ ! -z "$(pidof smbftpd)" ] && systemctl restart ftp
    [ ! -z "$(pidof smbd)" ] && systemctl restart smbd
  fi
}

scsi_disk_remove() {
  local device_name=$1
  local skip=$2
  local blk=/dev/${device_name}

  local list=$(tersql -sql "select foldername,mntpath,extend from share where extend like '${blk}%'")
  for line in $(echo $list | jq -c -r .[]); do
    [ -z "$line" ] && continue
    local foldername=$(echo $line | jq -r .foldername)
    local mntpath=$(echo $line | jq -r .mntpath)
    local slaveblk=$(echo $line | jq -r .extend)
    [ -z "${foldername}" -o -z "${slaveblk}" ] && continue
    local try=0
    local stat=1
    while [ $try -lt 5 ]; do
      local realpath=$(df-json | egrep "/Volume[0-9]+/@eSATA/$foldername" | awk '{print $8}')
      if [ -z "$realpath" ]; then
        stat=0
        break
      else
        mntpath=$realpath
        fuser -k ${mntpath}
        umount -fl ${mntpath} >>${log_path}
      fi
      let try=try+1
    done
    if [ $stat -ne 0 ]; then
      if [ ! -b "$slaveblk" ]; then
        db_share_delete "$mntpath"
      else
        echo "umount -fl ${mntpath} failed" >>${log_path}
      fi
    else
      echo "umount -fl ${mntpath} successful" >>${log_path}
      db_share_delete "$mntpath"
    fi
  done
  local blkname=${device_name:0:3}
  local path=/sys/block/${blkname}/device/delete
  if [ -e $path -a "X${skip}" = "X" ]; then
    echo 0 >$path
  fi

  [ ! -z "$(pidof smbftpd)" ] && systemctl restart ftp
  [ ! -z "$(pidof smbd)" ] && systemctl restart smbd
}

scsi_disk_format() {
  local device_name=$1
  local filesystem=$2
  local blk=${device_name:0:3}

  scsi_disk_remove ${device_name} $blk
  if [ "X${blk}" = "X${device_name}" ]; then
    parted -s /dev/$device_name "mktable gpt"
    parted -s /dev/$device_name "mkpart primary ext2 0% 100%"
    device_name=/dev/${device_name}1
  fi

  case $filesystem in
  exfat)
    [ ! -z "$partnumber" ] && parted -s /dev/$blk "set $partnumber msftdata on"
    mkfs.exfat /dev/$device_name >/dev/null 2>&1
    ;;
  ntfs)
    mkfs.ntfs -f /dev/$device_name >/dev/null 2>&1 #ntfs快速格式化
    ;;
  btrfs)
    echo -e "y\n" | mkfs.btrfs -n 64k -f /dev/$device_name >/dev/null 2>&1 #btrfs强制格式化并修改nodesize为64k
    ;;
  ext4)
    echo -e "y\n" | mkfs.ext4 -E lazy_itable_init=1,lazy_journal_init=1 /dev/$device_name >/dev/null 2>&1 #ext4格式化并延迟初始化
    tune2fs -O ea_inode /dev/$device_name >/dev/null 2>&1                                                 #打开ea_inode支持
    ;;
  *)
    echo -e "y\n" | mkfs.$filesystem /dev/$device_name >/dev/null 2>&1
    ;;
  esac

  scsi_disk_insert ${blk}
}

# insert process
if [ ${scsi_disk_op} = "insert" ]; then
  scsi_disk_insert "$2"
  processExit 0
fi

# remove process
if [ ${scsi_disk_op} = "remove" ] || [ ${scsi_disk_op} = "delete" ]; then
  scsi_disk_remove "$2"
  processExit 0
fi

# format process
if [ ${scsi_disk_op} = "format" ]; then
  if [ "X${3}" = "X" ]; then
    echo "eg: ${0} [format] [sda|sdb|sdc|...] [NTFS|VFAT|EXT4]"
    processExit 1
  else
    scsi_disk_format "$2" "$3"
    processExit 0
  fi
fi
