diff options
Diffstat (limited to 'init/initramfs.c')
-rw-r--r-- | init/initramfs.c | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/init/initramfs.c b/init/initramfs.c index d9c941c0c3ca..d3c56fcb30b8 100644 --- a/init/initramfs.c +++ b/init/initramfs.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/fcntl.h> | 5 | #include <linux/fcntl.h> |
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
8 | #include <linux/dirent.h> | ||
8 | #include <linux/syscalls.h> | 9 | #include <linux/syscalls.h> |
9 | #include <linux/utime.h> | 10 | #include <linux/utime.h> |
10 | 11 | ||
@@ -166,8 +167,6 @@ static __initdata char *victim; | |||
166 | static __initdata unsigned count; | 167 | static __initdata unsigned count; |
167 | static __initdata loff_t this_header, next_header; | 168 | static __initdata loff_t this_header, next_header; |
168 | 169 | ||
169 | static __initdata int dry_run; | ||
170 | |||
171 | static inline void __init eat(unsigned n) | 170 | static inline void __init eat(unsigned n) |
172 | { | 171 | { |
173 | victim += n; | 172 | victim += n; |
@@ -229,10 +228,6 @@ static int __init do_header(void) | |||
229 | parse_header(collected); | 228 | parse_header(collected); |
230 | next_header = this_header + N_ALIGN(name_len) + body_len; | 229 | next_header = this_header + N_ALIGN(name_len) + body_len; |
231 | next_header = (next_header + 3) & ~3; | 230 | next_header = (next_header + 3) & ~3; |
232 | if (dry_run) { | ||
233 | read_into(name_buf, N_ALIGN(name_len), GotName); | ||
234 | return 0; | ||
235 | } | ||
236 | state = SkipIt; | 231 | state = SkipIt; |
237 | if (name_len <= 0 || name_len > PATH_MAX) | 232 | if (name_len <= 0 || name_len > PATH_MAX) |
238 | return 0; | 233 | return 0; |
@@ -303,8 +298,6 @@ static int __init do_name(void) | |||
303 | free_hash(); | 298 | free_hash(); |
304 | return 0; | 299 | return 0; |
305 | } | 300 | } |
306 | if (dry_run) | ||
307 | return 0; | ||
308 | clean_path(collected, mode); | 301 | clean_path(collected, mode); |
309 | if (S_ISREG(mode)) { | 302 | if (S_ISREG(mode)) { |
310 | int ml = maybe_link(); | 303 | int ml = maybe_link(); |
@@ -476,10 +469,9 @@ static void __init flush_window(void) | |||
476 | outcnt = 0; | 469 | outcnt = 0; |
477 | } | 470 | } |
478 | 471 | ||
479 | static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | 472 | static char * __init unpack_to_rootfs(char *buf, unsigned len) |
480 | { | 473 | { |
481 | int written; | 474 | int written; |
482 | dry_run = check_only; | ||
483 | header_buf = kmalloc(110, GFP_KERNEL); | 475 | header_buf = kmalloc(110, GFP_KERNEL); |
484 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); | 476 | symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); |
485 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); | 477 | name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); |
@@ -574,10 +566,57 @@ skip: | |||
574 | initrd_end = 0; | 566 | initrd_end = 0; |
575 | } | 567 | } |
576 | 568 | ||
569 | #define BUF_SIZE 1024 | ||
570 | static void __init clean_rootfs(void) | ||
571 | { | ||
572 | int fd; | ||
573 | void *buf; | ||
574 | struct linux_dirent64 *dirp; | ||
575 | int count; | ||
576 | |||
577 | fd = sys_open("/", O_RDONLY, 0); | ||
578 | WARN_ON(fd < 0); | ||
579 | if (fd < 0) | ||
580 | return; | ||
581 | buf = kzalloc(BUF_SIZE, GFP_KERNEL); | ||
582 | WARN_ON(!buf); | ||
583 | if (!buf) { | ||
584 | sys_close(fd); | ||
585 | return; | ||
586 | } | ||
587 | |||
588 | dirp = buf; | ||
589 | count = sys_getdents64(fd, dirp, BUF_SIZE); | ||
590 | while (count > 0) { | ||
591 | while (count > 0) { | ||
592 | struct stat st; | ||
593 | int ret; | ||
594 | |||
595 | ret = sys_newlstat(dirp->d_name, &st); | ||
596 | WARN_ON_ONCE(ret); | ||
597 | if (!ret) { | ||
598 | if (S_ISDIR(st.st_mode)) | ||
599 | sys_rmdir(dirp->d_name); | ||
600 | else | ||
601 | sys_unlink(dirp->d_name); | ||
602 | } | ||
603 | |||
604 | count -= dirp->d_reclen; | ||
605 | dirp = (void *)dirp + dirp->d_reclen; | ||
606 | } | ||
607 | dirp = buf; | ||
608 | memset(buf, 0, BUF_SIZE); | ||
609 | count = sys_getdents64(fd, dirp, BUF_SIZE); | ||
610 | } | ||
611 | |||
612 | sys_close(fd); | ||
613 | kfree(buf); | ||
614 | } | ||
615 | |||
577 | static int __init populate_rootfs(void) | 616 | static int __init populate_rootfs(void) |
578 | { | 617 | { |
579 | char *err = unpack_to_rootfs(__initramfs_start, | 618 | char *err = unpack_to_rootfs(__initramfs_start, |
580 | __initramfs_end - __initramfs_start, 0); | 619 | __initramfs_end - __initramfs_start); |
581 | if (err) | 620 | if (err) |
582 | panic(err); | 621 | panic(err); |
583 | if (initrd_start) { | 622 | if (initrd_start) { |
@@ -585,13 +624,15 @@ static int __init populate_rootfs(void) | |||
585 | int fd; | 624 | int fd; |
586 | printk(KERN_INFO "checking if image is initramfs..."); | 625 | printk(KERN_INFO "checking if image is initramfs..."); |
587 | err = unpack_to_rootfs((char *)initrd_start, | 626 | err = unpack_to_rootfs((char *)initrd_start, |
588 | initrd_end - initrd_start, 1); | 627 | initrd_end - initrd_start); |
589 | if (!err) { | 628 | if (!err) { |
590 | printk(" it is\n"); | 629 | printk(" it is\n"); |
591 | unpack_to_rootfs((char *)initrd_start, | ||
592 | initrd_end - initrd_start, 0); | ||
593 | free_initrd(); | 630 | free_initrd(); |
594 | return 0; | 631 | return 0; |
632 | } else { | ||
633 | clean_rootfs(); | ||
634 | unpack_to_rootfs(__initramfs_start, | ||
635 | __initramfs_end - __initramfs_start); | ||
595 | } | 636 | } |
596 | printk("it isn't (%s); looks like an initrd\n", err); | 637 | printk("it isn't (%s); looks like an initrd\n", err); |
597 | fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); | 638 | fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); |
@@ -604,7 +645,7 @@ static int __init populate_rootfs(void) | |||
604 | #else | 645 | #else |
605 | printk(KERN_INFO "Unpacking initramfs..."); | 646 | printk(KERN_INFO "Unpacking initramfs..."); |
606 | err = unpack_to_rootfs((char *)initrd_start, | 647 | err = unpack_to_rootfs((char *)initrd_start, |
607 | initrd_end - initrd_start, 0); | 648 | initrd_end - initrd_start); |
608 | if (err) | 649 | if (err) |
609 | panic(err); | 650 | panic(err); |
610 | printk(" done\n"); | 651 | printk(" done\n"); |