util: Remove unused cat_file()
[platform/core/system/crash-worker.git] / src / shared / util.c
1 /*
2  * crash-manager
3  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 #ifndef _GNU_SOURCE
18 #define _GNU_SOURCE
19 #endif
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <sys/sendfile.h>
26 #include <dirent.h>
27 #include <fcntl.h>
28 #include <stdarg.h>
29 #include <unistd.h>
30 #include <limits.h>
31 #include <string.h>
32 #include <signal.h>
33 #include <time.h>
34 #include <errno.h>
35 #include <wait.h>
36 #include <ctype.h>
37 #include <grp.h>
38
39 #include "util.h"
40 #include "log.h"
41
42 #define READ_BUFF_SIZE 4096
43 #define SELECT_TIMEOUT_US 100000
44
45 int system_command_parallel(char *command)
46 {
47         int pid = 0;
48         const char *environ[] = { NULL };
49
50         if (command == NULL)
51                 return -1;
52         pid = fork();
53         if (pid == -1)
54                 return -1;
55         if (pid == 0) {
56                 char *argv[4];
57                 argv[0] = "sh";
58                 argv[1] = "-c";
59                 argv[2] = (char *)command;
60                 argv[3] = 0;
61                 execve("/bin/sh", argv, (char **)environ);
62                 exit(127);
63         }
64
65         return pid;
66 }
67
68 int wait_system_command(int pid)
69 {
70         int status = 0;
71
72         if (pid < 0)
73                 return -1;
74
75         do {
76                 if (waitpid(pid, &status, 0) == -1) {
77                         if (errno != EINTR)
78                                 return -1;
79                 } else {
80                         if (WIFEXITED(status))
81                                 return WEXITSTATUS(status);
82                         else if (WIFSIGNALED(status))
83                                 return WTERMSIG(status);
84                         else if (WIFSTOPPED(status))
85                                 return WSTOPSIG(status);
86                 }
87         } while (!WIFEXITED(status) && !WIFSIGNALED(status));
88
89         return 0;
90 }
91
92 int system_command(char *command)
93 {
94         int pid = 0;
95
96         pid = system_command_parallel(command);
97
98         return wait_system_command(pid);
99 }
100
101 int system_command_with_timeout(int timeout_seconds, char *command)
102 {
103         const char *environ[] = { NULL };
104
105         if (command == NULL)
106                 return -1;
107         clock_t start = clock();
108         pid_t pid = fork();
109         /* handle error case */
110         if (pid < 0) {
111                 _E("fork: %d\n", errno);
112                 return pid;
113         }
114         /* handle child case */
115         if (pid == 0) {
116                 char *argv[4];
117                 argv[0] = "sh";
118                 argv[1] = "-c";
119                 argv[2] = (char *)command;
120                 argv[3] = 0;
121
122                 execve("/bin/sh", argv, (char **)environ);
123                 _SI("exec(%s): %d\n", command, errno);
124                 _exit(-1);
125         }
126         /* handle parent case */
127         for (;;) {
128                 int status;
129                 pid_t p = waitpid(pid, &status, WNOHANG);
130                 float elapsed = (float) (clock() - start) / CLOCKS_PER_SEC;
131                 if (p == pid) {
132                         if (WIFSIGNALED(status))
133                                 _SI("%s: Killed by signal %d\n", command, WTERMSIG(status));
134                         else if (WIFEXITED(status) && WEXITSTATUS(status) > 0)
135                                 _SI("%s: Exit code %d\n", command, WEXITSTATUS(status));
136                         return WEXITSTATUS(status);
137                 }
138                 if (timeout_seconds && elapsed > timeout_seconds) {
139                         _SI("%s: Timed out after %.1fs (killing pid %d)\n",
140                                         command, elapsed, pid);
141                         kill(pid, SIGTERM);
142                         return -1;
143                 }
144                 /* poll every 0.1 sec */
145                 usleep(100000);
146         }
147 }
148
149 int file_exist(const char *file)
150 {
151         FILE *fp;
152
153         fp = fopen(file, "r");
154         if (fp == NULL)
155                 return -1;
156         fclose(fp);
157         return 1;
158 }
159
160 int write_fd(int fd, const void *buf, int len)
161 {
162         int count;
163         int total;
164         total = 0;
165         while (len) {
166                 count = write(fd, buf, len);
167                 if (count < 0) {
168                         if (errno == EINTR)
169                                 continue;
170                         if (total)
171                                 return total;
172                         return count;
173                 }
174                 total += count;
175                 buf = ((const char *)buf) + count;
176                 len -= count;
177         }
178         return total;
179 }
180
181 static int copy_bytes(int dfd, int sfd)
182 {
183         int res = 1;
184         ssize_t bytes_sent;
185         do
186                 bytes_sent = sendfile(dfd, sfd, NULL, PIPE_BUF);
187         while (bytes_sent > 0);
188
189         if (bytes_sent == -1) {
190                 _E("sendfile() error: %m\n");
191                 res = -1;
192         }
193         return res;
194 }
195
196 int copy_file(char *src, char *dst)
197 {
198         int res;
199         int sfd;
200         int dfd;
201
202         if (!src || !dst) {
203                 _E("Invalid argument\n");
204                 return -1;
205         }
206         sfd = open(src, O_RDONLY);
207         if (sfd < 0) {
208                 _E("Failed to open (%s)\n", src);
209                 return -1;
210         }
211         dfd = open(dst, O_WRONLY|O_CREAT|O_EXCL, 0644);
212         if (dfd < 0) {
213                 close(sfd);
214                 _SE("Failed to open (%s)\n", dst);
215                 return -1;
216         }
217
218         res = copy_bytes(dfd, sfd);
219
220         close(sfd);
221         close(dfd);
222         return res;
223 }
224
225 int move_file(char *src, char *dst)
226 {
227         if (copy_file(src, dst) < 0)
228                 return -1;
229         if (unlink(src) < 0)
230                 return -1;
231         return 1;
232 }
233
234 int dump_file_write_fd(char *src, int dfd)
235 {
236         int res;
237         int sfd;
238
239         if (!src) {
240                 _E("Invalid argument\n");
241                 return -1;
242         }
243         sfd = open(src, O_RDONLY);
244         if (sfd < 0) {
245                 _SE("Failed to open (%s)\n", src);
246                 return -1;
247         }
248
249         res = copy_bytes(dfd, sfd);
250
251         close(sfd);
252         return res;
253 }
254
255 static int run_command(char *path, char *args[], char *env[], int fd[])
256 {
257         if (dup2(fd[1], STDOUT_FILENO) == -1) {
258                 _E("dup2 error: %m");
259                 return -1;
260         }
261
262         if (close(fd[1]) == -1) {
263                 _E("close fd error: %m");
264                 return -1;
265         }
266
267         if (close(fd[0]) == -1) {
268                 _E("close fd error: %m");
269                 return -1;
270         }
271
272         if (execvpe(path, args, env) == -1) {
273                 _E("run command %s error: %m", path);
274                 return -1;
275         }
276         return -1;
277 }
278
279 static int wait_for_child(pid_t pid, int *exit_code, int timeout)
280 {
281         for (int i = 0; i < 10*timeout; i++) {
282                 int status;
283                 pid_t p = waitpid(pid, &status, WNOHANG);
284                 if (p == pid) {
285                         if (WIFSIGNALED(status)) {
286                                 _I("Killed by signal %d\n", WTERMSIG(status));
287                                 return -1;
288                         } else if (WIFEXITED(status)) {
289                                 *exit_code = WEXITSTATUS(status);
290                                 return 0;
291                         }
292                 } else if (p == -1) {
293                         _E("waitpid error: %m");
294                         return -1;
295                 }
296                 usleep(100000);
297         }
298         return -1;
299 }
300
301 static int read_into_buff(int fd, char *buff, int size, int timeout_us, int *eof)
302 {
303         struct timeval tout;
304         int sel_ret;
305         fd_set set;
306
307         FD_ZERO(&set);
308         FD_SET(fd, &set);
309
310         tout.tv_sec = timeout_us / 1000000;
311         tout.tv_usec = timeout_us % 1000000;
312         *eof = 0;
313
314         int buff_pos = 0;
315         if ((sel_ret = select(fd+1, &set, NULL, NULL, &tout)) >= 0) {
316                 if (sel_ret > 0) {
317                         // we can do nonblocking read
318                         int readed = read(fd, &buff[buff_pos], size);
319
320                         if (readed > 0) {
321                                 buff_pos += readed;
322                                 size -= readed;
323                         } else if (readed == 0) {
324                                 // no more data to read
325                                 *eof = 1;
326                         } else {
327                                 // error
328                                 _E("read data from the pipe error: %m");
329                                 return -1;
330                         }
331                 }
332         } else
333                 _E("select() error: %m");
334         return buff_pos;
335 }
336
337 // Usage:
338 // if buff is not NULL then 'size' bytes of the result is written the buffer,
339 // otherwise result is written to the dfd descriptor
340 int run_command_write_fd_timeout(char *path, char *args[], char *env[], int dfd, char *buff, int size, int timeout)
341 {
342         char BUFF[READ_BUFF_SIZE];
343         int fd[2];
344         struct timeval start, end;
345         int write_to_fd = buff == NULL ? 1 : 0;
346
347         if (!write_to_fd && size <= 0) {
348                 _E("buffer size must be greather than zero");
349                 return -1;
350         }
351
352         if (pipe(fd)) {
353                 _E("pipe create error: %m");
354                 return -1;
355         }
356
357         pid_t pid = fork();
358
359         if (pid == 0) {
360                 return run_command(path, args, env, fd);
361         } else if (pid > 0) {
362                 if (close(fd[1]) == -1) {
363                         _E("close fd error: %m");
364                         return -1;
365                 }
366
367                 if (gettimeofday(&start, NULL) == -1) {
368                         _E("gettimeofday error: %m");
369                         return -1;
370                 }
371
372                 int readed;
373                 int eof = 0;
374                 int outdated = 0;
375                 int count = 0;
376
377                 int act_size;
378                 char *act_buff;
379
380                 if (write_to_fd) {
381                         act_size = READ_BUFF_SIZE;
382                         act_buff = BUFF;
383                 } else {
384                         act_size = size;
385                         act_buff = buff;
386                 }
387
388                 while ((readed = read_into_buff(fd[0], act_buff, act_size, 1000000, &eof)) >= 0) {
389                         if (readed > 0) {
390                                 // we have some data
391                                 if (count < (INT_MAX - readed))
392                                         count += readed;
393                                 else
394                                         count = INT_MAX;
395
396                                 if (write_to_fd) {
397                                         if (write_fd(dfd, act_buff, readed) == -1) {
398                                                 _E("write data to pipe error: %m");
399                                                 break;
400                                         }
401                                 } else {
402                                         act_buff += readed;
403                                         act_size -= readed;
404
405                                         if (act_size == 0) {
406                                                 // buff is full, we can return
407                                                 eof = 1;
408                                         }
409                                 }
410                         }
411
412                         if (eof)
413                                 break;
414
415                         if (gettimeofday(&end, NULL) == -1) {
416                                 _E("gettimeofday error: %m");
417                                 break;
418                         }
419
420                         if ((end.tv_sec - start.tv_sec) > timeout) {
421                                 outdated = 1;
422                                 break;
423                         }
424
425                         if (readed == 0)
426                                 usleep(100000);
427                 }
428
429                 if (outdated) {
430                         _E("command timeout: %s", path);
431                         if (kill(pid, 0) == 0) {
432                                 // we can kill a child because we don't
433                                 // need it anymore
434                                 if (kill(pid, SIGTERM) == -1)
435                                         _E("kill child %d error: %m", pid);
436                         }
437                 }
438
439                 if (close(fd[0]) == -1) {
440                         _E("close fd error: %m");
441                         return -1;
442                 }
443
444                 // let's wait a second for a child
445                 int exit_code = -1;
446                 int wait_res = wait_for_child(pid, &exit_code, 1);
447
448                 if (wait_res != 0)
449                         _I("wait_for_child for \%s\" returns non-zero value\n", path);
450                 else if (exit_code != 0)
451                         _I("\"%s\" exit code: %d\n", path, exit_code);
452
453                 return (eof == 1 && exit_code == 0) ? count : -abs(exit_code);
454         } else {
455                 _E("fork() error: %m");
456                 return -1;
457         }
458
459         return -1;
460 }
461
462 int run_command_timeout(char *path, char *args[], char *env[], int timeout)
463 {
464         int fd = open("/dev/null", O_WRONLY);
465         if (fd < 0) {
466                 _E("open /dev/null error: %m");
467                 return -1;
468         }
469
470         int res = run_command_write_fd_timeout(path, args, env, fd, NULL, 0, timeout);
471
472         close(fd);
473
474         return res;
475 }
476
477 static int remove_dir_internal(int fd)
478 {
479         DIR *dir;
480         struct dirent *de;
481         int subfd, ret = 0;
482
483         dir = fdopendir(fd);
484         if (!dir)
485                 return -1;
486
487         while ((de = readdir(dir))) {
488                 if (de->d_type == DT_DIR) {
489                         if (!strncmp(de->d_name, ".", 2) || !strncmp(de->d_name, "..", 3))
490                                 continue;
491                         subfd = openat(fd, de->d_name, O_RDONLY | O_DIRECTORY);
492                         if (subfd < 0) {
493                                 _SE("Couldn't openat %s: %d\n", de->d_name, errno);
494                                 ret = -1;
495                                 continue;
496                         }
497                         if (remove_dir_internal(subfd))
498                                 ret = -1;
499                         close(subfd);
500                         if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
501                                 _SE("Couldn't unlinkat %s: %d\n", de->d_name, errno);
502                                 ret = -1;
503                         }
504                 } else {
505                         if (unlinkat(fd, de->d_name, 0) < 0) {
506                                 _SE("Couldn't unlinkat %s: %d\n", de->d_name, errno);
507                                 ret = -1;
508                         }
509                 }
510         }
511         closedir(dir);
512         return ret;
513 }
514
515 int remove_dir(const char *path, int del_dir)
516 {
517         int fd, ret = 0;
518
519         if (!path)
520                 return -1;
521         fd = open(path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
522         if (fd < 0) {
523                 _SE("Couldn't opendir %s: %d\n", path, errno);
524                 return -errno;
525         }
526         ret = remove_dir_internal(fd);
527         close(fd);
528
529         if (del_dir) {
530                 if (rmdir(path)) {
531                         _SE("Couldn't rmdir %s: %d\n", path, errno);
532                         ret = -1;
533                 }
534         }
535         return ret;
536 }
537
538 int get_exec_pid(const char *execpath)
539 {
540         DIR *dp;
541         struct dirent *dentry;
542         int pid = -1, fd;
543         int ret;
544         char buf[PATH_MAX];
545         char buf2[PATH_MAX];
546         int len;
547
548         dp = opendir("/proc");
549         if (!dp) {
550                 _E("FAIL: open /proc");
551                 return -1;
552         }
553
554         len = strlen(execpath) + 1;
555
556         while ((dentry = readdir(dp))) {
557                 if (!isdigit(dentry->d_name[0]))
558                         continue;
559
560                 pid = atoi(dentry->d_name);
561
562                 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
563                 fd = open(buf, O_RDONLY);
564                 if (fd < 0)
565                         continue;
566                 ret = read(fd, buf2, PATH_MAX);
567                 close(fd);
568
569                 if (ret < 0 || ret >= PATH_MAX)
570                         continue;
571
572                 buf2[ret] = '\0';
573
574                 if (!strncmp(buf2, execpath, len)) {
575                         closedir(dp);
576                         return pid;
577                 }
578         }
579
580         errno = ESRCH;
581         closedir(dp);
582         return -1;
583 }
584
585 int get_file_count(char *path)
586 {
587         DIR *dir;
588         struct dirent *dp;
589         int count = 0;
590
591         dir = opendir(path);
592         if (!dir)
593                 return 0;
594
595         while ((dp = readdir(dir))) {
596                 const char *name = dp->d_name;
597                 /* always skip "." and ".." */
598                 if (name[0] == '.') {
599                         if (name[1] == 0)
600                                 continue;
601                         if ((name[1] == '.') && (name[2] == 0))
602                                 continue;
603                 }
604                 count++;
605         }
606         closedir(dir);
607         return count;
608 }
609
610 int get_directory_usage(char *path)
611 {
612         DIR *dir;
613         struct dirent *de;
614         struct stat st;
615         size_t usage = 0;
616         int fd = -1;
617
618         fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
619         if (fd < 0)
620                 return -1;
621         dir = fdopendir(fd);
622         if (!dir) {
623                 close(fd);
624                 return -1;
625         }
626
627         while ((de = readdir(dir))) {
628                 if (!strncmp(de->d_name, ".", 2) || !strncmp(de->d_name, "..", 3))
629                         continue;
630                 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
631                         _SE("Failed to fstatat  %s: %d\n", de->d_name, errno);
632                         continue;
633                 }
634                 usage += st.st_size;
635         }
636         closedir(dir);
637         close(fd);
638         return usage;
639 }
640
641 int log_kmsg(char *fmt, ...)
642 {
643         int result = 1;
644         va_list ap;
645         FILE *file;
646
647         file = fopen("/dev/kmsg", "w");
648         if (file == NULL) {
649                 _E("Open /dev/kmsg error: %m");
650                 return 0;
651         }
652
653         va_start(ap, fmt);
654         if (vfprintf(file, fmt, ap) < 0) {
655                 _E("Write to /dev/kmsg error: %m");
656                 result = 0;
657         }
658         va_end(ap);
659         fclose(file);
660         return result;
661 }
662
663 /**
664  * @brief Check wchan of thread
665  *
666  * @param pid PID of the inspected process
667  * @param tid TID of the thread to check
668  */
669 static int check_thread_wchan(int pid, int tid)
670 {
671         int fd, cnt;
672         char path[PATH_MAX], buf[100];
673
674         snprintf(path, sizeof(path), "/proc/%d/task/%d/wchan", pid, tid);
675         fd = open(path, O_RDONLY);
676         if (fd == -1) {
677                 _E("cannot open %s: %m\n", path);
678                 return -errno;
679         }
680         cnt = read(fd, buf, sizeof(buf));
681         if (cnt == -1 || cnt == sizeof(buf)) {
682                 _E("read %s error: %m\n", path);
683                 close(fd);
684                 return -errno;
685         }
686         buf[cnt] = 0;
687         close(fd);
688
689         if (strncmp("do_coredump", buf, sizeof(buf)) == 0 || strncmp("pipe_wait", buf, sizeof(buf)) == 0)
690                 return tid;
691         else
692                 return 0;
693 }
694
695 /**
696  * @brief Find crashed tid if tid was not offered
697  *
698  * @param pid PID of the inspected process
699  */
700 int find_crash_tid(int pid)
701 {
702         int threadnum = 1;
703         int crash_tid = -1;
704         DIR *dir;
705         struct dirent *entry;
706         char task_path[PATH_MAX];
707         struct stat sb;
708
709         snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
710         if (stat(task_path, &sb) == -1) {
711                 _E("no such file: %s", task_path);
712                 return -1;
713         }
714
715         threadnum = sb.st_nlink - 2;
716
717         if (threadnum > 1) {
718                 dir = opendir(task_path);
719                 if (!dir) {
720                         _E("cannot open %s\n", task_path);
721                         return -1;
722                 } else {
723                         while ((entry = readdir(dir)) != NULL) {
724                                 if (strcmp(entry->d_name, ".") == 0 ||
725                                     strcmp(entry->d_name, "..") == 0)
726                                         continue;
727                                 crash_tid = check_thread_wchan(pid,
728                                                                atoi(entry->d_name));
729                                 if (crash_tid > 0)
730                                         break;
731                         }
732                         closedir(dir);
733                         return crash_tid;
734                 }
735         } else if (threadnum == 1) {
736                 return pid;
737         }
738         return -1;
739 }
740
741 char* get_cmd_line(pid_t pid)
742 {
743         char cmdline_path[PATH_MAX];
744
745         snprintf(cmdline_path, sizeof(cmdline_path),
746                         "/proc/%d/cmdline", pid);
747
748         int fd = open(cmdline_path, O_RDONLY);
749         if (fd < 0) {
750                 _E("Failed to open %s: %m\n", cmdline_path);
751                 return NULL;
752         }
753
754         char buffer[PATH_MAX];
755         ssize_t ret = read(fd, buffer, sizeof(buffer) - 1);
756         buffer[ret] = '\0';
757         close(fd);
758
759
760         if (ret <= 0) {
761                 _E("Failed to read %s: %m\n", cmdline_path);
762                 return NULL;
763         }
764
765         char *result;
766         if (asprintf(&result, "%s", buffer) == -1) {
767                 _E("asprintf() error: %m\n");
768                 return NULL;
769         }
770
771         return result;
772 }
773
774 char* get_exe_path(pid_t pid)
775 {
776         char exe_link[PATH_MAX];
777         char buffer[PATH_MAX];
778
779         snprintf(exe_link, sizeof(exe_link),
780                 "/proc/%d/exe", pid);
781
782         ssize_t ret = readlink(exe_link, buffer, sizeof(buffer) - 1);
783         buffer[ret] = '\0';
784
785         if (ret <= 0) {
786                 _E("Failed to read link %s: %m", exe_link);
787                 return NULL;
788         }
789
790         if (access(buffer, F_OK) == -1) {
791                 _E("Invalid path %s", buffer);
792                 return NULL;
793         }
794
795         char *result;
796         if (asprintf(&result, "%s", buffer) == -1) {
797                 _E("asprintf() error: %m\n");
798                 return NULL;
799         }
800
801         return result;
802 }
803 /**
804  * @}
805  */