1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
/*
* simple init to bootstrap sep-/usr
*
* Copyright (C) 2012-2013 Mike Frysinger <vapier@gentoo.org>
*
* Licensed under GPLv2 or later
*/
//applet:IF_GINIT(APPLET(ginit, BB_DIR_SBIN, BB_SUID_DROP))
//kbuild:lib-$(CONFIG_GINIT) += ginit.o
//config:config GINIT
//config: bool "ginit"
//config: default y
//config: select MKDIR
//config: select MDEV
//config: select MOUNT
//config: select MOUNTPOINT
//config: help
//config: sep-/usr bootstrapper
//usage:#define ginit_trivial_usage NOUSAGE_STR
//usage:#define ginit_full_usage ""
#include "libbb.h"
#define eprintf(fmt, args...) printf("%s" fmt, "sep-usr init: ", ## args)
static void process_args(char **args)
{
size_t i;
eprintf("running: ");
for (i = 0; args[i]; ++i) {
/* String needs to be writable, so dupe it */
args[i] = xstrdup(args[i]);
printf("'%s' ", args[i]);
}
printf("\n");
}
int ginit_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ginit_main(int argc UNUSED_PARAM, char **argv)
{
FILE *mntlist;
bool ismnted_dev, ismnted_sys, ismnted_usr;
struct mntent *mntent;
/*
int fd = open("/dev/console", O_RDWR);
if (fd >= 0) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
*/
/* If given an argv[] with an applet name, run it instead.
* Makes recovering simple by doing: init=/ginit bb
*/
if (argv[1] && argv[1][0] != '/') {
eprintf("running user requested applet %s\n", argv[1]);
return spawn_and_wait(argv+1);
}
#define saw(argv...) \
({ \
static const char *args[] = { argv, NULL }; \
/* These casts are fine -- see process_args for mem setup */ \
process_args((void *)args); \
spawn_and_wait((void *)args); \
})
/* First setup basic /dev */
if (saw("mountpoint", "-q", "/dev") != 0) {
/* Try /etc/fstab */
if (saw("mount", "-n", "/dev"))
/* Then devtmpfs */
if (saw("mount", "-n", "-t", "devtmpfs", "devtmpfs", "/dev"))
/* Finally normal tmpfs */
saw("mount", "-n", "-t", "tmpfs", "dev", "/dev");
} else {
eprintf("%s appears to be mounted; skipping its setup\n", "/dev");
}
/* If /dev is empty (e.g. tmpfs), run mdev to seed things */
if (access("/dev/console", F_OK) != 0) {
if (saw("mountpoint", "-q", "/sys") != 0) {
if (saw("mount", "-n", "/sys"))
saw("mount", "-n", "-t", "sysfs", "sysfs", "/sys");
} else {
eprintf("%s appears to be mounted; skipping its setup\n", "/sys");
}
/* Mount /proc as mdev will fork+exec /proc/self/exe */
if (saw("mountpoint", "-q", "/proc") != 0) {
/* Try /etc/fstab */
if (saw("mount", "-n", "/proc"))
saw("mount", "-n", "-t", "proc", "proc", "/proc");
}
saw("mdev", "-s");
}
/* Then seed the stuff we care about */
saw("mkdir", "-p", "/dev/pts", "/dev/shm");
/* Then mount /usr */
if (saw("mountpoint", "-q", "/usr") != 0) {
saw("mount", "-n", "/usr", "-o", "ro");
} else {
eprintf("%s appears to be mounted; skipping its setup\n", "/usr");
}
/* Now that we're all done, exec the real init */
if (!argv[1]) {
argv[0] = (void *)"/sbin/init";
argv[1] = NULL;
} else
++argv;
process_args(argv);
return execv(argv[0], argv);
}
|