]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
449ddb2d | 2 | /*** |
449ddb2d | 3 | Copyright 2010 Lennart Poettering |
449ddb2d LP |
4 | ***/ |
5 | ||
449ddb2d | 6 | #include <errno.h> |
cf0fbc49 | 7 | #include <mntent.h> |
449ddb2d | 8 | #include <string.h> |
b16fee15 | 9 | #include <sys/prctl.h> |
449ddb2d LP |
10 | #include <sys/stat.h> |
11 | #include <sys/wait.h> | |
cf0fbc49 | 12 | #include <unistd.h> |
449ddb2d | 13 | |
4349cd7c | 14 | #include "exit-status.h" |
449ddb2d | 15 | #include "log.h" |
4349cd7c LP |
16 | #include "mount-setup.h" |
17 | #include "mount-util.h" | |
9eb977db | 18 | #include "path-util.h" |
b16fee15 | 19 | #include "process-util.h" |
24882e06 | 20 | #include "signal-util.h" |
b16fee15 | 21 | #include "strv.h" |
4349cd7c | 22 | #include "util.h" |
449ddb2d LP |
23 | |
24 | /* Goes through /etc/fstab and remounts all API file systems, applying | |
25 | * options that are in /etc/fstab that systemd might not have | |
26 | * respected */ | |
27 | ||
28 | int main(int argc, char *argv[]) { | |
b16fee15 | 29 | _cleanup_hashmap_free_free_ Hashmap *pids = NULL; |
5862d652 | 30 | _cleanup_endmntent_ FILE *f = NULL; |
449ddb2d | 31 | struct mntent* me; |
b16fee15 | 32 | int r; |
449ddb2d LP |
33 | |
34 | if (argc > 1) { | |
35 | log_error("This program takes no argument."); | |
22f4096c | 36 | return EXIT_FAILURE; |
449ddb2d LP |
37 | } |
38 | ||
4cfa2c99 | 39 | log_set_target(LOG_TARGET_AUTO); |
449ddb2d LP |
40 | log_parse_environment(); |
41 | log_open(); | |
42 | ||
4c12626c LP |
43 | umask(0022); |
44 | ||
9ffcff0e | 45 | f = setmntent("/etc/fstab", "re"); |
adb2ce5f | 46 | if (!f) { |
b16fee15 LP |
47 | if (errno == ENOENT) { |
48 | r = 0; | |
49 | goto finish; | |
50 | } | |
e0295d26 | 51 | |
b16fee15 LP |
52 | r = log_error_errno(errno, "Failed to open /etc/fstab: %m"); |
53 | goto finish; | |
449ddb2d LP |
54 | } |
55 | ||
d5099efc | 56 | pids = hashmap_new(NULL); |
adb2ce5f | 57 | if (!pids) { |
b16fee15 | 58 | r = log_oom(); |
449ddb2d LP |
59 | goto finish; |
60 | } | |
61 | ||
449ddb2d LP |
62 | while ((me = getmntent(f))) { |
63 | pid_t pid; | |
64 | int k; | |
65 | char *s; | |
66 | ||
b4efdf97 | 67 | /* Remount the root fs, /usr and all API VFS */ |
2b93b027 | 68 | if (!mount_point_is_api(me->mnt_dir) && |
b4efdf97 LP |
69 | !path_equal(me->mnt_dir, "/") && |
70 | !path_equal(me->mnt_dir, "/usr")) | |
449ddb2d LP |
71 | continue; |
72 | ||
73 | log_debug("Remounting %s", me->mnt_dir); | |
74 | ||
b6e1fff1 LP |
75 | r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); |
76 | if (r < 0) | |
b16fee15 | 77 | goto finish; |
4c253ed1 | 78 | if (r == 0) { |
449ddb2d LP |
79 | /* Child */ |
80 | ||
b16fee15 | 81 | execv(MOUNT_PATH, STRV_MAKE(MOUNT_PATH, me->mnt_dir, "-o", "remount")); |
449ddb2d | 82 | |
f00929ad | 83 | log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m"); |
22f4096c | 84 | _exit(EXIT_FAILURE); |
449ddb2d LP |
85 | } |
86 | ||
87 | /* Parent */ | |
88 | ||
89 | s = strdup(me->mnt_dir); | |
adb2ce5f | 90 | if (!s) { |
b16fee15 LP |
91 | r = log_oom(); |
92 | goto finish; | |
adb2ce5f LP |
93 | } |
94 | ||
4a0b58c4 | 95 | k = hashmap_put(pids, PID_TO_PTR(pid), s); |
adb2ce5f | 96 | if (k < 0) { |
b16fee15 LP |
97 | free(s); |
98 | r = log_oom(); | |
99 | goto finish; | |
449ddb2d LP |
100 | } |
101 | } | |
102 | ||
b16fee15 | 103 | r = 0; |
449ddb2d | 104 | while (!hashmap_isempty(pids)) { |
b92bea5d | 105 | siginfo_t si = {}; |
449ddb2d LP |
106 | char *s; |
107 | ||
449ddb2d LP |
108 | if (waitid(P_ALL, 0, &si, WEXITED) < 0) { |
109 | ||
110 | if (errno == EINTR) | |
111 | continue; | |
112 | ||
b16fee15 LP |
113 | r = log_error_errno(errno, "waitid() failed: %m"); |
114 | goto finish; | |
449ddb2d LP |
115 | } |
116 | ||
4a0b58c4 | 117 | s = hashmap_remove(pids, PID_TO_PTR(si.si_pid)); |
adb2ce5f | 118 | if (s) { |
1f0958f6 | 119 | if (!is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) { |
449ddb2d | 120 | if (si.si_code == CLD_EXITED) |
f00929ad | 121 | log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status); |
449ddb2d | 122 | else |
f00929ad | 123 | log_error(MOUNT_PATH " for %s terminated by signal %s.", s, signal_to_string(si.si_status)); |
449ddb2d | 124 | |
b16fee15 | 125 | r = -ENOEXEC; |
449ddb2d LP |
126 | } |
127 | ||
128 | free(s); | |
129 | } | |
130 | } | |
131 | ||
132 | finish: | |
b16fee15 | 133 | return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; |
449ddb2d | 134 | } |