blob: 0b0113ff626b0f44b332c63a15810d4d8b435891 [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.
SCRIPT="$0"
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
BLOCK_DUMP_LINES=64
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"
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="$(find_log_path)"
echo "$(log_prefix) $@" >>"$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):" >>"$dest_path"
dd if="$1" bs=1M count=1 | gzip -c | base64 |
head -n $BLOCK_DUMP_LINES >>"$dest_path" 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 "$@"
;;
-- )
shift
append_log "$@"
;;
* )
append_log "$@"
;;
esac