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