/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/select.h> #include <sys/time.h> #include <sys/types.h> #include <sys/un.h> #include <cutils/sockets.h> #include <private/android_filesystem_config.h> static void usage(char *progname); static int do_monitor(int sock, int stop_after_cmd); static int do_cmd(int sock, int argc, char **argv); int main(int argc, char **argv) { int sock; int wait_for_socket; char *progname; progname = argv[0]; wait_for_socket = argc > 1 && strcmp(argv[1], "--wait") == 0; if(wait_for_socket) { argv++; argc--; } if(argc < 2) { usage(progname); exit(5); } const char* sockname = "vold"; if (!strcmp(argv[1], "cryptfs")) { sockname = "cryptd"; } while ((sock = socket_local_client(sockname, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)) < 0) { if(!wait_for_socket) { fprintf(stderr, "Error connecting (%s)\n", strerror(errno)); exit(4); } else { usleep(10000); } } if (!strcmp(argv[1], "monitor")) { exit(do_monitor(sock, 0)); } else { exit(do_cmd(sock, argc, argv)); } } static int do_cmd(int sock, int argc, char **argv) { char final_cmd[255] = "0 "; /* 0 is a (now required) sequence number */ int i; size_t ret; for (i = 1; i < argc; i++) { char *cmp; if (!strchr(argv[i], ' ')) asprintf(&cmp, "%s%s", argv[i], (i == (argc -1)) ? "" : " "); else asprintf(&cmp, "\"%s\"%s", argv[i], (i == (argc -1)) ? "" : " "); ret = strlcat(final_cmd, cmp, sizeof(final_cmd)); if (ret >= sizeof(final_cmd)) abort(); free(cmp); } if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) { perror("write"); return errno; } return do_monitor(sock, 1); } static int do_monitor(int sock, int stop_after_cmd) { char *buffer = malloc(4096); if (!stop_after_cmd) printf("[Connected to Vold]\n"); while(1) { fd_set read_fds; struct timeval to; int rc = 0; to.tv_sec = 10; to.tv_usec = 0; FD_ZERO(&read_fds); FD_SET(sock, &read_fds); if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) { fprintf(stderr, "Error in select (%s)\n", strerror(errno)); free(buffer); return errno; } else if (!rc) { continue; fprintf(stderr, "[TIMEOUT]\n"); return ETIMEDOUT; } else if (FD_ISSET(sock, &read_fds)) { memset(buffer, 0, 4096); if ((rc = read(sock, buffer, 4096)) <= 0) { if (rc == 0) fprintf(stderr, "Lost connection to Vold - did it crash?\n"); else fprintf(stderr, "Error reading data (%s)\n", strerror(errno)); free(buffer); if (rc == 0) return ECONNRESET; return errno; } int offset = 0; int i = 0; for (i = 0; i < rc; i++) { if (buffer[i] == '\0') { int code; char tmp[4]; strlcpy(tmp, buffer + offset, sizeof(tmp)); code = atoi(tmp); printf("%s\n", buffer + offset); if (stop_after_cmd) { if (code >= 200 && code < 600) return 0; } offset = i + 1; } } } } free(buffer); return 0; } static void usage(char *progname) { fprintf(stderr, "Usage: %s [--wait] <monitor>|<cmd> [arg1] [arg2...]\n", progname); }