chiark / gitweb /
update TODO
[elogind.git] / src / remount-api-vfs / remount-api-vfs.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 <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"
32 #include "set.h"
33 #include "mount-setup.h"
34 #include "exit-status.h"
35
36 /* Goes through /etc/fstab and remounts all API file systems, applying
37  * options that are in /etc/fstab that systemd might not have
38  * respected */
39
40 int main(int argc, char *argv[]) {
41         int ret = EXIT_FAILURE;
42         FILE *f = NULL;
43         struct mntent* me;
44         Hashmap *pids = NULL;
45
46         if (argc > 1) {
47                 log_error("This program takes no argument.");
48                 return EXIT_FAILURE;
49         }
50
51         log_set_target(LOG_TARGET_AUTO);
52         log_parse_environment();
53         log_open();
54
55         umask(0022);
56
57         f = setmntent("/etc/fstab", "r");
58         if (!f) {
59                 if (errno == ENOENT) {
60                         ret = EXIT_SUCCESS;
61                         goto finish;
62                 }
63
64                 log_error("Failed to open /etc/fstab: %m");
65                 goto finish;
66         }
67
68         pids = hashmap_new(trivial_hash_func, trivial_compare_func);
69         if (!pids) {
70                 log_error("Failed to allocate set");
71                 goto finish;
72         }
73
74         ret = EXIT_SUCCESS;
75
76         while ((me = getmntent(f))) {
77                 pid_t pid;
78                 int k;
79                 char *s;
80
81                 if (!mount_point_is_api(me->mnt_dir))
82                         continue;
83
84                 log_debug("Remounting %s", me->mnt_dir);
85
86                 pid = fork();
87                 if (pid < 0) {
88                         log_error("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("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_error("Out of memory.");
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("Failed to add PID to set: %s", strerror(-k));
122                         ret = EXIT_FAILURE;
123                         continue;
124                 }
125         }
126
127         while (!hashmap_isempty(pids)) {
128                 siginfo_t si;
129                 char *s;
130
131                 zero(si);
132                 if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
133
134                         if (errno == EINTR)
135                                 continue;
136
137                         log_error("waitid() failed: %m");
138                         ret = EXIT_FAILURE;
139                         break;
140                 }
141
142                 s = hashmap_remove(pids, UINT_TO_PTR(si.si_pid));
143                 if (s) {
144                         if (!is_clean_exit(si.si_code, si.si_status)) {
145                                 if (si.si_code == CLD_EXITED)
146                                         log_error("/bin/mount for %s exited with exit status %i.", s, si.si_status);
147                                 else
148                                         log_error("/bin/mount for %s terminated by signal %s.", s, signal_to_string(si.si_status));
149
150                                 ret = EXIT_FAILURE;
151                         }
152
153                         free(s);
154                 }
155         }
156
157 finish:
158
159         if (pids)
160                 hashmap_free_free(pids);
161
162         if (f)
163                 endmntent(f);
164
165         return ret;
166 }