X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=init%2Finitramfs.c;h=d9c941c0c3cacd26fb051059540673b5e011d967;hb=3ddeb51d9c83931c1ca6abf76a38934c5a1ed918;hp=85f04037ade137c6ce452f3183db87527f80e6cf;hpb=2e591bbc0d563e12f5a260fbbca0df7d5810910e;p=safe%2Fjmp%2Flinux-2.6 diff --git a/init/initramfs.c b/init/initramfs.c index 85f0403..d9c941c 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -6,6 +6,7 @@ #include #include #include +#include static __initdata char *message; static void __init error(char *x) @@ -14,16 +15,6 @@ static void __init error(char *x) message = x; } -static void __init *malloc(size_t size) -{ - return kmalloc(size, GFP_KERNEL); -} - -static void __init free(void *where) -{ - kfree(where); -} - /* link hash */ #define N_ALIGN(len) ((((len) + 1) & ~3) + 2) @@ -57,7 +48,7 @@ static char __init *find_link(int major, int minor, int ino, continue; return (*p)->name; } - q = (struct hash *)malloc(sizeof(struct hash)); + q = kmalloc(sizeof(struct hash), GFP_KERNEL); if (!q) panic("can't allocate link hash entry"); q->major = major; @@ -77,11 +68,54 @@ static void __init free_hash(void) while (*p) { q = *p; *p = q->next; - free(q); + kfree(q); } } } +static long __init do_utime(char __user *filename, time_t mtime) +{ + struct timespec t[2]; + + t[0].tv_sec = mtime; + t[0].tv_nsec = 0; + t[1].tv_sec = mtime; + t[1].tv_nsec = 0; + + return do_utimes(AT_FDCWD, filename, t, AT_SYMLINK_NOFOLLOW); +} + +static __initdata LIST_HEAD(dir_list); +struct dir_entry { + struct list_head list; + char *name; + time_t mtime; +}; + +static void __init dir_add(const char *name, time_t mtime) +{ + struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL); + if (!de) + panic("can't allocate dir_entry buffer"); + INIT_LIST_HEAD(&de->list); + de->name = kstrdup(name, GFP_KERNEL); + de->mtime = mtime; + list_add(&de->list, &dir_list); +} + +static void __init dir_utime(void) +{ + struct dir_entry *de, *tmp; + list_for_each_entry_safe(de, tmp, &dir_list, list) { + list_del(&de->list); + do_utime(de->name, de->mtime); + kfree(de->name); + kfree(de); + } +} + +static __initdata time_t mtime; + /* cpio header parsing */ static __initdata unsigned long ino, major, minor, nlink; @@ -107,6 +141,7 @@ static void __init parse_header(char *s) uid = parsed[2]; gid = parsed[3]; nlink = parsed[4]; + mtime = parsed[5]; body_len = parsed[6]; major = parsed[7]; minor = parsed[8]; @@ -133,13 +168,14 @@ static __initdata loff_t this_header, next_header; static __initdata int dry_run; -static inline void eat(unsigned n) +static inline void __init eat(unsigned n) { victim += n; this_header += n; count -= n; } +static __initdata char *vcollected; static __initdata char *collected; static __initdata int remains; static __initdata char *collect; @@ -281,6 +317,8 @@ static int __init do_name(void) if (wfd >= 0) { sys_fchown(wfd, uid, gid); sys_fchmod(wfd, mode); + sys_ftruncate(wfd, body_len); + vcollected = kstrdup(collected, GFP_KERNEL); state = CopyFile; } } @@ -288,12 +326,14 @@ static int __init do_name(void) sys_mkdir(collected, mode); sys_chown(collected, uid, gid); sys_chmod(collected, mode); + dir_add(collected, mtime); } else if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { if (maybe_link() == 0) { sys_mknod(collected, mode, rdev); sys_chown(collected, uid, gid); sys_chmod(collected, mode); + do_utime(collected, mtime); } } return 0; @@ -304,6 +344,8 @@ static int __init do_copy(void) if (count >= body_len) { sys_write(wfd, victim, body_len); sys_close(wfd); + do_utime(vcollected, mtime); + kfree(vcollected); eat(body_len); state = SkipIt; return 0; @@ -321,6 +363,7 @@ static int __init do_symlink(void) clean_path(collected, 0); sys_symlink(collected + N_ALIGN(name_len), collected); sys_lchown(collected, uid, gid); + do_utime(collected, mtime); state = SkipIt; next_state = Reset; return 0; @@ -407,18 +450,10 @@ static long bytes_out; static void __init flush_window(void); static void __init error(char *m); -static void __init gzip_mark(void **); -static void __init gzip_release(void **); -#include "../lib/inflate.c" - -static void __init gzip_mark(void **ptr) -{ -} +#define NO_INFLATE_MALLOC -static void __init gzip_release(void **ptr) -{ -} +#include "../lib/inflate.c" /* =========================================================================== * Write the output window window[0..outcnt-1] and update crc and bytes_out. @@ -445,10 +480,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) { int written; dry_run = check_only; - header_buf = malloc(110); - symlink_buf = malloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1); - name_buf = malloc(N_ALIGN(PATH_MAX)); - window = malloc(WSIZE); + header_buf = kmalloc(110, GFP_KERNEL); + symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); + name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); + window = kmalloc(WSIZE, GFP_KERNEL); if (!window || !header_buf || !symlink_buf || !name_buf) panic("can't allocate buffers"); state = Start; @@ -484,15 +519,26 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) buf += inptr; len -= inptr; } - free(window); - free(name_buf); - free(symlink_buf); - free(header_buf); + dir_utime(); + kfree(window); + kfree(name_buf); + kfree(symlink_buf); + kfree(header_buf); return message; } +static int __initdata do_retain_initrd; + +static int __init retain_initrd_param(char *str) +{ + if (*str) + return 0; + do_retain_initrd = 1; + return 1; +} +__setup("retain_initrd", retain_initrd_param); + extern char __initramfs_start[], __initramfs_end[]; -#ifdef CONFIG_BLK_DEV_INITRD #include #include @@ -501,7 +547,11 @@ static void __init free_initrd(void) #ifdef CONFIG_KEXEC unsigned long crashk_start = (unsigned long)__va(crashk_res.start); unsigned long crashk_end = (unsigned long)__va(crashk_res.end); +#endif + if (do_retain_initrd) + goto skip; +#ifdef CONFIG_KEXEC /* * If the initrd region is overlapped with crashkernel reserved region, * free only memory that is not part of crashkernel region. @@ -519,20 +569,17 @@ static void __init free_initrd(void) } else #endif free_initrd_mem(initrd_start, initrd_end); - +skip: initrd_start = 0; initrd_end = 0; } -#endif - -void __init populate_rootfs(void) +static int __init populate_rootfs(void) { char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start, 0); if (err) panic(err); -#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { #ifdef CONFIG_BLK_DEV_RAM int fd; @@ -544,7 +591,7 @@ void __init populate_rootfs(void) unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start, 0); free_initrd(); - return; + return 0; } printk("it isn't (%s); looks like an initrd\n", err); fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700); @@ -564,5 +611,6 @@ void __init populate_rootfs(void) free_initrd(); #endif } -#endif + return 0; } +rootfs_initcall(populate_rootfs);