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.
21 #include <sys/types.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 /* WARNING : formatted string buffer is limited to 1024 byte */
148 int fprintf_fd(int fd, const char *fmt, ...)
156 n = vsnprintf(buff, 1024 - 1, fmt, args);
157 ret = write(fd, buff, n);
162 int file_exist(const char *file)
166 fp = fopen(file, "r");
173 int write_fd(int fd, const void *buf, int len)
179 count = write(fd, buf, len);
186 buf = ((const char *)buf) + count;
192 int copy_file(char *src, char *dst)
199 _E("Invalid argument\n");
202 sfd = open(src, O_RDONLY);
204 _E("Failed to open (%s)\n", src);
207 dfd = open(dst, O_WRONLY|O_CREAT|O_EXCL, 0644);
210 _SE("Failed to open (%s)\n", dst);
214 int ret = read(sfd, buf, sizeof(buf));
216 ret = write_fd(dfd, buf, ret);
225 int cat_file(char *src, char *dst)
232 _E("Invalid argument\n");
235 sfd = open(src, O_RDONLY);
237 _SE("Failed to open (%s)\n", src);
240 dfd = open(dst, O_WRONLY|O_APPEND);
243 _SE("Failed to open (%s)\n", dst);
247 int ret = read(sfd, buf, sizeof(buf));
249 ret = write_fd(dfd, buf, ret);
258 int move_file(char *src, char *dst)
260 if (copy_file(src, dst) < 0)
267 int dump_file_write_fd(char *src, int dfd)
273 _E("Invalid argument\n");
276 sfd = open(src, O_RDONLY);
278 _SE("Failed to open (%s)\n", src);
282 int ret = read(sfd, buf, sizeof(buf));
284 ret = write_fd(dfd, buf, ret);
292 static int run_command(char *path, char *args[], char *env[], int fd[])
294 if (dup2(fd[1], STDOUT_FILENO) == -1) {
295 _E("dup2 error: %m");
299 if (close(fd[1]) == -1) {
300 _E("close fd error: %m");
304 if (close(fd[0]) == -1) {
305 _E("close fd error: %m");
309 if (execvpe(path, args, env) == -1) {
310 _E("run command %s error: %m", path);
316 static int wait_for_child(pid_t pid, int *exit_code, int timeout)
318 for (int i = 0; i < 10*timeout; i++) {
320 pid_t p = waitpid(pid, &status, WNOHANG);
322 if (WIFSIGNALED(status)) {
323 _I("Killed by signal %d\n", WTERMSIG(status));
325 } else if (WIFEXITED(status)) {
326 *exit_code = WEXITSTATUS(status);
329 } else if (p == -1) {
330 _E("waitpid error: %m");
338 static int read_into_buff(int fd, char *buff, int size, int timeout_us, int *eof)
347 tout.tv_sec = timeout_us / 1000000;
348 tout.tv_usec = timeout_us % 1000000;
352 if ((sel_ret = select(fd+1, &set, NULL, NULL, &tout)) >= 0) {
354 // we can do nonblocking read
355 int readed = read(fd, &buff[buff_pos], size);
360 } else if (readed == 0) {
361 // no more data to read
365 _E("read data from the pipe error: %m");
370 _E("select() error: %m");
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)
379 char BUFF[READ_BUFF_SIZE];
381 struct timeval start, end;
382 int write_to_fd = buff == NULL ? 1 : 0;
384 if (!write_to_fd && size <= 0) {
385 _E("buffer size must be greather than zero");
390 _E("pipe create error: %m");
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");
404 if (gettimeofday(&start, NULL) == -1) {
405 _E("gettimeofday error: %m");
418 act_size = READ_BUFF_SIZE;
425 while ((readed = read_into_buff(fd[0], act_buff, act_size, 1000000, &eof)) >= 0) {
428 if (count < (INT_MAX - readed))
434 if (write_fd(dfd, act_buff, readed) == -1) {
435 _E("write data to pipe error: %m");
443 // buff is full, we can return
452 if (gettimeofday(&end, NULL) == -1) {
453 _E("gettimeofday error: %m");
457 if ((end.tv_sec - start.tv_sec) > timeout) {
467 _E("command timeout: %s", path);
468 if (kill(pid, 0) == 0) {
469 // we can kill a child because we don't
471 if (kill(pid, SIGTERM) == -1)
472 _E("kill child %d error: %m", pid);
476 if (close(fd[0]) == -1) {
477 _E("close fd error: %m");
481 // let's wait a second for a child
483 if (wait_for_child(pid, &exit_code, 1) == 0 && exit_code != 0)
484 _I("\"%s\" exit code: %d\n", path, exit_code);
486 return (eof == 1 && exit_code == 0) ? count : -abs(exit_code);
488 _E("fork() error: %m");
495 int run_command_timeout(char *path, char *args[], char *env[], int timeout)
497 int fd = open("/dev/null", O_WRONLY);
499 _E("open /dev/null error: %m");
503 int res = run_command_write_fd_timeout(path, args, env, fd, NULL, 0, timeout);
510 static int remove_dir_internal(int fd)
520 while ((de = readdir(dir))) {
521 if (de->d_type == DT_DIR) {
522 if (!strncmp(de->d_name, ".", 2) || !strncmp(de->d_name, "..", 3))
524 subfd = openat(fd, de->d_name, O_RDONLY | O_DIRECTORY);
526 _SE("Couldn't openat %s: %d\n", de->d_name, errno);
530 if (remove_dir_internal(subfd))
533 if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
534 _SE("Couldn't unlinkat %s: %d\n", de->d_name, errno);
538 if (unlinkat(fd, de->d_name, 0) < 0) {
539 _SE("Couldn't unlinkat %s: %d\n", de->d_name, errno);
548 int remove_dir(const char *path, int del_dir)
554 fd = open(path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
556 _SE("Couldn't opendir %s: %d\n", path, errno);
559 ret = remove_dir_internal(fd);
564 _SE("Couldn't rmdir %s: %d\n", path, errno);
571 int get_exec_pid(const char *execpath)
574 struct dirent *dentry;
581 dp = opendir("/proc");
583 _E("FAIL: open /proc");
587 len = strlen(execpath) + 1;
589 while ((dentry = readdir(dp))) {
590 if (!isdigit(dentry->d_name[0]))
593 pid = atoi(dentry->d_name);
595 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
596 fd = open(buf, O_RDONLY);
599 ret = read(fd, buf2, PATH_MAX);
602 if (ret < 0 || ret >= PATH_MAX)
607 if (!strncmp(buf2, execpath, len)) {
618 int get_file_count(char *path)
628 while ((dp = readdir(dir))) {
629 const char *name = dp->d_name;
630 /* always skip "." and ".." */
631 if (name[0] == '.') {
634 if ((name[1] == '.') && (name[2] == 0))
643 int get_directory_usage(char *path)
651 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
660 while ((de = readdir(dir))) {
661 if (!strncmp(de->d_name, ".", 2) || !strncmp(de->d_name, "..", 3))
663 if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
664 _SE("Failed to fstatat %s: %d\n", de->d_name, errno);
675 int validate_env_name(char *name, int len)
685 if (name[0] >= '0' && name[0] <= '9')
688 for (p = name; p < name + len; p++)
689 if (!((*p >= 'A' && *p <= 'Z') ||
690 (*p >= '0' && *p <= '9') ||
696 int validate_file_name(char *name, int len)
706 if ((name[0] == '-') || (name[0] >= '0' && name[0] <= '9'))
709 for (p = name; p < name + len; p++)
710 if (!((*p >= 0x07 && *p <= 0x0C) ||
711 (*p >= 0x20 && *p <= 0x7E)))