]> git.proxmox.com Git - systemd.git/blob - src/remount-fs/remount-fs.c
Imported Upstream version 220
[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 "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] = MOUNT_PATH;
98 arguments[1] = me->mnt_dir;
99 arguments[2] = "-o";
100 arguments[3] = "remount";
101 arguments[4] = NULL;
102
103 execv(MOUNT_PATH, (char **) arguments);
104
105 log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %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(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status);
146 else
147 log_error(MOUNT_PATH " 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 }