Log file cleanups
[petitboot] / lib / system / system.c
1
2 #if defined(HAVE_CONFIG_H)
3 #include "config.h"
4 #endif
5
6 #include <assert.h>
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14
15 #include "log/log.h"
16 #include <talloc/talloc.h>
17 #include "system.h"
18
19 const struct pb_system_apps pb_system_apps = {
20         .cp = "/bin/cp",
21         .kexec = "/sbin/kexec",
22         .mount = "/bin/mount",
23         .shutdown = "/sbin/shutdown",
24         .sftp = "/usr/bin/sftp",
25         .tftp = "/usr/bin/tftp",
26         .umount = "/bin/umount",
27         .wget = "/usr/bin/wget",
28 };
29
30 int pb_mkdir_recursive(const char *dir)
31 {
32         struct stat statbuf;
33         char *str, *sep;
34         int mode = 0755;
35
36         if (!*dir)
37                 return 0;
38
39         if (!stat(dir, &statbuf)) {
40                 if (!S_ISDIR(statbuf.st_mode)) {
41                         pb_log("%s: %s exists, but isn't a directory\n",
42                                         __func__, dir);
43                         return -1;
44                 }
45                 return 0;
46         }
47
48         str = talloc_strdup(NULL, dir);
49         sep = strchr(*str == '/' ? str + 1 : str, '/');
50
51         while (1) {
52
53                 /* terminate the path at sep */
54                 if (sep)
55                         *sep = '\0';
56
57                 if (mkdir(str, mode) && errno != EEXIST) {
58                         pb_log("mkdir(%s): %s\n", str, strerror(errno));
59                         return -1;
60                 }
61
62                 if (!sep)
63                         break;
64
65                 /* reset dir to the full path */
66                 strcpy(str, dir);
67                 sep = strchr(sep + 1, '/');
68         }
69
70         talloc_free(str);
71
72         return 0;
73 }
74
75 int pb_rmdir_recursive(const char *base, const char *dir)
76 {
77         char *cur, *pos;
78
79         /* sanity check: make sure that dir is within base */
80         if (strncmp(base, dir, strlen(base)))
81                 return -1;
82
83         cur = talloc_strdup(NULL, dir);
84
85         while (strcmp(base, dir)) {
86
87                 rmdir(dir);
88
89                 /* null-terminate at the last slash */
90                 pos = strrchr(dir, '/');
91                 if (!pos)
92                         break;
93
94                 *pos = '\0';
95         }
96
97         talloc_free(cur);
98
99         return 0;
100 }
101
102 /**
103  * pb_run_cmd - Run the supplied command.
104  * @cmd_argv: An argument list array for execv.
105  */
106
107 int pb_run_cmd(const char *const *cmd_argv)
108 {
109 #if defined(DEBUG)
110         enum {do_debug = 1};
111 #else
112         enum {do_debug = 0};
113 #endif
114         int status;
115         pid_t pid;
116
117         if (do_debug) {
118                 const char *const *p = cmd_argv;
119
120                 pb_log("%s: ", __func__);
121                 while (*p) {
122                         pb_log("%s ", *p);
123                         p++;
124                 }
125                 pb_log("\n");
126         } else
127                 pb_log("%s: %s\n", __func__, cmd_argv[0]);
128
129         pid = fork();
130
131         if (pid == -1) {
132                 pb_log("%s: fork failed: %s\n", __func__, strerror(errno));
133                 return -1;
134         }
135
136         if (pid == 0) {
137                 int log = fileno(pb_log_get_stream());
138
139                 /* Redirect child output to log. */
140
141                 status = dup2(log, STDOUT_FILENO);
142                 assert(status != -1);
143
144                 status = dup2(log, STDERR_FILENO);
145                 assert(status != -1);
146
147                 execvp(cmd_argv[0], (char *const *)cmd_argv);
148                 pb_log("%s: exec failed: %s\n", __func__, strerror(errno));
149                 exit(EXIT_FAILURE);
150         }
151
152         if (waitpid(pid, &status, 0) == -1) {
153                 pb_log("%s: waitpid failed: %s\n", __func__,
154                                 strerror(errno));
155                 return -1;
156         }
157
158         if (do_debug && WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
159                 pb_log("%s: signaled\n", __func__);
160
161         if (!WIFEXITED(status)) {
162                 pb_log("%s: %s failed\n", __func__, cmd_argv[0]);
163                 return -1;
164         }
165
166         if (WEXITSTATUS(status))
167                 pb_log("%s: WEXITSTATUS %d\n", __func__, WEXITSTATUS(status));
168
169         return WEXITSTATUS(status);
170 }