Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 658 lines (532 sloc) 15.234 kb
418495e @falconindy initial commit. works for me!
authored
1 #define _GNU_SOURCE
2 #include <ctype.h>
3 #include <dirent.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <getopt.h>
7 #include <limits.h>
8 #include <linux/magic.h>
9 #include <signal.h>
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/mount.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include <sys/vfs.h>
18 #include <sys/wait.h>
19 #include <unistd.h>
20
21 /* util-linux */
22 #include <blkid.h>
23
24 #define msg(...) {if (!quiet) fprintf(stderr, ":: " __VA_ARGS__);}
25 #define err(...) {fprintf(stderr, "error" __VA_ARGS__);}
26 #define die(...) {err(__VA_ARGS__); _exit(1);}
27
2567d96 @falconindy new NEWROOT in place of hardcoded path
authored
28 #define TMPFS_FLAGS MS_NOEXEC|MS_NODEV|MS_NOSUID
29 #define NEWROOT "/new_root"
418495e @falconindy initial commit. works for me!
authored
30 #define UDEVD_PATH "/sbin/udevd"
99b14a4 @falconindy wrap at 80 cols
authored
31 #define CMDLINE_SIZE 2048 /* from arch/x86/include/asm/setup.h */
418495e @falconindy initial commit. works for me!
authored
32
33 int rootflags = 0;
34 int quiet = 0;
35
36 /* utility */
37 static void forkexecwait(char **argv) { /* {{{ */
38 pid_t pid;
4b5d25d @falconindy cleanup scoping and compiler warnings
authored
39 int statloc;
418495e @falconindy initial commit. works for me!
authored
40
41 pid = fork();
42 if (pid == -1) {
43 perror("fork");
44 return;
45 }
46
47 if (pid == 0) {
4b5d25d @falconindy cleanup scoping and compiler warnings
authored
48 int errsv;
418495e @falconindy initial commit. works for me!
authored
49 execv(argv[0], argv);
949ba05 @falconindy refactor bbox launching into forkexecwait
authored
50 errsv = errno;
51 fprintf(stderr, "failed to launch %s\n", argv[0]);
52 errno = errsv;
53 perror("");
418495e @falconindy initial commit. works for me!
authored
54 }
55
949ba05 @falconindy refactor bbox launching into forkexecwait
authored
56 /* block for process exit */
418495e @falconindy initial commit. works for me!
authored
57 waitpid(pid, &statloc, 0);
58
59 return;
60 } /* }}} */
61
b1811bb @falconindy refactor xasprintf and last_char_is into concat_path
authored
62 static char *concat_path(const char *path, const char *filename) { /* {{{ */
63 const char *ss, *lc;
64 char *concat;
65 int ret;
418495e @falconindy initial commit. works for me!
authored
66
67 if (!path) {
68 path = "";
69 }
70
b1811bb @falconindy refactor xasprintf and last_char_is into concat_path
authored
71 for (ss = path; *ss; ss++);
72 lc = (*--ss == '/' ? "" : "/");
73
418495e @falconindy initial commit. works for me!
authored
74 while (*filename == '/') {
75 filename++;
76 }
b1811bb @falconindy refactor xasprintf and last_char_is into concat_path
authored
77
78 ret = asprintf(&concat, "%s%s%s", path, lc, filename);
79 if (ret < 0) {
80 return NULL;
81 }
82
83 return concat;
418495e @falconindy initial commit. works for me!
authored
84 } /* }}} */
85
86 static char *sanitize_var(char *var) { /* {{{ */
87 char *p;
88
89 p = var;
7a35dc6 @falconindy be stricter about accepting environment vars
authored
90 if (!(isalpha(*p) || *p == '_')) {
91 /* invalid var name, can't use this */
418495e @falconindy initial commit. works for me!
authored
92 return NULL;
93 }
94
7a35dc6 @falconindy be stricter about accepting environment vars
authored
95 p++;
418495e @falconindy initial commit. works for me!
authored
96 while (*p) {
97 switch (*p) {
98 case '-': /* fallthrough */
99 case '.':
100 *p = '_';
101 break;
102 case '=': /* don't touch anything past this */
103 return var;
104 }
105 p++;
106 }
107
108 return var;
109 } /* }}} */
110
111 static void delete_contents(const char *directory, dev_t rootdev) { /* {{{ */
112 DIR *dir;
113 struct dirent *d;
114 struct stat st;
115
116 /* Don't descend into other filesystems */
117 if (lstat(directory, &st) || st.st_dev != rootdev) {
118 return;
119 }
120
121 /* Recursively delete the contents of directories */
122 if (S_ISDIR(st.st_mode)) {
123 dir = opendir(directory);
124 if (dir) {
125 while ((d = readdir(dir))) {
126 char *newdir = d->d_name;
127
128 /* Skip . and .. */
129 if (strcmp(newdir, ".") == 0 || strcmp(newdir, "..") == 0) {
130 continue;
131 }
132
133 /* Recurse to delete contents */
b1811bb @falconindy refactor xasprintf and last_char_is into concat_path
authored
134 newdir = concat_path(directory, newdir);
418495e @falconindy initial commit. works for me!
authored
135 delete_contents(newdir, rootdev);
136 free(newdir);
137 }
138 closedir(dir);
139
140 /* Directory should now be empty, zap it */
141 rmdir(directory);
142 }
143 } else {
144 /* It wasn't a directory, zap it */
145 unlink(directory);
146 }
147 } /* }}} */
148
149 static void start_rescue_shell(void) { /* {{{ */
150 char *bboxinstall[] = { "/bin/busybox", "--install", NULL };
151 char *bboxlaunch[] = { "/bin/busybox", "ash", NULL };
152
153 /* install symlinks */
949ba05 @falconindy refactor bbox launching into forkexecwait
authored
154 forkexecwait(bboxinstall);
418495e @falconindy initial commit. works for me!
authored
155
156 /* set a prompt */
157 putenv("PS1=[ramfs \\W]\\$ ");
158
159 /* start the shell */
949ba05 @falconindy refactor bbox launching into forkexecwait
authored
160 forkexecwait(bboxlaunch);
418495e @falconindy initial commit. works for me!
authored
161
162 } /* }}} */
163
4b5d25d @falconindy cleanup scoping and compiler warnings
authored
164 static char *probe_fstype(const char *devname) { /* {{{ */
418495e @falconindy initial commit. works for me!
authored
165 int ret;
166 char *fstype;
167 blkid_probe pr;
168
169 pr = blkid_new_probe_from_filename(devname);
170 if (!pr) {
171 err("%s: failed to create a new libblkid probe\n", devname);
172 return NULL;
173 }
174
175 blkid_probe_enable_superblocks(pr, 1);
176 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE);
177
178 ret = blkid_do_safeprobe(pr);
179 if (ret == -1) {
180 return NULL;
181 } else if (ret == 1) {
182 err("failed to probe device %s\n", devname);
183 return NULL;
184 } else {
185 const char *name, *data;
186 blkid_probe_get_value(pr, 0, &name, &data, NULL);
187 fstype = strdup(data);
188 }
189
190 blkid_free_probe(pr);
191
192 return fstype;
193 } /* }}} */
194
195 /* meat */
196 static void mount_setup(void) { /* {{{ */
197 int ret;
198
199 /* setup basic filesystems */
99b14a4 @falconindy wrap at 80 cols
authored
200 mount("proc", "/proc", "proc", TMPFS_FLAGS, NULL);
201 mount("sys", "/sys", "sysfs", TMPFS_FLAGS, NULL);
202 mount("tmpfs", "/run", "tmpfs", TMPFS_FLAGS, "mode=1777,size=10M");
418495e @falconindy initial commit. works for me!
authored
203
204 /* mountpoint for our eventual real root */
2567d96 @falconindy new NEWROOT in place of hardcoded path
authored
205 mkdir(NEWROOT, 0755);
418495e @falconindy initial commit. works for me!
authored
206
207 /* ENODEV returned on non-existant FS */
208 ret = mount("udev", "/dev", "devtmpfs", MS_NOSUID, "mode=0755,size=10M");
209 if (ret == -1 && errno == ENODEV) {
210 /* devtmpfs not available, use standard tmpfs */
211 mount("udev", "/dev", "tmpfs", MS_NOSUID, "mode=0755,size=10M");
212
213 /* create necessary nodes
214 * crw------- 1 root root 5, 1 Apr 2 18:30 /dev/console
215 * crw-rw-rw- 1 root root 1, 3 Apr 2 18:30 /dev/null
216 * crw-rw-rw- 1 root root 1, 5 Apr 2 18:30 /dev/zero
217 */
218 mknod("/dev/console", S_IFCHR|0600, makedev(5, 1));
219 mknod("/dev/null", S_IFCHR|0666, makedev(1, 3));
220 mknod("/dev/zero", S_IFCHR|0666, makedev(1, 5));
221 }
222 } /* }}} */
223
224 static void put_cmdline(void) { /* {{{ */
225 char cmdline[CMDLINE_SIZE], token[CMDLINE_SIZE];
226 char quoted = '\0';
227 char *c, *tp;
228 int isvar = 0;
229 FILE *fp;
230
231 /* a bit of pointer/var hell going on...
4b5d25d @falconindy cleanup scoping and compiler warnings
authored
232 * c = pointer along contents of /proc/cmdline
233 * token = container for current token being parsed
234 * tp = pointer along contents of token
418495e @falconindy initial commit. works for me!
authored
235 */
236
237 fp = fopen("/proc/cmdline", "r");
238 if (!fp) {
239 return;
240 }
241
242 if (!fgets(cmdline, CMDLINE_SIZE, fp)) {
243 return;
244 }
245 fclose(fp);
246
247 tp = token;
248 for (c = cmdline; *c; c++) {
249 if (*c == '#') { /* full stop! */
250 break;
251 }
252
253 if (isspace((unsigned char)*c)) {
254 /* don't break inside a quoted region */
255 if (!quoted && tp != token) {
256 *tp = '\0';
257 if (sanitize_var(token)) {
258 if (isvar) {
259 putenv(strdup(token));
260 } else {
261 setenv(strdup(token), "y", 1);
262 }
263 if (strcmp(token, "ro") == 0) {
264 rootflags |= MS_RDONLY;
265 } else if (strcmp(token, "quiet") == 0) {
266 quiet = 1;
267 }
268 }
269 isvar = 0;
270 tp = token;
271 }
272 continue;
273 } else if (*c == '\'' || *c == '"') {
274 if (quoted) {
275 if (quoted == *c) {
276 quoted = '\0';
277 continue;
278 }
279 } else {
280 quoted = *c;
281 continue;
282 }
283 }
284
285 if (*c == '=') {
286 isvar = 1;
287 }
288
289 *tp++ = *c;
290 }
291 } /* }}} */
292
293 static void disable_modules(void) { /* {{{ */
294 char *tok, *var;
295 FILE *fp;
296
297 if (getenv("disablemodules") == NULL) {
298 return;
299 }
300
301 /* ensure parent dirs exist */
302 mkdir("/etc", 0755);
303 mkdir("/etc/modprobe.d", 0755);
304
305 fp = fopen("/etc/modprobe.d/initcpio.conf", "w");
306 if (!fp) {
307 perror("error: /etc/modprobe.d/initcpio.conf");
308 return;
309 }
310
311 var = strdup(getenv("disablemodules"));
312 for (tok = strtok(var, ","); tok; tok = strtok(NULL, ",")) {
313 fprintf(fp, "install %s /bin/false\n", tok);
314 }
315
316 fclose(fp);
317 free(var);
318 } /* }}} */
319
320 static pid_t launch_udev(void) { /* {{{ */
321 char *udev_argv[] = { UDEVD_PATH, UDEVD_PATH, "--resolve-names=never", NULL };
322 pid_t pid;
323
324 if (access(UDEVD_PATH, X_OK) != 0) {
325 return 0;
326 }
327
328 msg("Starting udev...\n");
329
330 pid = fork();
331 if (pid == -1) {
332 perror("fork");
333 return 1;
334 }
335
336 if (pid == 0) {
337 execv(UDEVD_PATH, udev_argv);
338 perror("exec: " UDEVD_PATH);
339 }
340
341 return pid;
342 } /* }}} */
343
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
344 static void load_extra_modules(void) { /* {{{ */
345 FILE *fp;
418495e @falconindy initial commit. works for me!
authored
346 char *tok, *var;
347 char **argv;
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
348 char line[PATH_MAX];
418495e @falconindy initial commit. works for me!
authored
349 int modcount = 2;
350
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
351 /* load early modules */
352 if (getenv("earlymodules") != NULL) {
353 argv = calloc(2, sizeof(argv));
354 *argv = "/sbin/modprobe";
355 *(argv + 1) = "-qa";
418495e @falconindy initial commit. works for me!
authored
356
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
357 var = strdup(getenv("earlymodules"));
358 for (tok = strtok(var, ","); tok; tok = strtok(NULL, ",")) {
359 argv = realloc(argv, sizeof(argv) * ++modcount);
360 *(argv + (modcount - 1)) = tok;
361 }
418495e @falconindy initial commit. works for me!
authored
362
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
363 if (modcount > 2) {
364 argv = realloc(argv, sizeof(argv) * ++modcount);
365 *(argv + (modcount - 1)) = NULL;
366 forkexecwait(argv);
367 }
368 free(argv);
418495e @falconindy initial commit. works for me!
authored
369 }
370
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
371 /* load modules from /config */
372 fp = fopen("/config", "r");
373 if (fp) {
374 while (fgets(line, PATH_MAX, fp) != NULL) {
375 if (strncmp(line, "MODULES=", 8) == 0) {
376 argv = calloc(2, sizeof(argv));
377 *argv = "/sbin/modprobe";
378 *(argv + 1) = "-qa";
379 modcount = 2;
380
381 for (tok = strtok(&line[9], " \"\n"); tok; tok = strtok(NULL, " \"\n")) {
382 argv = realloc(argv, sizeof(argv) * ++modcount);
383 *(argv + (modcount - 1)) = tok;
384 }
418495e @falconindy initial commit. works for me!
authored
385
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
386 /* make sure array wasn't empty */
387 if (modcount > 2) {
388 argv = realloc(argv, sizeof(argv) * ++modcount);
389 *(argv + (modcount - 1)) = NULL;
390 forkexecwait(argv);
391 }
392
393 free(argv);
394 break;
395 }
396 }
397 fclose(fp);
398 }
418495e @falconindy initial commit. works for me!
authored
399
400 } /* }}} */
401
402 static void trigger_udev_events(void) { /* {{{ */
403 char *argv[] = { "/sbin/udevadm", "trigger", "--action=add", NULL };
3664974 @falconindy add missing udev msg
authored
404
405 msg("triggering udev events...\n");
418495e @falconindy initial commit. works for me!
authored
406 forkexecwait(argv);
407 } /* }}} */
408
409 static void disable_hooks(void) { /* {{{ */
410 char *hook, *list, *disable;
411
412 disable = getenv("disablehooks");
413 if (!disable) {
414 return;
415 }
416
417 list = strdup(disable);
418 for (hook = strtok(list, ", "); hook; hook = strtok(NULL, ", ")) {
419 char path[PATH_MAX];
420 snprintf(path, PATH_MAX, "/hooks/%s", hook);
421
422 /* mark as non-executable so run_hooks skips over it */
423 chmod(path, 0644);
424 }
425
426 free(list);
427 } /* }}} */
428
4b5d25d @falconindy cleanup scoping and compiler warnings
authored
429 static void run_hooks(void) { /* {{{ */
418495e @falconindy initial commit. works for me!
authored
430 FILE *fp;
431 char line[PATH_MAX];
432 char *hook;
433
434 fp = fopen("/config", "r");
435 if (!fp) {
436 return;
437 }
438
439 while (fgets(line, PATH_MAX, fp) != NULL) {
440 if (strncmp(line, "HOOKS=", 6) != 0) {
441 continue;
442 }
443
99b14a4 @falconindy wrap at 80 cols
authored
444 for (hook = strtok(&line[6], " \"\n"); hook; hook = strtok(NULL, " \"\n")) {
418495e @falconindy initial commit. works for me!
authored
445 char path[PATH_MAX];
446
447 snprintf(path, 4096, "hooks/%s", hook);
448
449 if (access(path, X_OK) != 0) {
450 continue;
451 }
452
453 char *argv[] = { path, path, NULL };
454 forkexecwait(argv);
455 }
456 }
457 } /* }}} */
458
a681c38 @falconindy add support for a user requested rescue_shell via "break"
authored
459 static void check_for_break(void) { /* {{{ */
460 if (getenv("break") == NULL) {
461 return;
462 }
463
464 msg("break requested. type 'exit' or 'logout' to resume\n");
465 start_rescue_shell();
466 } /* }}} */
467
418495e @falconindy initial commit. works for me!
authored
468 static void wait_for_root(void) { /* {{{ */
469 char *rootdelay, *root;
470 int found = 0, delay = 0;
471
472 rootdelay = getenv("rootdelay");
473 if (rootdelay) {
474 delay = atoi(rootdelay);
475 }
476
477 if (delay == 0) {
478 delay = 10;
479 }
480
481 root = getenv("root");
482
483 msg("waiting up to %d seconds for %s ...\n", delay, root);
484 while (delay--) {
485 if (access(root, R_OK) == 0) {
486 found = 1;
487 break;
488 }
489 sleep(1);
490 }
491
492 if (!found) {
493 err("root didn't show up! You are on your own, good luck\n");
494 start_rescue_shell();
495 msg("continuing... this will probably fail\n");
496 }
497
498 } /* }}} */
499
500 static void mount_root(void) { /* {{{ */
501 char *root, *fstype;
502 struct stat st;
503
504 root = getenv("root");
505 if (!root) {
506 err("root is undefined!\n");
507 return;
508 }
509
510 if (stat(root, &st) != 0) {
6f97e2b @falconindy always show continuation after leaving bbox.
authored
511 err("failed to stat root!\n");
418495e @falconindy initial commit. works for me!
authored
512 return;
513 }
514
515 fstype = probe_fstype(root);
516 if (!fstype) {
517 /* should never reach this */
518 err("zomg unknown FS!\n");
519 return;
520 }
521
2567d96 @falconindy new NEWROOT in place of hardcoded path
authored
522 if (mount(root, NEWROOT, fstype, rootflags, NULL) != 0) {
418495e @falconindy initial commit. works for me!
authored
523 err("failed to mount new root!\n");
524 }
525 free(fstype);
526 } /* }}} */
527
528 static char *find_init(void) { /* {{{ */
529 char *init;
530 char path[PATH_MAX];
531
532 init = getenv("init");
533 if (!init) {
534 init = "/sbin/init";
535 }
536
2567d96 @falconindy new NEWROOT in place of hardcoded path
authored
537 snprintf(path, PATH_MAX, NEWROOT "%s", init);
418495e @falconindy initial commit. works for me!
authored
538 if (access(path, R_OK) != 0) {
99b14a4 @falconindy wrap at 80 cols
authored
539 err("root is mounted, but '%s' is not found! Bailing to a rescue shell."
540 "Good luck!\n", init);
418495e @falconindy initial commit. works for me!
authored
541 start_rescue_shell();
6f97e2b @falconindy always show continuation after leaving bbox.
authored
542 err("continuing... \n");
418495e @falconindy initial commit. works for me!
authored
543 }
544
545 return init;
546 } /* }}} */
547
548 static void kill_udev(pid_t pid) { /* {{{ */
549 char path[PATH_MAX];
550 char *exe;
551
552 if (pid <= 1) { /* error launching udev */
553 return;
554 }
555
556 snprintf(path, PATH_MAX, "/proc/%d/exe", pid);
557 exe = realpath(path, NULL);
558
559 if (strcmp(exe, UDEVD_PATH) == 0) {
560 kill(pid, SIGTERM);
561 }
562
563 free(exe);
564 } /*}}}*/
565
566 static int switch_root(char *argv[]) { /* {{{ */
567 struct stat st;
568 struct statfs stfs;
569 dev_t rootdev;
570
571 /* this is mostly taken from busybox's util_linux/switch_root.c */
572
573 /* Change to new root directory and verify it's a different fs */
2567d96 @falconindy new NEWROOT in place of hardcoded path
authored
574 chdir(NEWROOT);
418495e @falconindy initial commit. works for me!
authored
575 stat("/", &st);
576 rootdev = st.st_dev;
577 stat(".", &st);
578
579 if (st.st_dev == rootdev) {
2567d96 @falconindy new NEWROOT in place of hardcoded path
authored
580 die("nothing was mounted on " NEWROOT "!\n");
418495e @falconindy initial commit. works for me!
authored
581 }
582
583 /* Additional sanity checks: we're about to rm -rf /, so be REALLY SURE we
584 * mean it. I could make this a CONFIG option, but I would get email from all
585 * the people who WILL destroy their filesystems. */
586 if (stat("/init", &st) != 0 || !S_ISREG(st.st_mode)) {
587 err("/init not found or not a regular file\n");
588 start_rescue_shell();
589 }
590
591 statfs("/", &stfs); /* this never fails */
99b14a4 @falconindy wrap at 80 cols
authored
592 if ((unsigned)stfs.f_type != RAMFS_MAGIC &&
593 (unsigned)stfs.f_type != TMPFS_MAGIC) {
418495e @falconindy initial commit. works for me!
authored
594 die("root filesystem is not ramfs/tmpfs\n");
595 }
596
597 /* zap everything out of rootdev */
598 delete_contents("/", rootdev);
599
600 /* mount $PWD over / and chroot into it */
601 if (mount(".", "/", NULL, MS_MOVE, NULL) != 0) {
602 /* fails when newroot is not a mountpoint */
603 die("error moving root\n");
604 }
605 chroot(".");
606
607 /* The chdir is needed to recalculate "." and ".." links */
608 chdir("/");
609
610 /* redirect stdin/stdout/stderr to new console */
611 close(0);
612 open("/dev/console", O_RDWR);
613 dup2(0, 1);
614 dup2(0, 2);
615
6577f64 @falconindy add bailout message after failed pid 1 exec
authored
616 /* exec real pid shady */
418495e @falconindy initial commit. works for me!
authored
617 execv(argv[0], argv);
6577f64 @falconindy add bailout message after failed pid 1 exec
authored
618 err("failed to execute '%s'\n", argv[0]);
99b14a4 @falconindy wrap at 80 cols
authored
619 fprintf(stderr, ":: This is the end. Something has gone terribly wrong.\n"
620 ":: Please file a detailed bug report.\n");
6577f64 @falconindy add bailout message after failed pid 1 exec
authored
621 _exit(EXIT_FAILURE);
418495e @falconindy initial commit. works for me!
authored
622 } /* }}} */
623
624 int main(int argc, char *argv[]) {
625 char *init;
626 pid_t udevpid;
627
6577f64 @falconindy add bailout message after failed pid 1 exec
authored
628 (void)argc; /* poor unloved argc */
418495e @falconindy initial commit. works for me!
authored
629
630 /* need some actual error checking throughout here */
631
632 mount_setup(); /* create early tmpfs mountpoints */
633 put_cmdline(); /* parse cmdline and set environment */
634 disable_modules(); /* blacklist modules passed in on cmdline */
635 udevpid = launch_udev(); /* try to launch udev */
4cbca7f @falconindy parse MODULES declaration out config file. fix a bug or two along the wa...
authored
636 load_extra_modules(); /* load modules passed in on cmdline */
418495e @falconindy initial commit. works for me!
authored
637 trigger_udev_events(); /* read and process uevent queue */
638 disable_hooks(); /* delete hooks specified on cmdline */
639 run_hooks(); /* run remaining hooks */
a681c38 @falconindy add support for a user requested rescue_shell via "break"
authored
640 check_for_break(); /* did the user request a shell? */
418495e @falconindy initial commit. works for me!
authored
641 wait_for_root(); /* ensure that root shows up */
642 mount_root(); /* this better work... */
643 init = find_init(); /* mounted something, now find init */
644 kill_udev(udevpid); /* shutdown udev in prep switch_root */
645
646 /* move mount points (fstype, options and flags are ignored) */
2567d96 @falconindy new NEWROOT in place of hardcoded path
authored
647 mount("/proc", NEWROOT "/proc", NULL, MS_MOVE, NULL);
648 mount("/sys", NEWROOT "/sys", NULL, MS_MOVE, NULL);
649 mount("/run", NEWROOT "/run", NULL, MS_MOVE, NULL);
418495e @falconindy initial commit. works for me!
authored
650
651 argv[0] = init;
652 switch_root(argv);
6577f64 @falconindy add bailout message after failed pid 1 exec
authored
653 /* unreached */
418495e @falconindy initial commit. works for me!
authored
654 return 0;
655 }
656
657 /* vim: set et ts=2 sw=2 */
Something went wrong with that request. Please try again.