Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 92 lines (84 sloc) 2.88 KB
#!/bin/bash
set -e -f -u -o pipefail
PATH="/sbin:${PATH}"
# Think about using tmutil on my laptop to disable and enable backups.
fix_single_volume() {
local directory="$1" verbose="$2"
if [[ "${verbose}" -eq 1 ]]; then
printf "Repairing %s\\n" "${directory}"
fi
chflags -R nouchg "${directory}"
# Do I need to disable SMB? Will that even unlock things? Is there a tool to
# list locks? Will rebooting fix anything? Can I enable or disable shares
# individually? Would putting the backups into different subdirs help with
# sharing more precisely?
# $ launchctl unload -w /System/Library/LaunchDaemons/com.apple.smbd.plist
# $ launchctl load -w /System/Library/LaunchDaemons/com.apple.smbd.plist
if [[ "${verbose}" -eq 1 ]]; then
printf "If hdiutil attach fails, it's probably because the volume is in use"
printf "\\nWait a while and try again seems to be the best option\\n"
fi
local output
output="$(mktemp -t hdiutil.XXXXXXXXXX)"
# Do I need -verbose -noverify -noautofsck ?
hdiutil attach -readwrite -nomount "${directory}" > "${output}"
# Need the line containing Apple_HFS.*
# Output:
# /dev/disk5 GUID_partition_scheme
# /dev/disk5s1 EFI
# /dev/disk5s2 Apple_HFS
local device
device="$(awk '/Apple_HFS/ { print $1 }' "${output}")"
rm -f "${output}"
trap 'hdiutil detach "${device}" > /dev/null' ERR
local i max=5
# Multiple attempts seem to help, so try a few times.
for i in $(seq 1 "${max}"); do
if [[ "${verbose}" -eq 1 ]]; then
printf "\\n\\nAttempt %d/%d\\n" "${i}" "${max}"
fi
local fsck_args=("-f" "-y" "-R" "ace") dest="/dev/null"
if [[ "${verbose}" -eq 1 ]]; then
dest="/dev/stdout"
if [[ "${i}" -gt 2 ]]; then
# Add debugging after a few attempts.
fsck_args+=("-d")
fi
fi
# -R ace rebuilds everything.
if fsck_hfs "${fsck_args[@]}" "${device}" > "${dest}"; then
if [[ "${verbose}" -eq 1 ]]; then
printf "\\n\\nRepair of %s succeeded on attempt %d/%d\\n" \
"${directory}" "${i}" "${max}"
fi
break
fi
if [[ "${i}" -eq "${max}" ]]; then
printf "\\n\\n%d repair attempts on %s failed :(\\n" \
"${max}" "${directory}" >&2
false
fi
done
hdiutil detach "${device}" > /dev/null
sed \
-e '/RecoveryBackupDeclinedDate/,/date/ d' \
-e 's,<integer>2</integer>,<integer>0</integer>,' \
-i .unedited \
"${directory}/com.apple.TimeMachine.MachineID.plist"
}
main() {
local dir exit_status=0 verbose=0
if [[ -t 0 ]]; then
verbose=1
fi
for dir in "$@"; do
# Bizzare Posix sh behaviour :( See
# https://unix.stackexchange.com/questions/65532/why-does-set-e-not-work-inside-subshells-with-parenthesis-followed-by-an-or
fix_single_volume "${dir}" "${verbose}" &
if ! wait "$!"; then
exit_status=1
fi
done
return "${exit_status}"
}
main "$@"