12628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme/* 22628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * Copyright (C) 2016 The Android Open Source Project 32628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * 42628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License"); 52628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * you may not use this file except in compliance with the License. 62628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * You may obtain a copy of the License at 72628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * 82628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * http://www.apache.org/licenses/LICENSE-2.0 92628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * 102628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * Unless required by applicable law or agreed to in writing, software 112628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS, 122628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * See the License for the specific language governing permissions and 142628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * limitations under the License. 152628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme */ 162628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 172628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <errno.h> 18ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme#include <getopt.h> 192628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <stdio.h> 202628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <sys/socket.h> 212628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <sys/types.h> 222628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <unistd.h> 232628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 242628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <cutils/properties.h> 252628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <cutils/sockets.h> 262628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 27ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemestatic constexpr char VERSION[] = "1.0"; 28ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme 29ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemestatic void show_usage() { 30ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme fprintf(stderr, 31ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme "usage: bugreportz [-h | -v]\n" 32ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme " -h: to display this help message\n" 33ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme " -v: to display the version\n" 34ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme " or no arguments to generate a zipped bugreport\n"); 35ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme} 36ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme 37ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemestatic void show_version() { 38ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme fprintf(stderr, "%s\n", VERSION); 39ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme} 40ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme 41ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemeint main(int argc, char *argv[]) { 42ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme 43ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme if (argc > 1) { 44ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme /* parse arguments */ 45ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme int c; 46ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme while ((c = getopt(argc, argv, "vh")) != -1) { 47ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme switch (c) { 48ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme case 'h': 49ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme show_usage(); 50ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme return EXIT_SUCCESS; 51ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme case 'v': 52ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme show_version(); 53ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme return EXIT_SUCCESS; 54ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme default: 55ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme show_usage(); 56ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme return EXIT_FAILURE; 57ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme } 58ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme } 59ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme // passed an argument not starting with - 60ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme if (optind > 1 || argv[optind] != nullptr) { 61ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme show_usage(); 62ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme return EXIT_FAILURE; 63ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme } 64ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme } 65ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme 66ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme // TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value); 67ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme // should be reused instead. 682628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 692628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme // Start the dumpstatez service. 702628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme property_set("ctl.start", "dumpstatez"); 712628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 722628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme // Socket will not be available until service starts. 732628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme int s; 742628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme for (int i = 0; i < 20; i++) { 752628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 762628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme if (s >= 0) 772628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme break; 782628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme // Try again in 1 second. 792628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme sleep(1); 802628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } 812628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 822628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme if (s == -1) { 831634d841af26421a76ef4c723095786da6d350a4Felipe Leme printf("FAIL:Failed to connect to dumpstatez service: %s\n", strerror(errno)); 841634d841af26421a76ef4c723095786da6d350a4Felipe Leme return EXIT_SUCCESS; 852628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } 862628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 872628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme // Set a timeout so that if nothing is read in 10 minutes, we'll stop 882628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme // reading and quit. No timeout in dumpstate is longer than 60 seconds, 892628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme // so this gives lots of leeway in case of unforeseen time outs. 902628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme struct timeval tv; 912628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme tv.tv_sec = 10 * 60; 922628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme tv.tv_usec = 0; 932628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { 941634d841af26421a76ef4c723095786da6d350a4Felipe Leme fprintf(stderr, "WARNING: Cannot set socket timeout: %s\n", strerror(errno)); 952628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } 962628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 972628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme while (1) { 982628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme char buffer[65536]; 992628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme ssize_t bytes_read = TEMP_FAILURE_RETRY( 1002628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme read(s, buffer, sizeof(buffer))); 1012628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme if (bytes_read == 0) { 1022628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme break; 1032628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } else if (bytes_read == -1) { 1042628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme // EAGAIN really means time out, so change the errno. 1052628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme if (errno == EAGAIN) { 1062628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme errno = ETIMEDOUT; 1072628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } 1081634d841af26421a76ef4c723095786da6d350a4Felipe Leme printf("FAIL:Bugreport read terminated abnormally (%s)\n", strerror(errno)); 1092628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme break; 1102628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } 1112628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 1122628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme ssize_t bytes_to_send = bytes_read; 1132628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme ssize_t bytes_written; 1142628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme do { 1152628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme bytes_written = TEMP_FAILURE_RETRY( 1162628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme write(STDOUT_FILENO, buffer + bytes_read - bytes_to_send, 1172628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme bytes_to_send)); 1182628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme if (bytes_written == -1) { 1191634d841af26421a76ef4c723095786da6d350a4Felipe Leme fprintf(stderr, 1202628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme "Failed to write data to stdout: read %zd, trying to send %zd (%s)\n", 1212628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme bytes_read, bytes_to_send, strerror(errno)); 1221634d841af26421a76ef4c723095786da6d350a4Felipe Leme break; 1232628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } 1242628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme bytes_to_send -= bytes_written; 1252628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } while (bytes_written != 0 && bytes_to_send > 0); 1262628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme } 1272628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme 1281634d841af26421a76ef4c723095786da6d350a4Felipe Leme if (close(s) == -1) { 1291634d841af26421a76ef4c723095786da6d350a4Felipe Leme fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno)); 1301634d841af26421a76ef4c723095786da6d350a4Felipe Leme } 131ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme return EXIT_SUCCESS; 1322628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme} 133