3
* Copyright © 2009 Canonical Ltd.
4
* Author: Scott James Remnant <scott@netsplit.com>.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2, as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
#endif /* HAVE_CONFIG_H */
27
#include <sys/types.h>
30
#include <sys/mount.h>
31
#include <sys/utsname.h>
32
#include <sys/sendfile.h>
49
#include <nih/macros.h>
50
#include <nih/alloc.h>
51
#include <nih/string.h>
52
#include <nih/option.h>
53
#include <nih/child.h>
54
#include <nih/signal.h>
57
#include <nih/logging.h>
58
#include <nih/error.h>
60
#include <nih-dbus/dbus_connection.h>
61
#include <nih-dbus/dbus_proxy.h>
63
#include "dbus/upstart.h"
64
#include "com.ubuntu.Upstart.h"
70
* fsck progress (usplash activation)
74
typedef struct mount Mount;
76
typedef int (*MountHook) (Mount *mnt);
85
struct udev_device *udev_device;
104
typedef struct filesystem {
109
typedef struct process {
114
void (*handler) (Mount *mnt, pid_t pid, int status);
120
EXIT_ERROR, /* General/OS error */
121
EXIT_FSCK, /* Filesystem check failed */
122
EXIT_MOUNT, /* Failed to mount a filesystem */
123
EXIT_REBOOT, /* Require a reboot */
127
Mount *new_mount (const char *mountpoint, const char *device,
128
int check, const char *type, const char *opts,
130
Mount *find_mount (const char *mountpoint);
131
void update_mount (Mount *mnt, const char *device, int check,
132
const char *type, const char *opts,
135
int has_option (Mount *mnt, const char *option, int current);
136
char * get_option (const void *parent, Mount *mnt, const char *option,
138
char * cut_options (const void *parent, Mount *mnt, ...);
140
int is_swap (Mount *mnt);
141
int is_virtual (Mount *mnt);
142
int is_remote (Mount *mnt);
143
int is_fhs (Mount *mnt);
144
int needs_remount (Mount *mnt);
146
void build_paths (void);
147
int path_compar (const void *a, const void *b);
149
void parse_fstab (void);
150
void parse_mountinfo (void);
151
void parse_filesystems (void);
154
void device_ready (Mount *mnt);
155
void mountpoint_ready (Mount *mnt);
156
void mounted (Mount *mnt);
157
void children_ready (Mount *mnt, int pass);
159
pid_t spawn (Mount *mnt, char * const *args, int wait,
160
void (*handler) (Mount *mnt, pid_t pid, int status));
161
void spawn_child_handler (Process *proc, pid_t pid,
162
NihChildEvents event, int status);
164
void run_mount (Mount *mnt, int fake);
165
void run_mount_finished (Mount *mnt, pid_t pid, int status);
167
void run_swapon (Mount *mnt);
168
void run_swapon_finished (Mount *mnt, pid_t pid, int status);
170
void run_fsck (Mount *mnt);
171
void run_fsck_finished (Mount *mnt, pid_t pid, int status);
173
void write_mtab (void);
175
int has_showthrough (Mount *root);
176
void mount_showthrough (Mount *root);
178
void upstart_disconnected (DBusConnection *connection);
179
void emit_event (const char *name);
180
void emit_event_error (void *data, NihDBusMessage *message);
182
void udev_monitor_watcher (struct udev_monitor *udev_monitor,
183
NihIoWatch *watch, NihIoEvents events);
184
void usr1_handler (void *data, NihSignal *signal);
186
int dev_hook (Mount *mnt);
187
int tmp_hook (Mount *mnt);
188
int var_run_hook (Mount *mnt);
191
static const struct {
192
const char *mountpoint;
199
{ "/", "/dev/root", TRUE, "rootfs", NULL, NULL },
200
{ "/proc", NULL, FALSE, "proc", "nodev,noexec,nosuid", NULL },
201
{ "/proc/sys/fs/binfmt_misc", NULL, FALSE, "binfmt_misc", NULL, NULL },
202
{ "/sys", NULL, FALSE, "sysfs", "nodev,noexec,nosuid", NULL },
203
{ "/sys/fs/fuse/connections", NULL, FALSE, "fusectl", NULL, NULL },
204
{ "/sys/kernel/debug", NULL, FALSE, "debugfs", NULL, NULL },
205
{ "/sys/kernel/security", NULL, FALSE, "securityfs", NULL, NULL },
206
{ "/spu", NULL, FALSE, "spufs", "gid=spu", NULL },
207
{ "/dev", NULL, FALSE, "tmpfs", "mode=0755", dev_hook },
208
{ "/dev/pts", NULL, FALSE, "devpts", "noexec,nosuid,gid=tty,mode=0620", NULL },
209
{ "/dev/shm", NULL, FALSE, "tmpfs", "nosuid,nodev", NULL },
210
{ "/tmp", NULL, FALSE, NULL, NULL, tmp_hook },
211
{ "/var/run", NULL, FALSE, "tmpfs", "mode=0755,nosuid,showthrough", var_run_hook },
212
{ "/var/lock", NULL, FALSE, "tmpfs", "nodev,noexec,nosuid,showthrough", NULL },
213
{ "/lib/init/rw", NULL, FALSE, "tmpfs", "mode=0755,nosuid", NULL },
217
static const char *fhs[] = {
219
"/boot", /* Often separate */
221
"/dev/pts", /* Built-in */
222
"/dev/shm", /* Built-in */
224
"/lib/init/rw", /* Built-in */
226
"/proc", /* Linux appendix */
227
"/proc/sys/fs/binfmt_misc", /* Built-in */
228
"/spu", /* Built-in */
230
"/sys", /* Not in FHS yet */
231
"/sys/fs/fuse/connections", /* Built-in */
232
"/sys/kernel/debug", /* Built-in */
233
"/sys/kernel/security", /* Built-in */
237
"/usr/var", /* Recommendation for /var symlink */
254
Mount *mounts = NULL;
255
size_t num_mounts = 0;
258
size_t num_paths = 0;
260
Filesystem *filesystems = NULL;
261
size_t num_filesystems = 0;
263
NihList *procs = NULL;
265
int written_mtab = FALSE;
267
int exit_code = EXIT_OK;
272
* Proxy to Upstart daemon.
274
static NihDBusProxy *upstart = NULL;
280
* Set to TRUE if we should become a daemon, rather than just running
283
static int daemonise = FALSE;
288
* Set to TRUE if we should pass -f to fsck invocations.
290
static int force_fsck = FALSE;
295
* Set to TRUE if we should pass -y to fsck invocations.
297
static int fsck_fix = FALSE;
302
* Set to TRUE if we should ignore remote filesystems.
304
static int no_remote = FALSE;
309
* Set to the number of hours grace files and directories in /tmp
310
* are given before being removed.
312
static int tmptime = 0;
316
new_mount (const char *mountpoint,
325
nih_assert (mountpoint != NULL);
327
mounts = NIH_MUST (nih_realloc (mounts, NULL,
328
sizeof (Mount) * (num_mounts + 1)));
329
mnt = &mounts[num_mounts++];
331
mnt->mountpoint = NIH_MUST (nih_strdup (mounts, mountpoint));
332
mnt->mountpoint_ready = FALSE;
334
mnt->mounted = FALSE;
336
mnt->device = device ? NIH_MUST (nih_strdup (mounts, device)) : NULL;
337
mnt->udev_device = NULL;
340
mnt->device_ready = FALSE;
342
mnt->type = type ? NIH_MUST (nih_strdup (mounts, type)) : NULL;
343
mnt->virtual = FALSE;
344
mnt->opts = opts ? NIH_MUST (nih_strdup (mounts, opts)) : NULL;
345
mnt->mount_opts = NULL;
349
nih_debug ("%s: %s %s %s%s%s",
354
mnt->check ? "*" : "",
355
mnt->hook ? "+" : "");
361
find_mount (const char *mountpoint)
363
nih_assert (mountpoint != NULL);
365
for (size_t i = 0; i < num_mounts; i++)
366
if (! strcmp (mounts[i].mountpoint, mountpoint))
373
update_mount (Mount * mnt,
380
nih_assert (mnt != NULL);
384
nih_unref (mnt->device, mounts);
385
mnt->device = NIH_MUST (nih_strdup (mounts, device));
392
/* Remove the current hook if we change the type */
394
|| strcmp (type, mnt->type))
398
nih_unref (mnt->type, mounts);
399
mnt->type = NIH_MUST (nih_strdup (mounts, type));
404
nih_unref (mnt->opts, mounts);
405
mnt->opts = NIH_MUST (nih_strdup (mounts, opts));
411
nih_debug ("%s: %s %s %s%s%s",
416
mnt->check ? "*" : "",
417
mnt->hook ? "+" : "");
422
has_option (Mount * mnt,
429
nih_assert (mnt != NULL);
430
nih_assert (option != NULL);
432
opts = current ? mnt->mount_opts : mnt->opts;
437
while (i < strlen (opts)) {
441
j = strcspn (opts + i, ",=");
442
k = strcspn (opts + i + j, ",");
444
if (! strncmp (opts + i, option, j))
454
get_option (const void *parent,
462
nih_assert (mnt != NULL);
463
nih_assert (option != NULL);
465
opts = current ? mnt->mount_opts : mnt->opts;
470
while (i < strlen (opts)) {
474
j = strcspn (opts + i, ",=");
475
k = strcspn (opts + i + j, ",");
477
if (! strncmp (opts + i, option, j))
478
return nih_strndup (parent, opts + i + j + 1,
488
cut_options (const void *parent,
496
nih_assert (mnt != NULL);
498
va_start (args, mnt);
500
opts = NIH_MUST (nih_strdup (parent, mnt->opts));
503
while (i < strlen (opts)) {
509
j = strcspn (opts + i, ",=");
510
k = strcspn (opts + i + j, ",");
512
va_copy (options, args);
513
while ((option = va_arg (options, const char *)) != NULL) {
514
if (! strncmp (opts + i, option, j))
520
memmove (opts + (i ? i - 1 : 0), opts + i + j + k,
521
strlen (opts) - i - j - k + 1);
538
nih_assert (mnt != NULL);
542
} else if (strcmp (mnt->type, "swap")) {
544
} else if (! mnt->device) {
552
is_virtual (Mount *mnt)
554
nih_assert (mnt != NULL);
560
is_remote (Mount *mnt)
562
nih_assert (mnt != NULL);
564
if (has_option (mnt, "_netdev", FALSE)) {
566
} else if (! mnt->type) {
568
} else if (strcmp (mnt->type, "nfs")
569
&& strcmp (mnt->type, "nfs4")
570
&& strcmp (mnt->type, "smbfs")
571
&& strcmp (mnt->type, "cifs")
572
&& strcmp (mnt->type, "coda")
573
&& strcmp (mnt->type, "ncp")
574
&& strcmp (mnt->type, "ncpfs")
575
&& strcmp (mnt->type, "ocfs2")
576
&& strcmp (mnt->type, "gfs")) {
586
nih_assert (mnt != NULL);
588
for (const char * const *path = fhs; path && *path; path++)
589
if (! strcmp (*path, mnt->mountpoint))
596
needs_remount (Mount *mnt)
598
nih_assert (mnt != NULL);
600
if (mnt->mounted && has_option (mnt, "ro", TRUE)) {
611
for (size_t i = 0; i < num_mounts; i++) {
614
if (mounts[i].mountpoint[0] == '/') {
615
paths = NIH_MUST (nih_realloc (paths, NULL,
616
sizeof (Path) * (num_paths + 1)));
617
path = &paths[num_paths++];
619
path->path = mounts[i].mountpoint;
620
path->mnt = &mounts[i];
621
path->device = FALSE;
625
&& strncmp (mounts[i].device, "/dev/", 5)
626
&& (! mounts[i].virtual)) {
627
paths = NIH_MUST (nih_realloc (paths, NULL,
628
sizeof (Path) * (num_paths + 1)));
629
path = &paths[num_paths++];
631
path->path = mounts[i].device;
632
path->mnt = &mounts[i];
637
qsort (paths, num_paths, sizeof (Path),
642
path_compar (const void *a,
652
ret = strcmp (path_a->path, path_b->path);
655
} else if (path_a->device && (! path_b->device)) {
657
} else if (path_b->device && (! path_a->device)) {
669
struct mntent *mntent;
671
nih_debug ("updating mounts");
673
fstab = setmntent (_PATH_MNTTAB, "r");
675
nih_fatal ("%s: %s", _PATH_MNTTAB, strerror (errno));
679
while ((mntent = getmntent (fstab)) != NULL) {
682
mnt = find_mount (mntent->mnt_dir);
686
mntent->mnt_passno != 0,
691
mnt = new_mount (mntent->mnt_dir,
693
mntent->mnt_passno != 0,
704
parse_mountinfo (void)
707
nih_local char *buf = NULL;
710
nih_debug ("updating mounts");
712
mountinfo = fopen ("/proc/self/mountinfo", "r");
713
if ((! mountinfo) && (errno == ENOENT)) {
716
nih_debug ("mounting /proc");
717
if (mount ("none", "/proc", "proc",
718
MS_NODEV | MS_NOEXEC | MS_NOSUID, NULL) < 0) {
719
nih_fatal ("%s: %s: %s", "/proc",
720
_("unable to mount"),
725
mnt = find_mount ("/proc");
729
mountinfo = fopen ("/proc/self/mountinfo", "r");
732
nih_fatal ("%s: %s", "/proc/self/mountinfo",
738
buf = NIH_MUST (nih_alloc (NULL, bufsz));
740
while (fgets (buf, bufsz, mountinfo) != NULL) {
750
while ((! strchr (buf, '\n')) && (! feof (mountinfo))) {
751
buf = NIH_MUST (nih_realloc (buf, NULL, bufsz + 4096));
752
fgets (buf + bufsz - 1, 4097, mountinfo);
757
ptr = strtok_r (buf, " \t\n", &saveptr);
762
ptr = strtok_r (NULL, " \t\n", &saveptr);
767
ptr = strtok_r (NULL, " \t\n", &saveptr);
772
ptr = strtok_r (NULL, " \t\n", &saveptr);
777
mountpoint = strtok_r (NULL, " \t\n", &saveptr);
782
mount_opts = strtok_r (NULL, " \t\n", &saveptr);
786
/* optional fields */
787
while (((ptr = strtok_r (NULL, " \t\n", &saveptr)) != NULL)
788
&& strcmp (ptr, "-"))
794
type = strtok_r (NULL, " \t\n", &saveptr);
797
if (! strcmp (type, "rootfs"))
801
device = strtok_r (NULL, " \t\n", &saveptr);
804
if (! strcmp (device, "/dev/root"))
807
/* superblock opts */
808
super_opts = strtok_r (NULL, " \t\n", &saveptr);
813
mnt = find_mount (mountpoint);
815
update_mount (mnt, device, -1, type, NULL, NULL);
818
nih_unref (mnt->mount_opts, mounts);
820
mnt = new_mount (mountpoint, device, FALSE, type, NULL, NULL);
824
mnt->mount_opts = NIH_MUST (nih_sprintf (mounts, "%s,%s",
825
mount_opts, super_opts));
828
if (fclose (mountinfo) < 0) {
829
nih_fatal ("%s: %s", "/proc/self/mountinfo",
836
parse_filesystems (void)
839
nih_local char *buf = NULL;
842
nih_debug ("reading filesystems");
844
fs = fopen ("/proc/filesystems", "r");
846
nih_fatal ("%s: %s", "/proc/filesystems",
852
buf = NIH_MUST (nih_alloc (NULL, bufsz));
854
while (fgets (buf, bufsz, fs) != NULL) {
857
Filesystem *filesystem;
859
while (((ptr = strchr (buf, '\n')) == NULL) && (! feof (fs))) {
860
buf = NIH_MUST (nih_realloc (buf, NULL, bufsz + 4096));
861
fgets (buf + bufsz - 1, 4097, fs);
866
if (! strncmp (buf, "nodev\t", 6)) {
869
nih_debug ("%s (nodev)", ptr);
870
} else if (buf[0] == '\t') {
873
nih_debug ("%s", ptr);
877
filesystems = NIH_MUST (nih_realloc (filesystems, NULL,
878
sizeof (Filesystem) * (num_filesystems + 1)));
879
filesystem = &filesystems[num_filesystems++];
881
filesystem->name = NIH_MUST (nih_strdup (filesystems, ptr));
882
filesystem->nodev = nodev;
885
if (fclose (fs) < 0) {
886
nih_fatal ("%s: %s", "/proc/filesystems",
895
for (size_t i = 0; i < num_mounts; i++) {
899
/* Check through the known filesystems, if this is a virtual
900
* filesystem then mark it as such so we don't wait for any
901
* device to be ready. Otherwise if we didn't find the
902
* filesystem type, and no device is specified, drop as this
903
* is platform-dependent (e.g. spufs).
905
if (mounts[i].type) {
906
for (j = 0; j < num_filesystems; j++)
907
if (! strcmp (mounts[i].type, filesystems[j].name))
910
if (j < num_filesystems) {
911
if (filesystems[j].nodev && (! is_remote (&mounts[i])))
912
mounts[i].virtual = TRUE;
913
} else if ((! mounts[i].device) && (! mounts[i].mounted)) {
914
nih_debug ("%s: dropping unknown filesystem",
915
mounts[i].mountpoint);
917
} else if (! strcmp (mounts[i].type, "ignore")) {
918
nih_debug ("%s: dropping ignored filesystem",
919
mounts[i].mountpoint);
924
/* Drop anything that's not auto-mounted which isn't already
927
if (has_option (&mounts[i], "noauto", FALSE) && (! mounts[i].mounted)) {
928
nih_debug ("%s: dropping noauto filesystem",
929
mounts[i].mountpoint);
934
memmove (&mounts[i], &mounts[i+1],
935
sizeof (Mount) * (num_mounts - i - 1));
939
if (is_virtual (&mounts[i])) {
940
nih_debug ("virtual %s", mounts[i].mountpoint);
941
} else if (is_swap (&mounts[i])) {
942
nih_debug ("swap %s", mounts[i].device);
943
} else if (is_remote (&mounts[i])) {
944
nih_debug ("remote %s", mounts[i].mountpoint);
946
nih_debug ("local %s", mounts[i].mountpoint);
949
if (is_fhs (&mounts[i]))
950
nih_debug ("FHS %s", mounts[i].mountpoint);
957
device_ready (Mount *mnt)
959
nih_assert (mnt != NULL);
960
nih_assert (mnt->device != NULL);
961
nih_assert (mnt->type != NULL);
963
nih_debug ("%s", mnt->mountpoint);
965
/* Activate swap devices as soon as the device is ready;
966
* don't mount filesystems until the mountpoint is ready
969
mnt->device_ready = TRUE;
972
} else if (mnt->mountpoint_ready)
973
run_mount (mnt, FALSE);
977
mountpoint_ready (Mount *mnt)
979
nih_assert (mnt != NULL);
981
nih_debug ("%s", mnt->mountpoint);
983
/* Activate virtual filesystems as soon as the mountpoint
984
* is ready, otherwise don't mount filesystems until the
985
* device is ready. Be sure to ignore swap partitions
986
* since they're mounted in device_ready() itself.
988
mnt->mountpoint_ready = TRUE;
991
|| (mnt->device_ready && (! is_swap (mnt))))
992
run_mount (mnt, FALSE);
998
size_t num_virtual = 0;
999
size_t num_virtual_mounted = 0;
1000
static int virtual_triggered = FALSE;
1001
size_t num_swap = 0;
1002
size_t num_swap_mounted = 0;
1003
static int swap_triggered = FALSE;
1004
size_t num_remote = 0;
1005
size_t num_remote_mounted = 0;
1006
static int remote_triggered = FALSE;
1007
size_t num_local = 0;
1008
size_t num_local_mounted = 0;
1009
static int local_triggered = FALSE;
1011
size_t num_fhs_mounted = 0;
1012
static int fhs_triggered = FALSE;
1014
nih_assert (mnt != NULL);
1016
nih_debug ("%s", mnt->mountpoint);
1019
if (mnt->hook (mnt) < 0) {
1020
exit_code = nih_max (exit_code, EXIT_ERROR);
1021
if (NIH_LIST_EMPTY (procs))
1028
/* Any previous mount options no longer apply
1029
* (ie. we're not read-only anymore)
1031
if (mnt->mount_opts)
1032
nih_unref (mnt->mount_opts, mounts);
1033
mnt->mount_opts = NULL;
1038
/* Look at the current table state */
1039
for (size_t i = 0; i < num_mounts; i++) {
1040
int mounted = FALSE;
1042
if (is_virtual (&mounts[i])) {
1044
if (mounts[i].mounted) {
1045
num_virtual_mounted++;
1048
} else if (is_swap (&mounts[i])) {
1050
if (mounts[i].mounted) {
1054
} else if (is_remote (&mounts[i])) {
1056
if (mounts[i].mounted) {
1057
num_remote_mounted++;
1062
if (mounts[i].mounted && (! needs_remount (&mounts[i]))) {
1063
num_local_mounted++;
1068
if (is_fhs (&mounts[i])) {
1075
nih_debug ("virtual %zi/%zi swap %zi/%zi remote %zi/%zi local %zi/%zi",
1076
num_virtual_mounted, num_virtual,
1077
num_swap_mounted, num_swap,
1078
num_remote_mounted, num_remote,
1079
num_local_mounted, num_local);
1081
if ((! virtual_triggered) && (num_virtual_mounted == num_virtual)) {
1082
nih_info ("virtual filesystems finished");
1083
emit_event ("virtual-filesystems");
1084
virtual_triggered = TRUE;
1086
if ((! swap_triggered) && (num_swap_mounted == num_swap)) {
1087
nih_info ("swap finished");
1088
emit_event ("all-swaps");
1089
swap_triggered = TRUE;
1091
if ((! remote_triggered) && (num_remote_mounted == num_remote)) {
1092
nih_info ("remote finished");
1093
emit_event ("remote-filesystems");
1094
remote_triggered = TRUE;
1096
if ((! local_triggered) && (num_local_mounted == num_local)) {
1097
nih_info ("local finished");
1098
emit_event ("local-filesystems");
1099
local_triggered = TRUE;
1102
nih_debug ("fhs %zi/%zi", num_fhs_mounted, num_fhs);
1103
if ((! fhs_triggered) && (num_fhs_mounted == num_fhs)) {
1104
nih_info ("fhs mounted");
1105
emit_event ("filesystem");
1106
fhs_triggered = TRUE;
1109
if ((num_virtual_mounted == num_virtual)
1110
&& (num_swap_mounted == num_swap)
1111
&& (no_remote || (num_remote_mounted == num_remote))
1112
&& (num_local_mounted == num_local)) {
1113
nih_info ("finished");
1114
emit_event ("all-filesystems");
1115
nih_main_loop_exit (EXIT_OK);
1118
/* Mount points underneath this are now ready for mounting,
1119
* unless this was the root filesystem in which case they
1120
* were already ready anyway so don't mark them again.
1122
if (! is_swap (mnt)) {
1123
if (strcmp (mnt->mountpoint, "/")) {
1124
children_ready (mnt, 0);
1126
children_ready (mnt, 2);
1132
children_ready (Mount *root,
1137
nih_assert (root != NULL);
1139
while ((i < num_paths)
1140
&& ((paths[i].mnt != root) || paths[i].device))
1142
nih_assert (i++ < num_paths);
1144
while ((i < num_paths)
1145
&& (! strncmp (paths[i].path, root->mountpoint,
1146
strlen (root->mountpoint)))
1147
&& ((! strcmp (root->mountpoint, "/"))
1148
|| (paths[i].path[strlen (root->mountpoint)] == '/')
1149
|| (paths[i].path[strlen (root->mountpoint)] == '\0'))) {
1151
struct stat statbuf;
1154
if (lstat (path->path, &statbuf) < 0) {
1155
nih_debug ("ignored %s: %s", path->path,
1161
/* Do not consider devices ready in the "mounted ro"
1162
* pass, only when writable.
1165
if ((S_ISREG (statbuf.st_mode)
1166
|| S_ISDIR (statbuf.st_mode))) {
1167
device_ready (path->mnt);
1169
nih_debug ("ignored %s: not regular",
1174
/* If there is no type to mount, then this is a hook
1175
* placeholder and we want don't want to run it in
1176
* the initial "mounted ro" pass. Otherwise
1177
* we don't don't want to run mount in the "remount"
1180
if (pass != (path->mnt->type ? 2 : 1))
1181
mountpoint_ready (path->mnt);
1183
/* Children of this mount point aren't ready until
1184
* this mountpoint is mounted, unless they're always
1185
* expected to show through.
1187
while ((i < num_paths)
1188
&& (! strncmp (paths[i].path, path->path,
1189
strlen (path->path)))
1190
&& ((paths[i].path[strlen (path->path)] == '/')
1191
|| (paths[i].path[strlen (path->path)] == '\0')))
1193
if ((! paths[i].device)
1194
&& paths[i].mnt->type
1195
&& has_option (paths[i].mnt, "showthrough", FALSE)
1196
&& (lstat (paths[i].path, &statbuf) == 0)
1197
&& S_ISDIR (statbuf.st_mode)) {
1198
mountpoint_ready (paths[i].mnt);
1200
nih_debug ("skipped %s", paths[i].path);
1212
char * const * args,
1214
void (*handler) (Mount *mnt, pid_t pid, int status))
1221
nih_assert (mnt != NULL);
1222
nih_assert (args != NULL);
1223
nih_assert (args[0] != NULL);
1225
NIH_ZERO (pipe2 (fds, O_CLOEXEC));
1232
nih_fatal ("%s %s: %s", args[0],
1233
is_swap (mnt) ? mnt->device : mnt->mountpoint,
1237
nih_local char *msg = NULL;
1239
for (char * const *arg = args; arg && *arg; arg++)
1240
NIH_MUST (nih_strcat_sprintf (&msg, NULL, msg ? " %s" : "%s", *arg));
1242
nih_debug ("%s", msg);
1244
execvp (args[0], args);
1245
nih_fatal ("%s %s [%d]: %s", args[0],
1246
is_swap (mnt) ? mnt->device : mnt->mountpoint,
1247
getpid (), strerror (errno));
1248
write (fds[1], &flag, 1);
1254
ret = read (fds[0], &flag, 1);
1258
exit_code = nih_max (exit_code, EXIT_ERROR);
1259
if (NIH_LIST_EMPTY (procs))
1266
nih_debug ("%s %s [%d]", args[0],
1267
is_swap (mnt) ? mnt->device : mnt->mountpoint,
1270
proc = NIH_MUST (nih_new (NULL, Process));
1271
nih_list_init (&proc->entry);
1277
nih_ref (proc->args, proc);
1281
proc->handler = handler;
1283
nih_list_add (procs, &proc->entry);
1288
NIH_ZERO (waitid (P_PID, pid, &info, WEXITED));
1289
spawn_child_handler (proc, pid, info.si_code == CLD_EXITED ? NIH_CHILD_EXITED : NIH_CHILD_KILLED,
1293
NIH_MUST (nih_child_add_watch (NULL, pid, NIH_CHILD_EXITED|NIH_CHILD_KILLED|NIH_CHILD_DUMPED,
1294
(NihChildHandler)spawn_child_handler, proc));
1300
spawn_child_handler (Process * proc,
1302
NihChildEvents event,
1305
nih_assert (proc != NULL);
1306
nih_assert (pid == proc->pid);
1308
nih_list_remove (&proc->entry);
1310
if (event != NIH_CHILD_EXITED) {
1313
sig = nih_signal_to_name (status);
1315
nih_fatal ("%s %s [%d] killed by %s signal", proc->args[0],
1316
is_swap (proc->mnt) ? proc->mnt->device : proc->mnt->mountpoint,
1319
nih_fatal ("%s %s [%d] killed by signal %d", proc->args[0],
1320
is_swap (proc->mnt) ? proc->mnt->device : proc->mnt->mountpoint,
1324
exit_code = nih_max (exit_code, EXIT_ERROR);
1325
if (NIH_LIST_EMPTY (procs))
1330
} else if (status) {
1331
nih_warn ("%s %s [%d] terminated with status %d", proc->args[0],
1332
is_swap (proc->mnt) ? proc->mnt->device : proc->mnt->mountpoint,
1335
nih_info ("%s %s [%d] exited normally", proc->args[0],
1336
is_swap (proc->mnt) ? proc->mnt->device : proc->mnt->mountpoint,
1341
proc->handler (proc->mnt, pid, status);
1345
if (exit_code && NIH_LIST_EMPTY (procs))
1351
run_mount (Mount *mnt,
1354
nih_local char **args = NULL;
1355
size_t args_len = 0;
1357
nih_assert (mnt != NULL);
1360
nih_debug ("mtab %s", mnt->mountpoint);
1361
} else if (mnt->mounted) {
1362
if (needs_remount (mnt)) {
1363
nih_info ("remounting %s", mnt->mountpoint);
1365
nih_debug ("%s: already mounted", mnt->mountpoint);
1369
} else if (mnt->mount_pid > 0) {
1370
nih_debug ("%s: already mounting", mnt->mountpoint);
1372
} else if (! mnt->type) {
1373
nih_debug ("%s: hook", mnt->mountpoint);
1377
nih_info ("mounting %s", mnt->mountpoint);
1380
args = NIH_MUST (nih_str_array_new (NULL));
1381
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "mount"));
1383
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-f"));
1384
} else if (! written_mtab) {
1385
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-n"));
1387
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-a"));
1388
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-t"));
1389
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->type));
1391
nih_local char *opts = NULL;
1393
opts = cut_options (NULL, mnt, "showthrough", NULL);
1394
if (mnt->mounted && (! fake)) {
1397
tmp = NIH_MUST (nih_strdup (NULL, "remount,"));
1398
NIH_MUST (nih_strcat (&tmp, NULL, opts));
1404
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-o"));
1405
NIH_MUST (nih_str_array_addp (&args, NULL, &args_len, opts));
1406
} else if (mnt->mounted && (! fake)) {
1407
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-o"));
1408
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "remount"));
1410
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->device ?: "none"));
1411
if (has_showthrough (mnt) && (! fake)) {
1412
nih_local char *mountpoint = NULL;
1414
mountpoint = NIH_MUST (nih_sprintf (NULL, "/dev/%s",
1417
for (size_t i = 5; i < strlen (mountpoint); i++)
1418
if (mountpoint[i] == '/')
1419
mountpoint[i] = '.';
1421
nih_debug ("diverting mount to %s", mountpoint);
1422
if ((mkdir (mountpoint, 0755) < 0)
1423
&& (errno != EEXIST)) {
1424
nih_fatal ("mkdir %s: %s", mountpoint, strerror (errno));
1426
exit_code = nih_max (exit_code, EXIT_ERROR);
1427
if (NIH_LIST_EMPTY (procs))
1431
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mountpoint));
1433
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->mountpoint));
1437
spawn (mnt, args, TRUE, NULL);
1438
} else if (has_option (mnt, "showthrough", FALSE)) {
1439
spawn (mnt, args, TRUE, run_mount_finished);
1441
mnt->mount_pid = spawn (mnt, args, FALSE, run_mount_finished);
1446
run_mount_finished (Mount *mnt,
1450
nih_assert (mnt != NULL);
1451
nih_assert ((mnt->mount_pid == pid)
1452
|| (mnt->mount_pid == -1));
1454
mnt->mount_pid = -1;
1456
if (status & ~(16 | 64)) {
1457
nih_error ("Filesystem could not be mounted: %s",
1460
exit_code = nih_max (exit_code, EXIT_MOUNT);
1464
mount_showthrough (mnt);
1470
run_swapon (Mount *mnt)
1472
nih_local char **args = NULL;
1473
size_t args_len = 0;
1474
nih_local char * pri = NULL;
1476
nih_assert (mnt != NULL);
1477
nih_assert (mnt->device != NULL);
1480
nih_debug ("%s: already activated", mnt->device);
1483
} else if (mnt->mount_pid > 0) {
1484
nih_debug ("%s: already activating", mnt->device);
1488
nih_info ("activating %s", mnt->device);
1490
args = NIH_MUST (nih_str_array_new (NULL));
1491
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "swapon"));
1493
if (((pri = get_option (NULL, mnt, "pri", FALSE)) != NULL)
1495
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-p"));
1496
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, pri));
1498
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->device));
1500
mnt->mount_pid = spawn (mnt, args, FALSE, run_swapon_finished);
1504
run_swapon_finished (Mount *mnt,
1508
nih_assert (mnt != NULL);
1509
nih_assert (mnt->mount_pid == pid);
1511
mnt->mount_pid = -1;
1513
/* Swapon doesn't return any useful status codes, so we just
1514
* carry on regardless if it failed.
1517
nih_warn ("Problem activating swap: %s", mnt->device);
1524
run_fsck (Mount *mnt)
1526
nih_local char **args = NULL;
1527
size_t args_len = 0;
1529
nih_assert (mnt != NULL);
1530
nih_assert (mnt->device != NULL);
1531
nih_assert (mnt->type != NULL);
1534
nih_debug ("%s: no check required", mnt->mountpoint);
1537
} else if (mnt->mounted && (! has_option (mnt, "ro", TRUE))) {
1538
nih_debug ("%s: mounted filesystem", mnt->mountpoint);
1541
} else if (mnt->mount_pid > 0) {
1542
nih_debug ("%s: already mounting", mnt->mountpoint);
1544
} else if (mnt->fsck_pid > 0) {
1545
nih_debug ("%s: already checking", mnt->mountpoint);
1549
/* FIXME look up underlying device, and add to fsck queue.
1550
* only continue if was first in the queue.
1553
nih_info ("checking %s", mnt->mountpoint);
1555
args = NIH_MUST (nih_str_array_new (NULL));
1556
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "fsck"));
1558
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-y"));
1560
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-a"));
1563
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-f"));
1564
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-t"));
1565
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->type));
1566
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mnt->device));
1568
mnt->fsck_pid = spawn (mnt, args, FALSE, run_fsck_finished);
1572
run_fsck_finished (Mount *mnt,
1576
nih_assert (mnt != NULL);
1577
nih_assert (mnt->fsck_pid == pid);
1581
/* FIXME remove from fsck queue for underlying device,
1582
* queue next in that list if there is one.
1586
nih_error ("System must be rebooted: %s",
1588
exit_code = nih_max (exit_code, EXIT_REBOOT);
1589
} else if (status & 4) {
1590
nih_error ("Filesystem has errors: %s",
1592
exit_code = nih_max (exit_code, EXIT_FSCK);
1593
} else if (status & (8 | 16 | 128)) {
1594
nih_fatal ("General fsck error");
1595
exit_code = nih_max (exit_code, EXIT_ERROR);
1596
} else if (status & 1) {
1597
nih_info ("Filesystem errors corrected: %s",
1599
} else if (status & 32) {
1600
nih_info ("Filesytem check cancelled: %s",
1613
if (((mtab = open (_PATH_MOUNTED, O_CREAT | O_TRUNC | O_WRONLY, 0644)) < 0)
1614
|| (close (mtab) < 0))
1617
for (size_t i = 0; i < num_mounts; i++) {
1618
if (! mounts[i].mounted)
1620
if (! mounts[i].type)
1622
if (is_swap (&mounts[i]))
1625
run_mount (&mounts[i], TRUE);
1628
written_mtab = TRUE;
1633
has_showthrough (Mount *root)
1637
nih_assert (root != NULL);
1639
/* Root cannot have showthroughs */
1640
if (! strcmp (root->mountpoint, "/"))
1643
while ((i < num_paths)
1644
&& ((paths[i].mnt != root) || paths[i].device))
1646
nih_assert (i++ < num_paths);
1648
while ((i < num_paths)
1649
&& (! strncmp (paths[i].path, root->mountpoint,
1650
strlen (root->mountpoint)))
1651
&& ((paths[i].path[strlen (root->mountpoint)] == '/')
1652
|| (paths[i].path[strlen (root->mountpoint)] == '\0'))) {
1658
if (! has_option (path->mnt, "showthrough", FALSE))
1660
if (! path->mnt->mounted)
1663
/* Mount option that should show though */
1671
mount_showthrough (Mount *root)
1673
nih_local char * mountpoint = NULL;
1675
nih_local char **args = NULL;
1676
size_t args_len = 0;
1679
nih_assert (root != NULL);
1681
/* Root cannot have showthroughs */
1682
if (! strcmp (root->mountpoint, "/"))
1685
while ((i < num_paths)
1686
&& ((paths[i].mnt != root) || paths[i].device))
1688
nih_assert (i++ < num_paths);
1690
/* This is the mountpoint we actually used */
1691
mountpoint = NIH_MUST (nih_sprintf (NULL, "/dev/%s", root->mountpoint));
1692
for (size_t i = 5; i < strlen (mountpoint); i++)
1693
if (mountpoint[i] == '/')
1694
mountpoint[i] = '.';
1696
while ((i < num_paths)
1697
&& (! strncmp (paths[i].path, root->mountpoint,
1698
strlen (root->mountpoint)))
1699
&& ((paths[i].path[strlen (root->mountpoint)] == '/')
1700
|| (paths[i].path[strlen (root->mountpoint)] == '/'))) {
1702
nih_local char * submount = NULL;
1703
nih_local char **args = NULL;
1704
size_t args_len = 0;
1709
if (! has_option (path->mnt, "showthrough", FALSE))
1711
if (! path->mnt->mounted)
1714
submount = NIH_MUST (nih_sprintf (NULL, "%s%s", mountpoint,
1715
path->mnt->mountpoint + strlen (root->mountpoint)));
1717
args = NIH_MUST (nih_str_array_new (NULL));
1718
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "mount"));
1719
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-n"));
1720
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "--bind"));
1721
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, path->mnt->mountpoint));
1722
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, submount));
1724
nih_debug ("binding %s to %s", path->mnt->mountpoint, submount);
1727
if (spawn (path->mnt, args, TRUE, NULL) < 0)
1734
args = NIH_MUST (nih_str_array_new (NULL));
1735
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "mount"));
1736
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "-n"));
1737
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, "--move"));
1738
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, mountpoint));
1739
NIH_MUST (nih_str_array_add (&args, NULL, &args_len, root->mountpoint));
1741
nih_debug ("moving %s", root->mountpoint);
1743
if (spawn (root, args, TRUE, NULL) < 0)
1746
if ((rmdir (mountpoint) < 0)
1747
&& (errno != EEXIST))
1748
nih_warn ("rmdir %s: %s", mountpoint, strerror (errno));
1754
upstart_disconnected (DBusConnection *connection)
1756
nih_fatal (_("Disconnected from Upstart"));
1757
exit_code = nih_max (exit_code, EXIT_ERROR);
1758
if (NIH_LIST_EMPTY (procs))
1763
emit_event (const char *name)
1765
DBusPendingCall *pending_call;
1766
nih_local char **env = NULL;
1768
nih_assert (name != NULL);
1770
env = NIH_MUST (nih_str_array_new (NULL));
1772
pending_call = NIH_SHOULD (upstart_emit_event (upstart,
1774
NULL, emit_event_error, NULL,
1775
NIH_DBUS_TIMEOUT_NEVER));
1776
if (! pending_call) {
1779
err = nih_error_get ();
1780
nih_warn ("%s", err->message);
1786
dbus_pending_call_unref (pending_call);
1790
emit_event_error (void * data,
1791
NihDBusMessage *message)
1795
err = nih_error_get ();
1796
nih_warn ("%s", err->message);
1802
udev_monitor_watcher (struct udev_monitor *udev_monitor,
1806
struct udev_device * udev_device;
1807
const char * action;
1808
const char * subsystem;
1809
const char * devname;
1814
struct udev_list_entry *devlinks;
1816
udev_device = udev_monitor_receive_device (udev_monitor);
1820
action = udev_device_get_action (udev_device);
1821
subsystem = udev_device_get_subsystem (udev_device);
1822
devname = udev_device_get_devnode (udev_device);
1823
devlinks = udev_device_get_devlinks_list_entry (udev_device);
1824
usage = udev_device_get_property_value (udev_device, "ID_FS_USAGE");
1825
type = udev_device_get_property_value (udev_device, "ID_FS_TYPE");
1826
uuid = udev_device_get_property_value (udev_device, "ID_FS_UUID");
1827
label = udev_device_get_property_value (udev_device, "ID_FS_LABEL");
1830
|| strcmp (subsystem, "block")) {
1831
udev_device_unref (udev_device);
1836
|| (strcmp (action, "add")
1837
&& strcmp (action, "change"))) {
1838
udev_device_unref (udev_device);
1843
|| (strcmp (usage, "filesystem")
1844
&& (strcmp (usage, "other")
1846
|| strcmp (type, "swap")))) {
1847
udev_device_unref (udev_device);
1851
nih_debug ("%s %s %s %s", subsystem, devname, uuid, label);
1853
for (size_t i = 0; i < num_mounts; i++) {
1854
if (! mounts[i].device)
1857
if ((! strncmp (mounts[i].device, "UUID=", 5))
1859
&& (! strcmp (mounts[i].device + 5, uuid))) {
1860
struct udev_list_entry *devlink;
1862
nih_debug ("%s by uuid", mounts[i].mountpoint);
1864
for (devlink = devlinks; devlink;
1865
devlink = udev_list_entry_get_next (devlink)) {
1866
const char *name = udev_list_entry_get_name (devlink);
1868
if (! strncmp (name, "/dev/disk/by-uuid/", 18)) {
1869
update_mount (&mounts[i], name, -1, NULL, NULL, NULL);
1875
update_mount (&mounts[i], devname, -1, NULL, NULL, NULL);
1876
} else if ((! strncmp (mounts[i].device, "LABEL=", 6))
1878
&& (! strcmp (mounts[i].device + 6, label))) {
1879
struct udev_list_entry *devlink;
1881
nih_debug ("%s by label", mounts[i].mountpoint);
1883
for (devlink = devlinks; devlink;
1884
devlink = udev_list_entry_get_next (devlink)) {
1885
const char *name = udev_list_entry_get_name (devlink);
1887
if (! strncmp (name, "/dev/disk/by-label/", 18)) {
1888
update_mount (&mounts[i], name, -1, NULL, NULL, NULL);
1894
update_mount (&mounts[i], devname, -1, NULL, NULL, NULL);
1895
} else if (! strcmp (mounts[i].device, devname)) {
1896
nih_debug ("%s by name", mounts[i].mountpoint);
1898
struct udev_list_entry *devlink;
1900
for (devlink = devlinks; devlink;
1901
devlink = udev_list_entry_get_next (devlink)) {
1902
const char *name = udev_list_entry_get_name (devlink);
1904
if (! strcmp (mounts[i].device, name)) {
1905
nih_debug ("%s by link %s", mounts[i].mountpoint,
1915
if (mounts[i].udev_device)
1916
udev_device_unref (mounts[i].udev_device);
1918
mounts[i].udev_device = udev_device;
1919
udev_device_ref (mounts[i].udev_device);
1921
run_fsck (&mounts[i]);
1924
udev_device_unref (udev_device);
1928
usr1_handler (void * data,
1934
nih_debug ("Received SIGUSR1 (network device up)");
1936
for (size_t i = 0; i < num_mounts; i++)
1937
if (is_remote (&mounts[i])
1938
&& (! mounts[i].mounted))
1939
device_ready (&mounts[i]);
1944
dev_hook (Mount *mnt)
1946
nih_assert (mnt != NULL);
1948
nih_debug ("populating %s", mnt->mountpoint);
1950
int dev_hook_walk (const char * fpath,
1951
const struct stat *sb,
1953
struct FTW * ftwbuf)
1955
char dest[PATH_MAX];
1957
strcpy (dest, mnt->mountpoint);
1958
strcat (dest, fpath + 17);
1960
if (S_ISDIR (sb->st_mode)) {
1961
if ((mkdir (dest, sb->st_mode & ~S_IFMT) < 0)
1962
&& (errno != EEXIST))
1963
nih_warn ("%s: %s", dest, strerror (errno));
1964
} else if (S_ISLNK (sb->st_mode)) {
1965
char target[PATH_MAX];
1968
len = readlink (fpath, target, sizeof target);
1971
if ((symlink (target, dest) < 0)
1972
&& (errno != EEXIST))
1973
nih_warn ("%s: %s", dest, strerror (errno));
1975
if ((mknod (dest, sb->st_mode, sb->st_rdev) < 0)
1976
&& (errno != EEXIST))
1977
nih_warn ("%s: %s", dest, strerror (errno));
1980
return FTW_CONTINUE;
1984
return nftw ("/lib/udev/devices", dev_hook_walk, 1024,
1985
FTW_ACTIONRETVAL | FTW_PHYS | FTW_MOUNT);
1989
tmp_hook (Mount *mnt)
1991
struct stat statbuf;
1995
nih_assert (mnt != NULL);
1997
if ((lstat (mnt->mountpoint, &statbuf) < 0)
1998
|| (! (statbuf.st_mode & S_IWOTH))) {
1999
nih_debug ("cowardly not cleaning up %s", mnt->mountpoint);
2001
} else if (tmptime < 0) {
2002
nih_debug ("not cleaning up %s", mnt->mountpoint);
2006
nih_debug ("cleaning up %s", mnt->mountpoint);
2009
barrier = time (NULL) - (tmptime * 3600);
2015
int tmp_hook_walk (const char * fpath,
2016
const struct stat *sb,
2018
struct FTW * ftwbuf)
2020
const char *name = fpath + ftwbuf->base;
2022
if (! ftwbuf->level)
2023
return FTW_CONTINUE;
2025
if (S_ISDIR (sb->st_mode)) {
2026
if (strcmp (name, "lost+found")
2028
|| ((sb->st_mtime < barrier
2029
&& (sb->st_ctime < barrier)))))
2031
if (rmdir (fpath) < 0)
2032
nih_warn ("%s: %s", fpath, strerror (errno));
2036
if (strcmp (name, "quota.user")
2037
&& strcmp (name, "aquota.user")
2038
&& strcmp (name, "quote.group")
2039
&& strcmp (name, "aquota.group")
2040
&& strcmp (name, ".journal")
2041
&& fnmatch ("...security*", name, FNM_PATHNAME)
2043
|| ((sb->st_mtime < barrier)
2044
&& (sb->st_ctime < barrier)
2045
&& (sb->st_atime < barrier))
2046
|| ((ftwbuf->level == 1)
2047
&& (! fnmatch (".X*-lock", fpath + ftwbuf->base, FNM_PATHNAME)))))
2049
if (unlink (fpath) < 0)
2050
nih_warn ("%s: %s", fpath, strerror (errno));
2055
return FTW_CONTINUE;
2058
return nftw (mnt->mountpoint, tmp_hook_walk, 1024,
2059
FTW_ACTIONRETVAL | FTW_DEPTH | FTW_PHYS | FTW_MOUNT);
2063
var_run_hook (Mount *mnt)
2065
char path[PATH_MAX];
2069
nih_assert (mnt != NULL);
2071
if (nih_main_write_pidfile (getpid ()) < 0) {
2074
err = nih_error_get ();
2075
nih_warn ("%s: %s", nih_main_get_pidfile (), err->message);
2079
nih_debug ("creating %s/utmp", mnt->mountpoint);
2081
strcpy (path, mnt->mountpoint);
2082
strcat (path, "/utmp");
2084
if (((fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, 0664)) < 0)
2085
|| (close (fd) < 0)) {
2086
nih_warn ("%s: %s", path, strerror (errno));
2090
grp = getgrnam ("utmp");
2092
chown (path, 0, grp->gr_gid);
2096
nih_debug ("creating %s/motd", mnt->mountpoint);
2098
strcpy (path, mnt->mountpoint);
2099
strcat (path, "/motd");
2101
fp = fopen (path, "w");
2103
nih_warn ("%s: %s", path, strerror (errno));
2108
fprintf (fp, "%s %s %s %s %s\n",
2109
uts.sysname, uts.nodename, uts.release, uts.version,
2113
if ((fd = open ("/etc/motd.tail", O_RDONLY)) >= 0) {
2117
while ((len = read (fd, buf, sizeof buf)) > 0)
2118
write (fileno (fp), buf, len);
2124
nih_warn ("%s: %s", path, strerror (errno));
2128
nih_debug ("populating %s from initramfs", mnt->mountpoint);
2130
int var_run_hook_walk (const char * fpath,
2131
const struct stat *sb,
2133
struct FTW * ftwbuf)
2135
char dest[PATH_MAX];
2137
strcpy (dest, mnt->mountpoint);
2138
strcat (dest, fpath + 22);
2140
if (S_ISDIR (sb->st_mode)) {
2141
if ((mkdir (dest, sb->st_mode & ~S_IFMT) < 0)
2142
&& (errno != EEXIST))
2143
nih_warn ("%s: %s", dest, strerror (errno));
2144
} else if (S_ISLNK (sb->st_mode)) {
2145
char target[PATH_MAX];
2148
len = readlink (fpath, target, sizeof target);
2151
if ((symlink (target, dest) < 0)
2152
&& (errno != EEXIST))
2153
nih_warn ("%s: %s", dest, strerror (errno));
2160
in_fd = open (fpath, O_RDONLY);
2162
nih_warn ("%s: %s", fpath, strerror (errno));
2163
return FTW_CONTINUE;
2166
out_fd = open (dest, O_WRONLY | O_CREAT | O_TRUNC,
2169
nih_warn ("%s: %s", dest, strerror (errno));
2171
return FTW_CONTINUE;
2174
while ((len = read (in_fd, buf, sizeof buf)) > 0)
2175
write (out_fd, buf, len);
2178
if (close (out_fd) < 0)
2179
nih_warn ("%s: %s", dest, strerror (errno));
2182
return FTW_CONTINUE;
2186
return nftw ("/dev/.initramfs/varrun", var_run_hook_walk, 1024,
2187
FTW_ACTIONRETVAL | FTW_PHYS | FTW_MOUNT);
2192
tmptime_option (NihOption * option,
2197
nih_assert (option != NULL);
2198
nih_assert (option->value != NULL);
2199
nih_assert (arg != NULL);
2201
value = (int *)option->value;
2203
if (strcmp (arg, "infinite")
2204
&& strcmp (arg, "infinity")) {
2205
*value = atoi (arg);
2216
* Command-line options accepted by this program.
2218
static NihOption options[] = {
2219
{ 0, "daemon", N_("Detach and run in the background"),
2220
NULL, NULL, &daemonise, NULL },
2221
{ 0, "force-fsck", N_("Force check of all filesystems"),
2222
NULL, NULL, &force_fsck, NULL },
2223
{ 0, "fsck-fix", N_("Attempt to fix all fsck errors"),
2224
NULL, NULL, &fsck_fix, NULL },
2225
{ 0, "no-remote", N_("Ignore remote filesystems"),
2226
NULL, NULL, &no_remote, NULL },
2227
{ 0, "tmptime", N_("Grace to give files in /tmp"),
2228
NULL, "HOURS", &tmptime, tmptime_option },
2239
DBusConnection * connection;
2241
struct udev_monitor *udev_monitor;
2245
nih_main_init (argv[0]);
2247
nih_option_set_synopsis (_("Mount filesystems on boot"));
2248
nih_option_set_help (
2249
_("By default, mountall does not detach from the "
2250
"console and remains in the foreground. Use the --daemon "
2251
"option to have it detach."));
2253
args = nih_option_parser (NULL, argc, argv, options, FALSE);
2257
nih_signal_reset ();
2259
/* Initialise the connection to Upstart */
2260
connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
2264
err = nih_error_get ();
2265
nih_fatal ("%s: %s", _("Could not connect to Upstart"),
2272
upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
2273
NULL, DBUS_PATH_UPSTART,
2278
err = nih_error_get ();
2279
nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
2286
/* Initialise the connection to udev */
2287
nih_assert (udev = udev_new ());
2288
nih_assert (udev_monitor = udev_monitor_new_from_netlink (udev, "udev"));
2289
nih_assert (udev_monitor_filter_add_match_subsystem_devtype (udev_monitor, "block", NULL) == 0);
2290
nih_assert (udev_monitor_enable_receiving (udev_monitor) == 0);
2292
NIH_MUST (nih_io_add_watch (NULL, udev_monitor_get_fd (udev_monitor),
2294
(NihIoWatcher)udev_monitor_watcher,
2297
/* Initialse mount table with built-in filesystems, then parse
2298
* from /etc/fstab and /proc/self/mountinfo to find out what else
2301
for (builtin = builtins; builtin->mountpoint; builtin++)
2302
new_mount (builtin->mountpoint, builtin->device, builtin->check,
2303
builtin->type, builtin->opts, builtin->hook);
2308
/* Parse /proc/filesystems and eliminate anything we don't know
2309
* about, or anything that's got "noauto" in its options, etc.
2311
parse_filesystems ();
2314
/* Build a path table so we can lookup both children mountpoints
2315
* and devices. Initialise a process list.
2318
procs = NIH_MUST (nih_list_new (NULL));
2320
/* Sanity check, the root filesystem should be already mounted */
2321
root = find_mount ("/");
2322
if (! root->mounted) {
2323
nih_fatal ("%s", _("root filesystem isn't mounted"));
2331
/* Fork once because Upstart makes us a session leader,
2332
* or we may be a session leader of an existing process
2337
nih_fatal ("%s: %s", _("Unable to become daemon"),
2341
} else if (pid > 0) {
2345
/* Create a new session */
2348
/* Fork again so that we're not the leader of that session */
2351
nih_fatal ("%s: %s", _("Unable to become daemon"),
2355
} else if (pid > 0) {
2359
/* Usual daemon cleanups */
2364
/* Send all logging output to syslog */
2365
openlog (program_name, LOG_PID, LOG_DAEMON);
2366
nih_log_set_logger (nih_logger_syslog);
2368
nih_signal_set_ignore (SIGHUP);
2370
nih_signal_set_handler (SIGINT, nih_signal_handler);
2371
NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
2374
nih_signal_set_handler (SIGCHLD, nih_signal_handler);
2376
/* Handle TERM and INT signals gracefully */
2377
nih_signal_set_handler (SIGTERM, nih_signal_handler);
2378
NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
2380
/* SIGUSR1 tells us that a network device came up */
2381
nih_signal_set_handler (SIGUSR1, nih_signal_handler);
2382
NIH_MUST (nih_signal_add_handler (NULL, SIGUSR1, usr1_handler, NULL));
2385
/* All of the mountpoints under the root filesystem are now ready
2386
* for mounting, even though it's still read-only. All of the
2387
* devices will be ready when it's mounted for writing. This means
2388
* we'll mount all of the virtual filesystems.
2390
* Once that's done, mark the root mountpoint itself ready so we
2391
* can remount the root filesystem when the device itself is ready.
2393
children_ready (root, 1);
2394
mountpoint_ready (root);
2396
ret = nih_main_loop ();
2398
nih_main_unlink_pidfile ();