1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/* 2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2008 The Android Open Source Project 3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * 4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License. 6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at 7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * 8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * 10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software 11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and 14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License. 15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */ 16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 17f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdio.h> 18f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdlib.h> 19f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <unistd.h> 20f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <string.h> 21f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <signal.h> 22f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <errno.h> 23f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <fcntl.h> 24092aa1c585fedd9e169eece41b8a471f1739908aPeter Bohm#include <stdlib.h> 2547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey#include <poll.h> 26f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 27f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <sys/socket.h> 28f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <sys/select.h> 29f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <sys/time.h> 30f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <sys/types.h> 31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <sys/un.h> 32f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 33c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry#include <android-base/logging.h> 3447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey#include <android-base/stringprintf.h> 3547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/sockets.h> 37f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <private/android_filesystem_config.h> 38f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic void usage(char *progname); 40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int do_monitor(int sock, int stop_after_cmd); 41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int do_cmd(int sock, int argc, char **argv); 42f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 4347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystatic constexpr int kCommandTimeoutMs = 20 * 1000; 4447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint main(int argc, char **argv) { 46f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat int sock; 47f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence int wait_for_socket; 485e900ac898bd9d96d6fded95c0b9c080dda54e8fMohamad Ayyash char *progname; 49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 505e900ac898bd9d96d6fded95c0b9c080dda54e8fMohamad Ayyash progname = argv[0]; 51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 52c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry if (getppid() == 1) { 53c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry // If init is calling us then it's during boot and we should log to kmsg 54c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry android::base::InitLogging(argv, &android::base::KernelLogger); 55c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry } else { 56c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry android::base::InitLogging(argv, &android::base::StderrLogger); 57c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry } 58c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry 595e900ac898bd9d96d6fded95c0b9c080dda54e8fMohamad Ayyash wait_for_socket = argc > 1 && strcmp(argv[1], "--wait") == 0; 6047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (wait_for_socket) { 61f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence argv++; 62f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence argc--; 63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 6547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (argc < 2) { 665e900ac898bd9d96d6fded95c0b9c080dda54e8fMohamad Ayyash usage(progname); 67f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence exit(5); 685e900ac898bd9d96d6fded95c0b9c080dda54e8fMohamad Ayyash } 69f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence 70d0b4295ccc07d0cd715ade415c8c0d7d6945880ePaul Lawrence const char* sockname = "vold"; 71d0b4295ccc07d0cd715ade415c8c0d7d6945880ePaul Lawrence if (!strcmp(argv[1], "cryptfs")) { 72d0b4295ccc07d0cd715ade415c8c0d7d6945880ePaul Lawrence sockname = "cryptd"; 73d0b4295ccc07d0cd715ade415c8c0d7d6945880ePaul Lawrence } 74d0b4295ccc07d0cd715ade415c8c0d7d6945880ePaul Lawrence 75d0b4295ccc07d0cd715ade415c8c0d7d6945880ePaul Lawrence while ((sock = socket_local_client(sockname, 76f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence ANDROID_SOCKET_NAMESPACE_RESERVED, 77f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence SOCK_STREAM)) < 0) { 7847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (!wait_for_socket) { 79c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry PLOG(ERROR) << "Error connecting to " << sockname; 80f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence exit(4); 81f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence } else { 820628fa25141261e549f06d1c6f9e9f3d29e2b8f0Paul Lawrence usleep(10000); 83f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence } 84f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence } 85f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence 86f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence if (!strcmp(argv[1], "monitor")) { 87f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat exit(do_monitor(sock, 0)); 88f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence } else { 89f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence exit(do_cmd(sock, argc, argv)); 90f4faa575c9fc20a8a8e133d6098865b5ce3a7ed2Paul Lawrence } 91f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 92f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 93f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int do_cmd(int sock, int argc, char **argv) { 9447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey int seq = getpid(); 95f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 9647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey std::string cmd(android::base::StringPrintf("%d ", seq)); 9747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey for (int i = 1; i < argc; i++) { 9847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (!strchr(argv[i], ' ')) { 9947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey cmd.append(argv[i]); 10047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } else { 10147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey cmd.push_back('\"'); 10247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey cmd.append(argv[i]); 10347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey cmd.push_back('\"'); 10447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 105f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 10647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (i < argc - 1) { 10747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey cmd.push_back(' '); 10847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 109f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 110f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 11147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (TEMP_FAILURE_RETRY(write(sock, cmd.c_str(), cmd.length() + 1)) < 0) { 112c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry PLOG(ERROR) << "Failed to write command"; 113f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return errno; 114f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 115f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 11647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey return do_monitor(sock, seq); 117f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 118f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 11947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystatic int do_monitor(int sock, int stop_after_seq) { 12047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey char buffer[4096]; 12147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey int timeout = kCommandTimeoutMs; 122f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 12347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (stop_after_seq == 0) { 124c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry LOG(INFO) << "Connected to vold"; 12547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey timeout = -1; 12647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 12847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey while (1) { 12947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey struct pollfd poll_sock = { sock, POLLIN, 0 }; 13047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey int rc = TEMP_FAILURE_RETRY(poll(&poll_sock, 1, timeout)); 13147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (rc == 0) { 132c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry LOG(ERROR) << "Timeout waiting for " << stop_after_seq; 133f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return ETIMEDOUT; 13447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } else if (rc < 0) { 135c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry PLOG(ERROR) << "Failed during poll"; 13647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey return errno; 13747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 13947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (!(poll_sock.revents & POLLIN)) { 140c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry LOG(INFO) << "No data; trying again"; 14147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey continue; 14247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 143f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 14447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey memset(buffer, 0, sizeof(buffer)); 14547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey rc = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); 14647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (rc == 0) { 147c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry LOG(ERROR) << "Lost connection, did vold crash?"; 14847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey return ECONNRESET; 14947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } else if (rc < 0) { 150c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry PLOG(ERROR) << "Error reading data"; 15147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey return errno; 15247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 153f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 15447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey int offset = 0; 15547695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey for (int i = 0; i < rc; i++) { 15647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (buffer[i] == '\0') { 15747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey char* res = buffer + offset; 15847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey fprintf(stdout, "%s\n", res); 15947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 16047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey int code = atoi(strtok(res, " ")); 16147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (code >= 200 && code < 600) { 16247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey int seq = atoi(strtok(nullptr, " ")); 16347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (seq == stop_after_seq) { 16447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey if (code == 200) { 165f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return 0; 16647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } else { 16747695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey return code; 16847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey } 169f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 170f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 17147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey 17247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey offset = i + 1; 173f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 174f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 175f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat } 17647695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey return EIO; 177f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 178f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 179f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic void usage(char *progname) { 180c61581e7d25dd7a736d487e4db85b61adb336144Tom Cherry LOG(INFO) << "Usage: " << progname << " [--wait] <monitor>|<cmd> [arg1] [arg2...]"; 18147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey} 182