diff options
Diffstat (limited to 'cmds/dumpstate/utils.c')
-rw-r--r-- | cmds/dumpstate/utils.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c new file mode 100644 index 0000000..60d845f --- /dev/null +++ b/cmds/dumpstate/utils.c @@ -0,0 +1,230 @@ +/* + * 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 <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/stat.h> +#include <dirent.h> +#include <limits.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/time.h> +#include <sys/wait.h> + +#include <cutils/properties.h> +#include <sys/system_properties.h> + +#include "dumpstate.h" + + +/* prints the contents of a file */ +int dump_file(const char* path) { + char buffer[32768]; + int fd, amount_read; + int ret = 0; + + fd = open(path, O_RDONLY); + if (fd < 0) + return fd; + + do { + ret = read(fd, buffer, sizeof(buffer)); + if (ret > 0) + ret = write(STDOUT_FILENO, buffer, ret); + } while (ret > 0); + + buffer[0] = '\n'; + write(STDOUT_FILENO, buffer, 1); + + close(fd); + return ret; +} + +/* prints the contents of all files in a directory */ +void dump_files(const char* path) { + DIR* dir; + struct dirent* entry; + char buffer[PATH_MAX]; + + dir = opendir(path); + if (!dir) { + fprintf(stderr, "could not open directory %s\n", path); + return; + } + + while ((entry = readdir(dir))) { + if (entry->d_type == DT_REG) { + snprintf(buffer, sizeof(buffer), "%s/%s", path, entry->d_name); + dump_file(path); + printf("\n"); + } + } + + closedir(dir); +} + +/* prints the name and value of a system property */ +int print_property(const char* name) { + char value[PROP_VALUE_MAX]; + + __system_property_get(name, value); + printf("%s=%s\n", name, value); + return 0; +} + +static pid_t alarm_pid = 0; +static int timed_out = 0; +static void sig_alarm(int sig) +{ + if (alarm_pid) { + kill(alarm_pid, SIGKILL); + timed_out = 1; + alarm_pid = 0; + } +} + +/* forks a command and waits for it to finish */ +int run_command(struct Command* cmd, int timeout) { + struct sigaction sa; + pid_t pid; + int status; + + pid = fork(); + /* handle error case */ + if (pid < 0) + return pid; + + /* handle child case */ + if (pid == 0) { + int ret = execv(cmd->path, cmd->args); + if (ret) + fprintf(stderr, "execv %s returned %d\n", cmd->path, ret); + exit(ret); + } + + /* handle parent case */ + timed_out = 0; + if (timeout) { + memset(&sa, 0, sizeof(sa)); + sa.sa_flags = SA_RESETHAND; + sa.sa_handler = sig_alarm; + sigaction(SIGALRM, &sa, NULL); + + /* set an alarm so we don't hang forever */ + alarm_pid = pid; + alarm(timeout); + } + + waitpid(pid, &status, 0); + + if (timed_out) + printf("ERROR: command %s timed out\n", cmd->path); + + return status; +} + +/* reads the current time into tm */ +void get_time(struct tm *tm) { + time_t t; + + tzset(); + time(&t); + localtime_r(&t, tm); +} + +/* prints the date in tm */ +void print_date(const char* prompt, struct tm *tm) { + char strbuf[260]; + + strftime(strbuf, sizeof(strbuf), + "%a %b %e %H:%M:%S %Z %Y", + tm); + printf("%s%s\n", prompt, strbuf); +} + + +static void print_prop(const char *key, const char *name, + void *user __attribute__((unused))) +{ + printf("[%s]: [%s]\n", key, name); +} + +/* prints all the system properties */ +void print_properties() { + property_list(print_prop, NULL); +} + +/* creates directories as needed for the given path */ +void create_directories(char *path) +{ + char *chp = path; + + /* skip initial slash */ + if (chp[0] == '/') + chp++; + + while (chp && chp[0]) { + chp = strchr(chp, '/'); + if (chp) { + *chp = 0; + mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + *chp = '/'; + chp++; + } + } +} + +/* runs the vibrator using the given pattern */ +void vibrate_pattern(int fd, int* pattern) +{ + struct timespec tm; + char buffer[10]; + + while (*pattern) { + /* read vibrate on time */ + int on_time = *pattern++; + snprintf(buffer, sizeof(buffer), "%d", on_time); + write(fd, buffer, strlen(buffer)); + + /* read vibrate off time */ + int delay = *pattern++; + if (delay) { + delay += on_time; + + tm.tv_sec = delay / 1000; + tm.tv_nsec = (delay % 1000) * 1000000; + nanosleep(&tm, NULL); + } else + break; + } +} + +/* prevents the OOM killer from killing us */ +void protect_from_oom_killer() +{ + int fd; + + fd = open("/proc/self/oom_adj", O_WRONLY); + if (fd >= 0) { + // -17 should make us immune to OOM + const char* text = "-17"; + write(fd, text, strlen(text)); + close(fd); + } +} |