3 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 #include <sys/types.h>
23 #include <sys/sendfile.h>
40 #define READ_BUFF_SIZE 4096
41 #define SELECT_TIMEOUT_US 100000
43 int system_command_parallel(char *command)
46 const char *environ[] = { NULL };
57 argv[2] = (char *)command;
59 execve("/bin/sh", argv, (char **)environ);
66 int wait_system_command(int pid)
74 if (waitpid(pid, &status, 0) == -1) {
78 if (WIFEXITED(status))
79 return WEXITSTATUS(status);
80 else if (WIFSIGNALED(status))
81 return WTERMSIG(status);
82 else if (WIFSTOPPED(status))
83 return WSTOPSIG(status);
85 } while (!WIFEXITED(status) && !WIFSIGNALED(status));
90 int system_command(char *command)
94 pid = system_command_parallel(command);
96 return wait_system_command(pid);
99 int system_command_with_timeout(int timeout_seconds, char *command)
101 const char *environ[] = { NULL };
105 clock_t start = clock();
107 /* handle error case */
109 _E("fork: %d\n", errno);
112 /* handle child case */
117 argv[2] = (char *)command;
120 execve("/bin/sh", argv, (char **)environ);
121 _SI("exec(%s): %d\n", command, errno);
124 /* handle parent case */
127 pid_t p = waitpid(pid, &status, WNOHANG);
128 float elapsed = (float) (clock() - start) / CLOCKS_PER_SEC;
130 if (WIFSIGNALED(status))
131 _SI("%s: Killed by signal %d\n", command, WTERMSIG(status));
132 else if (WIFEXITED(status) && WEXITSTATUS(status) > 0)
133 _SI("%s: Exit code %d\n", command, WEXITSTATUS(status));
134 return WEXITSTATUS(status);
136 if (timeout_seconds && elapsed > timeout_seconds) {
137 _SI("%s: Timed out after %.1fs (killing pid %d)\n",
138 command, elapsed, pid);
142 /* poll every 0.1 sec */
147 int write_fd(int fd, const void *buf, int len)
153 count = write(fd, buf, len);
162 buf = ((const char *)buf) + count;
168 static int copy_bytes_sendfile(int destfd, int srcfd, off_t *ncopied)
174 nsent = sendfile(destfd, srcfd, NULL, INT32_MAX);
177 else if (nsent < 0 && errno == EAGAIN)
186 return nsent == -1 ? -1 : 0;
189 static int copy_bytes_rw(int destfd, int srcfd, off_t *ncopied)
196 n = read(srcfd, buf, sizeof buf);
198 if (errno == EAGAIN || errno == EINTR)
204 int m = write_fd(destfd, buf, n);
206 _E("failed to write data to destination fd: %m");
218 int copy_bytes(int destfd, int srcfd, off_t *ncopied)
220 int r = copy_bytes_sendfile(destfd, srcfd, ncopied);
221 return r == 0 ? r : copy_bytes_rw(destfd, srcfd, ncopied);
224 int copy_file(char *dst, char *src)
231 _E("Invalid argument\n");
234 sfd = open(src, O_RDONLY);
236 _E("Failed to open (%s)\n", src);
239 dfd = open(dst, O_WRONLY|O_CREAT|O_EXCL, 0644);
242 _SE("Failed to open (%s)\n", dst);
246 res = copy_bytes(dfd, sfd, NULL);
253 int move_file(char *dst, char *src)
255 if (copy_file(dst, src) < 0)
262 int dump_file_write_fd(int dfd, char *src)
268 _E("Invalid argument\n");
271 sfd = open(src, O_RDONLY);
273 _SE("Failed to open (%s)\n", src);
277 res = copy_bytes(dfd, sfd, NULL);
283 static int run_command(char *path, char *args[], char *env[], int fd[])
285 if (dup2(fd[1], STDOUT_FILENO) == -1) {
286 _E("dup2 error: %m");
290 if (close(fd[1]) == -1) {
291 _E("close fd error: %m");
295 if (close(fd[0]) == -1) {
296 _E("close fd error: %m");
300 if (execvpe(path, args, env) == -1) {
301 _E("run command %s error: %m", path);
307 static int wait_for_child(pid_t pid, int *exit_code, int timeout)
309 for (int i = 0; i < 10*timeout; i++) {
311 pid_t p = waitpid(pid, &status, WNOHANG);
313 if (WIFSIGNALED(status)) {
314 _I("Killed by signal %d\n", WTERMSIG(status));
316 } else if (WIFEXITED(status)) {
317 *exit_code = WEXITSTATUS(status);
320 } else if (p == -1) {
321 _E("waitpid error: %m");
329 static int read_into_buff(int fd, char *buff, int size, int timeout_us, int *eof)
338 tout.tv_sec = timeout_us / 1000000;
339 tout.tv_usec = timeout_us % 1000000;
343 if ((sel_ret = select(fd+1, &set, NULL, NULL, &tout)) >= 0) {
345 // we can do nonblocking read
346 int readed = read(fd, &buff[buff_pos], size);
351 } else if (readed == 0) {
352 // no more data to read
356 _E("read data from the pipe error: %m");
361 _E("select() error: %m");
366 // if buff is not NULL then 'size' bytes of the result is written the buffer,
367 // otherwise result is written to the dfd descriptor
368 int run_command_write_fd_timeout(char *path, char *args[], char *env[], int dfd, char *buff, int size, int timeout)
370 char BUFF[READ_BUFF_SIZE];
372 struct timeval start, end;
373 int write_to_fd = buff == NULL ? 1 : 0;
375 if (!write_to_fd && size <= 0) {
376 _E("buffer size must be greather than zero");
381 _E("pipe create error: %m");
388 return run_command(path, args, env, fd);
389 } else if (pid > 0) {
390 if (close(fd[1]) == -1) {
391 _E("close fd error: %m");
395 if (gettimeofday(&start, NULL) == -1) {
396 _E("gettimeofday error: %m");
409 act_size = READ_BUFF_SIZE;
416 while ((readed = read_into_buff(fd[0], act_buff, act_size, 1000000, &eof)) >= 0) {
419 if (count < (INT_MAX - readed))
425 if (write_fd(dfd, act_buff, readed) == -1) {
426 _E("write data to pipe error: %m");
434 // buff is full, we can return
443 if (gettimeofday(&end, NULL) == -1) {
444 _E("gettimeofday error: %m");
448 if ((end.tv_sec - start.tv_sec) > timeout) {
458 _E("command timeout: %s", path);
459 if (kill(pid, 0) == 0) {
460 // we can kill a child because we don't
462 if (kill(pid, SIGTERM) == -1)
463 _E("kill child %d error: %m", pid);
467 if (close(fd[0]) == -1) {
468 _E("close fd error: %m");
472 // let's wait a second for a child
474 int wait_res = wait_for_child(pid, &exit_code, 1);
477 _I("wait_for_child for \%s\" returns non-zero value\n", path);
478 else if (exit_code != 0)
479 _I("\"%s\" exit code: %d\n", path, exit_code);
481 return (eof == 1 && exit_code == 0) ? count : -abs(exit_code);
483 _E("fork() error: %m");
490 int run_command_timeout(char *path, char *args[], char *env[], int timeout)
492 int fd = open("/dev/null", O_WRONLY);
494 _E("open /dev/null error: %m");
498 int res = run_command_write_fd_timeout(path, args, env, fd, NULL, 0, timeout);
505 int fsync_path(char *const path)
509 ret = fd = open(path, O_RDONLY);
516 _E("Unable to fsync %s: %m", path);
521 static int remove_dir_internal(int fd)
531 while ((de = readdir(dir))) {
532 if (de->d_type == DT_DIR) {
533 if (!strncmp(de->d_name, ".", 2) || !strncmp(de->d_name, "..", 3))
535 subfd = openat(fd, de->d_name, O_RDONLY | O_DIRECTORY);
537 _SE("Couldn't openat %s: %d\n", de->d_name, errno);
541 if (remove_dir_internal(subfd))
544 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
545 _SE("Couldn't unlinkat %s: %d\n", de->d_name, errno);
549 if (unlinkat(fd, de->d_name, 0) < 0) {
550 _SE("Couldn't unlinkat %s: %d\n", de->d_name, errno);
559 int remove_dir(const char *path, int del_dir)
565 fd = open(path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
567 _SE("Couldn't opendir %s: %d\n", path, errno);
570 ret = remove_dir_internal(fd);
575 _SE("Couldn't rmdir %s: %d\n", path, errno);
582 int get_exec_pid(const char *execpath)
585 struct dirent *dentry;
592 dp = opendir("/proc");
594 _E("FAIL: open /proc");
598 len = strlen(execpath) + 1;
600 while ((dentry = readdir(dp))) {
601 if (!isdigit(dentry->d_name[0]))
604 pid = atoi(dentry->d_name);
606 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
607 fd = open(buf, O_RDONLY);
610 ret = read(fd, buf2, PATH_MAX);
613 if (ret < 0 || ret >= PATH_MAX)
618 if (!strncmp(buf2, execpath, len)) {
629 int get_file_count(char *path)
639 while ((dp = readdir(dir))) {
640 const char *name = dp->d_name;
641 /* always skip "." and ".." */
642 if (name[0] == '.') {
645 if ((name[1] == '.') && (name[2] == 0))
654 int get_directory_usage(char *path)
662 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
671 while ((de = readdir(dir))) {
672 if (!strncmp(de->d_name, ".", 2) || !strncmp(de->d_name, "..", 3))
674 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
675 _SE("Failed to fstatat %s: %d\n", de->d_name, errno);
685 int log_kmsg(char *fmt, ...)
691 file = fopen("/dev/kmsg", "w");
693 _E("Open /dev/kmsg error: %m");
698 if (vfprintf(file, fmt, ap) < 0) {
699 _E("Write to /dev/kmsg error: %m");
708 * @brief Check wchan of thread
710 * @param pid PID of the inspected process
711 * @param tid TID of the thread to check
713 static int check_thread_wchan(int pid, int tid)
716 char path[PATH_MAX], buf[100];
718 snprintf(path, sizeof(path), "/proc/%d/task/%d/wchan", pid, tid);
719 fd = open(path, O_RDONLY);
721 _E("cannot open %s: %m\n", path);
724 cnt = read(fd, buf, sizeof(buf));
725 if (cnt == -1 || cnt == sizeof(buf)) {
726 _E("read %s error: %m\n", path);
733 if (strncmp("do_coredump", buf, sizeof(buf)) == 0 || strncmp("pipe_wait", buf, sizeof(buf)) == 0)
740 * @brief Find crashed tid if tid was not offered
742 * @param pid PID of the inspected process
744 int find_crash_tid(int pid)
749 struct dirent *entry;
750 char task_path[PATH_MAX];
753 snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
754 if (stat(task_path, &sb) == -1) {
755 _E("no such file: %s", task_path);
759 threadnum = sb.st_nlink - 2;
762 dir = opendir(task_path);
764 _E("cannot open %s\n", task_path);
767 while ((entry = readdir(dir)) != NULL) {
768 if (strcmp(entry->d_name, ".") == 0 ||
769 strcmp(entry->d_name, "..") == 0)
771 crash_tid = check_thread_wchan(pid,
772 atoi(entry->d_name));
779 } else if (threadnum == 1) {
785 char* get_cmd_line(pid_t pid)
787 char cmdline_path[PATH_MAX];
789 snprintf(cmdline_path, sizeof(cmdline_path),
790 "/proc/%d/cmdline", pid);
792 int fd = open(cmdline_path, O_RDONLY);
794 _E("Failed to open %s: %m\n", cmdline_path);
798 char buffer[PATH_MAX];
799 ssize_t ret = read(fd, buffer, sizeof(buffer) - 1);
803 _E("Failed to read %s: %m\n", cmdline_path);
809 if (asprintf(&result, "%s", buffer) == -1) {
810 _E("asprintf() error: %m\n");
817 char* get_exe_path(pid_t pid)
819 char exe_link[PATH_MAX];
820 char buffer[PATH_MAX];
822 snprintf(exe_link, sizeof(exe_link),
823 "/proc/%d/exe", pid);
825 ssize_t ret = readlink(exe_link, buffer, sizeof(buffer) - 1);
828 _E("Failed to read link %s: %m", exe_link);
833 if (access(buffer, F_OK) == -1) {
834 _E("Invalid path %s", buffer);
839 if (asprintf(&result, "%s", buffer) == -1) {
840 _E("asprintf() error: %m\n");
847 /* This function is supposed to accept same data as passed to execve
848 * (argv and envp), which can be arrays of strings as well as NULL
851 char* concatenate(char *const vec[])
854 for (char *const *p = vec; p && *p; p++)
855 length += strlen(*p) + 1;
860 char *str = (char *)malloc(length);
865 char *const *vecp = vec;
867 destp = stpcpy(destp, *(vecp++));
869 destp = stpcpy(destp, " ");