]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/remount-fs/remount-fs.c
core: when determining whether a process exit status is clean, consider whether it...
[thirdparty/systemd.git] / src / remount-fs / remount-fs.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <mntent.h>
22 #include <string.h>
23 #include <sys/prctl.h>
24 #include <sys/stat.h>
25 #include <sys/wait.h>
26 #include <unistd.h>
27
28 #include "exit-status.h"
29 #include "log.h"
30 #include "mount-setup.h"
31 #include "mount-util.h"
32 #include "path-util.h"
33 #include "process-util.h"
34 #include "signal-util.h"
35 #include "strv.h"
36 #include "util.h"
37
38 /* Goes through /etc/fstab and remounts all API file systems, applying
39 * options that are in /etc/fstab that systemd might not have
40 * respected */
41
42 int main(int argc, char *argv[]) {
43 _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
44 _cleanup_endmntent_ FILE *f = NULL;
45 struct mntent* me;
46 int r;
47
48 if (argc > 1) {
49 log_error("This program takes no argument.");
50 return EXIT_FAILURE;
51 }
52
53 log_set_target(LOG_TARGET_AUTO);
54 log_parse_environment();
55 log_open();
56
57 umask(0022);
58
59 f = setmntent("/etc/fstab", "r");
60 if (!f) {
61 if (errno == ENOENT) {
62 r = 0;
63 goto finish;
64 }
65
66 r = log_error_errno(errno, "Failed to open /etc/fstab: %m");
67 goto finish;
68 }
69
70 pids = hashmap_new(NULL);
71 if (!pids) {
72 r = log_oom();
73 goto finish;
74 }
75
76 while ((me = getmntent(f))) {
77 pid_t pid;
78 int k;
79 char *s;
80
81 /* Remount the root fs, /usr and all API VFS */
82 if (!mount_point_is_api(me->mnt_dir) &&
83 !path_equal(me->mnt_dir, "/") &&
84 !path_equal(me->mnt_dir, "/usr"))
85 continue;
86
87 log_debug("Remounting %s", me->mnt_dir);
88
89 pid = fork();
90 if (pid < 0) {
91 r = log_error_errno(errno, "Failed to fork: %m");
92 goto finish;
93 }
94
95 if (pid == 0) {
96 /* Child */
97
98 (void) reset_all_signal_handlers();
99 (void) reset_signal_mask();
100 (void) prctl(PR_SET_PDEATHSIG, SIGTERM);
101
102 execv(MOUNT_PATH, STRV_MAKE(MOUNT_PATH, me->mnt_dir, "-o", "remount"));
103
104 log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m");
105 _exit(EXIT_FAILURE);
106 }
107
108 /* Parent */
109
110 s = strdup(me->mnt_dir);
111 if (!s) {
112 r = log_oom();
113 goto finish;
114 }
115
116 k = hashmap_put(pids, PID_TO_PTR(pid), s);
117 if (k < 0) {
118 free(s);
119 r = log_oom();
120 goto finish;
121 }
122 }
123
124 r = 0;
125 while (!hashmap_isempty(pids)) {
126 siginfo_t si = {};
127 char *s;
128
129 if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
130
131 if (errno == EINTR)
132 continue;
133
134 r = log_error_errno(errno, "waitid() failed: %m");
135 goto finish;
136 }
137
138 s = hashmap_remove(pids, PID_TO_PTR(si.si_pid));
139 if (s) {
140 if (!is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) {
141 if (si.si_code == CLD_EXITED)
142 log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status);
143 else
144 log_error(MOUNT_PATH " for %s terminated by signal %s.", s, signal_to_string(si.si_status));
145
146 r = -ENOEXEC;
147 }
148
149 free(s);
150 }
151 }
152
153 finish:
154 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
155 }