1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include <time.h> 21#include <unistd.h> 22#include <sys/stat.h> 23#include <dirent.h> 24#include <limits.h> 25#include <fcntl.h> 26#include <signal.h> 27#include <sys/time.h> 28#include <sys/wait.h> 29 30#include <cutils/properties.h> 31#include <sys/system_properties.h> 32 33#include "dumpstate.h" 34 35 36/* prints the contents of a file */ 37int dump_file(const char* path) { 38 char buffer[32768]; 39 int fd, amount_read; 40 int ret = 0; 41 42 fd = open(path, O_RDONLY); 43 if (fd < 0) 44 return fd; 45 46 do { 47 ret = read(fd, buffer, sizeof(buffer)); 48 if (ret > 0) 49 ret = write(STDOUT_FILENO, buffer, ret); 50 } while (ret > 0); 51 52 buffer[0] = '\n'; 53 write(STDOUT_FILENO, buffer, 1); 54 55 close(fd); 56 return ret; 57} 58 59/* prints the contents of all files in a directory */ 60void dump_files(const char* path) { 61 DIR* dir; 62 struct dirent* entry; 63 char buffer[PATH_MAX]; 64 65 dir = opendir(path); 66 if (!dir) { 67 fprintf(stderr, "could not open directory %s\n", path); 68 return; 69 } 70 71 while ((entry = readdir(dir))) { 72 if (entry->d_type == DT_REG) { 73 snprintf(buffer, sizeof(buffer), "%s/%s", path, entry->d_name); 74 dump_file(path); 75 printf("\n"); 76 } 77 } 78 79 closedir(dir); 80} 81 82/* prints the name and value of a system property */ 83int print_property(const char* name) { 84 char value[PROP_VALUE_MAX]; 85 86 __system_property_get(name, value); 87 printf("%s=%s\n", name, value); 88 return 0; 89} 90 91static pid_t alarm_pid = 0; 92static int timed_out = 0; 93static void sig_alarm(int sig) 94{ 95 if (alarm_pid) { 96 kill(alarm_pid, SIGKILL); 97 timed_out = 1; 98 alarm_pid = 0; 99 } 100} 101 102/* forks a command and waits for it to finish */ 103int run_command(struct Command* cmd, int timeout) { 104 struct sigaction sa; 105 pid_t pid; 106 int status; 107 108 pid = fork(); 109 /* handle error case */ 110 if (pid < 0) 111 return pid; 112 113 /* handle child case */ 114 if (pid == 0) { 115 int ret = execv(cmd->path, cmd->args); 116 if (ret) 117 fprintf(stderr, "execv %s returned %d\n", cmd->path, ret); 118 exit(ret); 119 } 120 121 /* handle parent case */ 122 timed_out = 0; 123 if (timeout) { 124 memset(&sa, 0, sizeof(sa)); 125 sa.sa_flags = SA_RESETHAND; 126 sa.sa_handler = sig_alarm; 127 sigaction(SIGALRM, &sa, NULL); 128 129 /* set an alarm so we don't hang forever */ 130 alarm_pid = pid; 131 alarm(timeout); 132 } 133 134 waitpid(pid, &status, 0); 135 136 if (timed_out) 137 printf("ERROR: command %s timed out\n", cmd->path); 138 139 return status; 140} 141 142/* reads the current time into tm */ 143void get_time(struct tm *tm) { 144 time_t t; 145 146 tzset(); 147 time(&t); 148 localtime_r(&t, tm); 149} 150 151/* prints the date in tm */ 152void print_date(const char* prompt, struct tm *tm) { 153 char strbuf[260]; 154 155 strftime(strbuf, sizeof(strbuf), 156 "%a %b %e %H:%M:%S %Z %Y", 157 tm); 158 printf("%s%s\n", prompt, strbuf); 159} 160 161 162static void print_prop(const char *key, const char *name, 163 void *user __attribute__((unused))) 164{ 165 printf("[%s]: [%s]\n", key, name); 166} 167 168/* prints all the system properties */ 169void print_properties() { 170 property_list(print_prop, NULL); 171} 172 173/* creates directories as needed for the given path */ 174void create_directories(char *path) 175{ 176 char *chp = path; 177 178 /* skip initial slash */ 179 if (chp[0] == '/') 180 chp++; 181 182 while (chp && chp[0]) { 183 chp = strchr(chp, '/'); 184 if (chp) { 185 *chp = 0; 186 mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 187 *chp = '/'; 188 chp++; 189 } 190 } 191} 192 193/* runs the vibrator using the given pattern */ 194void vibrate_pattern(int fd, int* pattern) 195{ 196 struct timespec tm; 197 char buffer[10]; 198 199 while (*pattern) { 200 /* read vibrate on time */ 201 int on_time = *pattern++; 202 snprintf(buffer, sizeof(buffer), "%d", on_time); 203 write(fd, buffer, strlen(buffer)); 204 205 /* read vibrate off time */ 206 int delay = *pattern++; 207 if (delay) { 208 delay += on_time; 209 210 tm.tv_sec = delay / 1000; 211 tm.tv_nsec = (delay % 1000) * 1000000; 212 nanosleep(&tm, NULL); 213 } else 214 break; 215 } 216} 217 218/* prevents the OOM killer from killing us */ 219void protect_from_oom_killer() 220{ 221 int fd; 222 223 fd = open("/proc/self/oom_adj", O_WRONLY); 224 if (fd >= 0) { 225 // -17 should make us immune to OOM 226 const char* text = "-17"; 227 write(fd, text, strlen(text)); 228 close(fd); 229 } 230} 231