| #!/system/bin/sh |
| |
| # Copyright 2016 Nest Labs, Inc. All rights reserved. |
| |
| # Base directory that contains any log reporter state files. |
| LOG_STATE_DIR="/data/misc/logrotate" |
| LOG_DIR="/data/misc/logd/" |
| |
| # Max upload/download rate |
| LIMIT_RATE="200K" |
| |
| # Log sender lock in case the sender is already running. |
| LOG_SENDER_LOCK="${LOG_STATE_DIR}/lock/log_sender" |
| # File descriptor to reference lock file, single digit only in Android Shell(mksh) |
| LOG_SENDER_LOCK_FD=9 |
| |
| # Path to a CA certificate file for log server |
| CA_CERTIFICATES_FILE_PATH="/system/etc/dropcam_calist.pem" |
| SSL_CERT="/data/misc/certs/device_cert.pem" |
| SSL_CERT_TYPE="PEM" |
| SSL_KEY="/data/misc/certs/device_cert.key" |
| SSL_KEY_TYPE="PEM" |
| |
| # File whose existence implies we're running and not to start again. |
| RUN_FILE="${LOG_STATE_DIR}/run/log_sender.pid" |
| |
| # The tag for all logging we emit. |
| TAG="$(basename $0)[$$]" |
| |
| # Directory to store timestamp files indicating the uploads in the past 24 |
| # hours. |
| TIMESTAMPS_DIR="${LOG_STATE_DIR}/log_sender" |
| |
| # Temp directory for this process. |
| TMP_DIR="" |
| |
| lecho() { |
| log -t "${TAG}" "$@" |
| } |
| |
| lwarn() { |
| lecho -psyslog.warn "$@" |
| } |
| |
| die () { |
| lecho $@ |
| lecho "Exit" |
| exit 1 |
| } |
| |
| cleanup() { |
| if [ -n "${TMP_DIR}" ]; then |
| rm -rf "${TMP_DIR}" |
| fi |
| rm -f "${RUN_FILE}" |
| # clean all log_sender files in case things are going wrong |
| rm -rf /data/misc/logrotate/tmp/log_sender* |
| } |
| |
| # Returns true if uploading is enabled |
| is_upload_enabled() { |
| [ "$(get_key_value "log.upload_enabled")" -eq 1 ] && return 0 |
| return 1 |
| } |
| |
| get_key_value() { |
| local key="$1" value |
| |
| value=`getprop persist.nl.${key}` |
| |
| echo "${value:-undefined}" |
| } |
| |
| send_log() { |
| local log_path="$1" |
| local url="$(get_key_value "log.server")" |
| local send_size="$(stat -c "%s" "${log_path}" 2>/dev/null)" |
| local mac=`sysenv get hwaddr0` |
| # Cloud does not parse ":" in MAC address, so remove all of them |
| mac=${mac//":"/""} |
| |
| # If log_reporter.server is not set return with an error. |
| if [ -z "${url}" ]; then |
| lecho "Configuration error: log server not set." |
| return 1 |
| fi |
| |
| if [[ -z "${mac}" || ${#mac} -ne 12 ]]; then |
| lecho "Configuration error: mac address is invalid." |
| return 1 |
| fi |
| |
| lecho "Sending log:" |
| lecho " MAC: ${mac}" |
| lecho " File: ${log_path}" |
| lecho " URL: ${url}" |
| lecho " Size: ${send_size}" |
| |
| local curl_stderr="${TMP_DIR}/curl_stderr" |
| local curl_report="${TMP_DIR}/report" |
| |
| set +e |
| curl -vvv "${url}" \ |
| --cacert "${CA_CERTIFICATES_FILE_PATH}" \ |
| --cert "${SSL_CERT}" \ |
| --cert-type "${SSL_CERT_TYPE}" \ |
| --key "${SSL_KEY}" \ |
| --key-type "${SSL_KEY_TYPE}" \ |
| --limit-rate "${LIMIT_RATE}" \ |
| -F "mac=${mac}" \ |
| -F "file=@${log_path};type=application/octet-stream" \ |
| -o "${curl_report}" \ |
| 2>"${curl_stderr}" |
| curl_result=$? |
| set -e |
| |
| if [ -f ${curl_report} ]; then |
| lecho "Message from server: " \ |
| "$(cat "${curl_report}")" |
| fi |
| |
| if [ ${curl_result} -eq 0 ]; then |
| local timestamp="$(date +%s)" |
| lecho "Log ${log_path} has been sent at ${timestamp}" |
| else |
| lecho "Log sending failed with exit code ${curl_result}: " \ |
| "$(cat "${curl_stderr}")" |
| fi |
| |
| rm -f "${curl_report}" |
| rm -f "${curl_stderr}" |
| |
| return ${curl_result} |
| } |
| |
| # *.meta files always end with done=1 so we can tell if they are complete. |
| # Remove the given report path. |
| remove_report() { |
| rm -f -- "${1}" |
| } |
| |
| # Send all logs from the given directory. |
| send_logs() { |
| local dir="$1" |
| lecho "Sending logs for ${dir}" |
| |
| if [ ! -d "${dir}" ]; then |
| die "Can't find directory ${dir}" |
| fi |
| |
| # start from old |
| for log_path in $(ls -1tr "${dir}"/messages.*.gz 2>/dev/null); do |
| lecho "Considering log ${log_path}." |
| |
| # Try to upload. |
| if ! send_log "${log_path}"; then |
| lecho "Problem sending ${log_path}, not removing." |
| continue |
| fi |
| |
| # Send was successful, now remove. |
| lecho "Successfully sent log ${log_path} and removing." |
| remove_report "${log_path}" |
| done |
| } |
| |
| main() { |
| |
| lecho "Starting log uploading..." |
| |
| if ! is_upload_enabled; |
| then |
| lecho "Log uploading is disabled. Exit." |
| exit 0; |
| fi |
| |
| # We don't perform checks on this because we have a master lock with the |
| # LOG_SENDER_LOCK file. This pid file is for the system to keep track |
| # that we're still running. |
| echo $$ > "${RUN_FILE}" |
| |
| TMP_DIR="$(mktemp -d "${LOG_STATE_DIR}/tmp/log_sender.XXXXXX")" |
| if [ $? -ne 0 ]; then |
| die "Failed to create TMP_DIR: ${LOG_STATE_DIR}/tmp/log_sender.XXXXX" |
| fi |
| |
| # Send system-wide logs |
| send_logs "${LOG_DIR}" |
| } |
| |
| trap cleanup EXIT INT TERM |
| |
| mkdir -p $(dirname ${LOG_SENDER_LOCK}) |
| ( |
| # -x:Exclusive lock, -n:Non-blocking |
| flock -xn 9 || die "Failed to acquire lock!" |
| main "$@" |
| ) 9>$LOG_SENDER_LOCK |