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