blob: 9055ce8153c5398d4ec8b9448e095b860da24800 [file] [log] [blame]
#!/bin/sh
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This script can maintain a log file across stateful partition wiping
# transition.
CLOBBER_LOG_FILE="clobber.log"
# Temp folder is always accessible (by tmpfs), but stateful partition may be not
# available. To verify that, check the existence of STATEFUL_LOG_FOLDER.
STATEFUL_LOG_FOLDER="/mnt/stateful_partition/unencrypted/"
STATEFUL_LOG_PATH="${STATEFUL_LOG_FOLDER}/${CLOBBER_LOG_FILE}"
TMP_LOG_PATH="/tmp/${CLOBBER_LOG_FILE}"
PSTORE_PATH="/sys/fs/pstore"
RAMOOPS_LOG="${PSTORE_PATH}/console-ramoops"
MAX_KEEP_LOG_LINES=1024
RAMOOPS_DUMP_LINES=128
mount_pstore() {
# Copied from pstore.conf. clobber-state is always executed before
# boot-services so pstore.conf won't be ready at that time and we have to
# mount now.
if ! mountpoint -q "${PSTORE_PATH}"; then
mount -n -t pstore -o nodev,nosuid,noexec pstore "${PSTORE_PATH}" || true
fi
}
log_prefix() {
echo "$(date --utc '+%Y/%m/%d %H:%M:%S') UTC"
}
preserve_log() {
# Try to copy log from stateful partition to tmp.
local source_path="${STATEFUL_LOG_PATH}"
local dest_path="${TMP_LOG_PATH}"
# TODO(hungte) store log in some special place, like last sector of stateful
# partition so that logs won't be lost if user interrupts during wiping.
if [ -s "${source_path}" ]; then
tail -n "${MAX_KEEP_LOG_LINES}" "${source_path}" >"${dest_path}"
else
echo "No prior clobber-log found" >>"${dest_path}"
fi
echo "$(log_prefix) (preserve log): $*" >>"${dest_path}"
}
restore_log() {
# Try to copy log from tmp back to stateful partition.
local source_path="${TMP_LOG_PATH}"
local dest_path="${STATEFUL_LOG_PATH}"
# the mode should be matched to chromeos_startup.
mkdir -p -m 0755 "${STATEFUL_LOG_FOLDER}"
if [ -s "${source_path}" ]; then
cp "${source_path}" "${dest_path}"
fi
echo "$(log_prefix) (restore log): $*" >>"${dest_path}"
}
find_log_path() {
# Always use log in stateful partition, otherwise create in temp.
local dest_path="${STATEFUL_LOG_PATH}"
if [ ! -d "${STATEFUL_LOG_FOLDER}" ]; then
dest_path="${TMP_LOG_PATH}"
fi
echo "${dest_path}"
}
append_log() {
# Add one line of log into the clobber log file.
local dest_path
dest_path="$(find_log_path)"
echo "$(log_prefix) $*" >>"${dest_path}"
}
append_logfile() {
# Add MAX_KEEP_LOG_LINES from file into log.
local dest_path="$(find_log_path)"
local source_path="$1"
if [ ! -f "${source_path}" ]; then
echo "File not found: ${source_path}"
return
fi
echo "-- $(basename ${source_path}) --" >> "${dest_path}"
tail -n ${MAX_KEEP_LOG_LINES} "${source_path}" >> "${dest_path}"
echo "-- end of logfile --" >> "${dest_path}"
echo "$(log_prefix) (append_logfile): $@" >>"$dest_path"
}
repair_log() {
# Report detail messages for the status of stateful partition.
local dest_path="${TMP_LOG_PATH}"
# TODO(hungte) try to recover logs from some where - see preserve_log.
if [ ! -b "$1" ]; then
echo "$(log_prefix) repair: $1: invalid device file." >>"${dest_path}"
return
fi
echo "$(log_prefix) (repair): $*" >>"${dest_path}"
# "fsck -n" and "mount -v" may also help.
dumpe2fs -fh "$1" >>"${dest_path}" 2>&1
mount_pstore
echo "-- Ramoops (logs from last boot):" >>"${dest_path}"
# There might be more than one record, so grab them all with a glob.
# Plus, for <linux-3.19, it's named "console-ramoops", but for newer
# versions, it's named "console-ramoops-#".
local ramoops
for ramoops in "${RAMOOPS_LOG}"*; do
if [ -f "${ramoops}" ]; then
echo "${ramoops}"
tail -n "${RAMOOPS_DUMP_LINES}" "${ramoops}" >>"${dest_path}" 2>/dev/null
else
echo "(No ramoops found, sorry)" >>"${dest_path}"
fi
done
# try to dump first several blocks
(
echo "-- File system $1 block data (gz+base64):"
dd if="$1" bs=1M count=1 | gzip -c | base64 2>/dev/null
echo "-- File system $1 block data dump complete."
) >>"${dest_path}"
# to read back the block data, extract to a file and do
# cat block | base64 -d | gunzip -c -d > block.bin
}
# Process the very limited commands
case "$1" in
--preserve )
shift
preserve_log "$@"
;;
--restore )
shift
restore_log "$@"
;;
--repair )
shift
repair_log "$@"
;;
--append_logfile )
shift
append_logfile "$@"
;;
-- )
shift
append_log "$@"
;;
* )
append_log "$@"
;;
esac