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