| #! /bin/bash |
| # Copyright 2013 Google Inc. All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| # Mount a disk, formatting it if necessary. If the disk looks like it may |
| # have been formatted before, we will not format it. |
| # |
| # This script uses blkid and file to search for magic "formatted" bytes |
| # at the beginning of the disk. Furthermore, it attempts to use fsck to |
| # repair the filesystem before formatting it. |
| |
| FSCK=fsck.ext4 |
| MOUNT_OPTIONS="discard,defaults" |
| MKFS="mkfs.ext4 -E lazy_itable_init=0,lazy_journal_init=0,discard -F" |
| if [ -f /etc/redhat-release ]; then |
| if grep -q '6\..' /etc/redhat-release; then |
| # lazy_journal_init is not recognized in redhat 6 |
| MKFS="mkfs.ext4 -E lazy_itable_init=0 -F" |
| elif grep -q '7\..' /etc/redhat-release; then |
| FSCK=fsck.xfs |
| MKFS=mkfs.xfs |
| fi |
| fi |
| |
| LOGTAG=safe_format_and_mount |
| LOGFACILITY=user |
| |
| function log() { |
| local readonly severity=$1; shift; |
| logger -t ${LOGTAG} -p ${LOGFACILITY}.${severity} -s "$@" |
| } |
| |
| function log_command() { |
| local readonly log_file=$(mktemp) |
| local readonly retcode |
| log info "Running: $*" |
| $* > ${log_file} 2>&1 |
| retcode=$? |
| # only return the last 1000 lines of the logfile, just in case it's HUGE. |
| tail -1000 ${log_file} | logger -t ${LOGTAG} -p ${LOGFACILITY}.info -s |
| rm -f ${log_file} |
| return ${retcode} |
| } |
| |
| function help() { |
| cat >&2 <<EOF |
| $0 [-f fsck_cmd] [-m mkfs_cmd] [-o mount_opts] <device> <mountpoint> |
| EOF |
| exit 0 |
| } |
| |
| while getopts ":hf:o:m:" opt; do |
| case $opt in |
| h) help;; |
| f) FSCK=$OPTARG;; |
| o) MOUNT_OPTIONS=$OPTARG;; |
| m) MKFS=$OPTARG;; |
| -) break;; |
| \?) log error "Invalid option: -${OPTARG}"; exit 1;; |
| :) log "Option -${OPTARG} requires an argument."; exit 1;; |
| esac |
| done |
| |
| shift $(($OPTIND - 1)) |
| readonly DISK=$1 |
| readonly MOUNTPOINT=$2 |
| |
| [[ -z ${DISK} ]] && help |
| [[ -z ${MOUNTPOINT} ]] && help |
| |
| function disk_looks_unformatted() { |
| blkid ${DISK} |
| if [[ $? == 0 ]]; then |
| return 0 |
| fi |
| |
| local readonly file_type=$(file --special-files ${DISK}) |
| case ${file_type} in |
| *filesystem*) |
| return 0;; |
| esac |
| |
| return 1 |
| } |
| |
| function format_disk() { |
| log_command ${MKFS} ${DISK} |
| } |
| |
| function try_repair_disk() { |
| log_command ${FSCK} -a ${DISK} |
| local readonly fsck_return=$? |
| if [[ ${fsck_return} -ge 8 ]]; then |
| log error "Fsck could not correct errors on ${DISK}" |
| return 1 |
| fi |
| if [[ ${fsck_return} -gt 0 ]]; then |
| log warning "Fsck corrected errors on ${DISK}" |
| fi |
| return 0 |
| } |
| |
| function try_mount() { |
| local mount_retcode |
| try_repair_disk |
| |
| log_command mount -o ${MOUNT_OPTIONS} ${DISK} ${MOUNTPOINT} |
| mount_retcode=$? |
| if [[ ${mount_retcode} == 0 ]]; then |
| return 0 |
| fi |
| |
| # Check to see if it looks like a filesystem before formatting it. |
| disk_looks_unformatted ${DISK} |
| if [[ $? == 0 ]]; then |
| log error "Disk ${DISK} looks formatted but won't mount. Giving up." |
| return ${mount_retcode} |
| fi |
| |
| # The disk looks like it's not been formatted before. |
| format_disk |
| if [[ $? != 0 ]]; then |
| log error "Format of ${DISK} failed." |
| fi |
| |
| log_command mount -o ${MOUNT_OPTIONS} ${DISK} ${MOUNTPOINT} |
| mount_retcode=$? |
| if [[ ${mount_retcode} == 0 ]]; then |
| return 0 |
| fi |
| log error "Tried everything we could, but could not mount ${DISK}." |
| return ${mount_retcode} |
| } |
| |
| try_mount |
| exit $? |