]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/remount-fs/remount-fs.c
treewide: auto-convert the simple cases to log_*_errno()
[thirdparty/systemd.git] / src / remount-fs / remount-fs.c
CommitLineData
449ddb2d
LP
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
5430f7f2
LP
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
449ddb2d
LP
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
5430f7f2 16 Lesser General Public License for more details.
449ddb2d 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
449ddb2d
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <string.h>
26#include <sys/stat.h>
27#include <sys/wait.h>
28#include <mntent.h>
29
30#include "log.h"
31#include "util.h"
9eb977db 32#include "path-util.h"
449ddb2d
LP
33#include "set.h"
34#include "mount-setup.h"
9a57c629 35#include "exit-status.h"
449ddb2d
LP
36
37/* Goes through /etc/fstab and remounts all API file systems, applying
38 * options that are in /etc/fstab that systemd might not have
39 * respected */
40
41int main(int argc, char *argv[]) {
22f4096c 42 int ret = EXIT_FAILURE;
5862d652 43 _cleanup_endmntent_ FILE *f = NULL;
449ddb2d
LP
44 struct mntent* me;
45 Hashmap *pids = NULL;
46
47 if (argc > 1) {
48 log_error("This program takes no argument.");
22f4096c 49 return EXIT_FAILURE;
449ddb2d
LP
50 }
51
4cfa2c99 52 log_set_target(LOG_TARGET_AUTO);
449ddb2d
LP
53 log_parse_environment();
54 log_open();
55
4c12626c
LP
56 umask(0022);
57
adb2ce5f
LP
58 f = setmntent("/etc/fstab", "r");
59 if (!f) {
5862d652
ZJS
60 if (errno == ENOENT)
61 return EXIT_SUCCESS;
e0295d26 62
449ddb2d 63 log_error("Failed to open /etc/fstab: %m");
5862d652 64 return EXIT_FAILURE;
449ddb2d
LP
65 }
66
d5099efc 67 pids = hashmap_new(NULL);
adb2ce5f 68 if (!pids) {
449ddb2d
LP
69 log_error("Failed to allocate set");
70 goto finish;
71 }
72
22f4096c 73 ret = EXIT_SUCCESS;
449ddb2d
LP
74
75 while ((me = getmntent(f))) {
76 pid_t pid;
77 int k;
78 char *s;
79
b4efdf97 80 /* Remount the root fs, /usr and all API VFS */
2b93b027 81 if (!mount_point_is_api(me->mnt_dir) &&
b4efdf97
LP
82 !path_equal(me->mnt_dir, "/") &&
83 !path_equal(me->mnt_dir, "/usr"))
449ddb2d
LP
84 continue;
85
86 log_debug("Remounting %s", me->mnt_dir);
87
adb2ce5f
LP
88 pid = fork();
89 if (pid < 0) {
449ddb2d 90 log_error("Failed to fork: %m");
adb2ce5f 91 ret = EXIT_FAILURE;
449ddb2d
LP
92 continue;
93 }
94
95 if (pid == 0) {
96 const char *arguments[5];
97 /* Child */
98
99 arguments[0] = "/bin/mount";
100 arguments[1] = me->mnt_dir;
101 arguments[2] = "-o";
102 arguments[3] = "remount";
103 arguments[4] = NULL;
104
105 execv("/bin/mount", (char **) arguments);
106
107 log_error("Failed to execute /bin/mount: %m");
22f4096c 108 _exit(EXIT_FAILURE);
449ddb2d
LP
109 }
110
111 /* Parent */
112
113 s = strdup(me->mnt_dir);
adb2ce5f 114 if (!s) {
0d0f0c50 115 log_oom();
adb2ce5f
LP
116 ret = EXIT_FAILURE;
117 continue;
118 }
119
449ddb2d 120
adb2ce5f
LP
121 k = hashmap_put(pids, UINT_TO_PTR(pid), s);
122 if (k < 0) {
0a1beeb6 123 log_error_errno(-k, "Failed to add PID to set: %m");
22f4096c 124 ret = EXIT_FAILURE;
449ddb2d
LP
125 continue;
126 }
127 }
128
129 while (!hashmap_isempty(pids)) {
b92bea5d 130 siginfo_t si = {};
449ddb2d
LP
131 char *s;
132
449ddb2d
LP
133 if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
134
135 if (errno == EINTR)
136 continue;
137
138 log_error("waitid() failed: %m");
22f4096c 139 ret = EXIT_FAILURE;
449ddb2d
LP
140 break;
141 }
142
adb2ce5f
LP
143 s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid));
144 if (s) {
96342de6 145 if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
449ddb2d
LP
146 if (si.si_code == CLD_EXITED)
147 log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status);
148 else
149 log_error("/bin/mount for %s terminated by signal %s.", s, signal_to_string(si.si_status));
150
22f4096c 151 ret = EXIT_FAILURE;
449ddb2d
LP
152 }
153
154 free(s);
155 }
156 }
157
158finish:
159
160 if (pids)
161 hashmap_free_free(pids);
162
449ddb2d
LP
163 return ret;
164}