chiark / gitweb /
build-sys: allow lto and FORTIFY_SOURCE with -O[sz]
[elogind.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 "mount-setup.h"
33 #include "exit-status.h"
34
35 /* Goes through /etc/fstab and remounts all API file systems, applying
36  * options that are in /etc/fstab that systemd might not have
37  * respected */
38
39 int main(int argc, char *argv[]) {
40         int ret = EXIT_FAILURE;
41         _cleanup_endmntent_ FILE *f = NULL;
42         struct mntent* me;
43         Hashmap *pids = NULL;
44
45         if (argc > 1) {
46                 log_error("This program takes no argument.");
47                 return EXIT_FAILURE;
48         }
49
50         log_set_target(LOG_TARGET_AUTO);
51         log_parse_environment();
52         log_open();
53
54         umask(0022);
55
56         f = setmntent("/etc/fstab", "r");
57         if (!f) {
58                 if (errno == ENOENT)
59                         return EXIT_SUCCESS;
60
61                 log_error_errno(errno, "Failed to open /etc/fstab: %m");
62                 return EXIT_FAILURE;
63         }
64
65         pids = hashmap_new(NULL);
66         if (!pids) {
67                 log_error("Failed to allocate set");
68                 goto finish;
69         }
70
71         ret = EXIT_SUCCESS;
72
73         while ((me = getmntent(f))) {
74                 pid_t pid;
75                 int k;
76                 char *s;
77
78                 /* Remount the root fs, /usr and all API VFS */
79                 if (!mount_point_is_api(me->mnt_dir) &&
80                     !path_equal(me->mnt_dir, "/") &&
81                     !path_equal(me->mnt_dir, "/usr"))
82                         continue;
83
84                 log_debug("Remounting %s", me->mnt_dir);
85
86                 pid = fork();
87                 if (pid < 0) {
88                         log_error_errno(errno, "Failed to fork: %m");
89                         ret = EXIT_FAILURE;
90                         continue;
91                 }
92
93                 if (pid == 0) {
94                         const char *arguments[5];
95                         /* Child */
96
97                         arguments[0] = "/bin/mount";
98                         arguments[1] = me->mnt_dir;
99                         arguments[2] = "-o";
100                         arguments[3] = "remount";
101                         arguments[4] = NULL;
102
103                         execv("/bin/mount", (char **) arguments);
104
105                         log_error_errno(errno, "Failed to execute /bin/mount: %m");
106                         _exit(EXIT_FAILURE);
107                 }
108
109                 /* Parent */
110
111                 s = strdup(me->mnt_dir);
112                 if (!s) {
113                         log_oom();
114                         ret = EXIT_FAILURE;
115                         continue;
116                 }
117
118
119                 k = hashmap_put(pids, UINT_TO_PTR(pid), s);
120                 if (k < 0) {
121                         log_error_errno(k, "Failed to add PID to set: %m");
122                         ret = EXIT_FAILURE;
123                         continue;
124                 }
125         }
126
127         while (!hashmap_isempty(pids)) {
128                 siginfo_t si = {};
129                 char *s;
130
131                 if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
132
133                         if (errno == EINTR)
134                                 continue;
135
136                         log_error_errno(errno, "waitid() failed: %m");
137                         ret = EXIT_FAILURE;
138                         break;
139                 }
140
141                 s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid));
142                 if (s) {
143                         if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
144                                 if (si.si_code == CLD_EXITED)
145                                         log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status);
146                                 else
147                                         log_error("/bin/mount for %s terminated by signal %s.", s, signal_to_string(si.si_status));
148
149                                 ret = EXIT_FAILURE;
150                         }
151
152                         free(s);
153                 }
154         }
155
156 finish:
157
158         if (pids)
159                 hashmap_free_free(pids);
160
161         return ret;
162 }