| #!/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 |