diff options
-rw-r--r-- | init/initramfs.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/init/initramfs.c b/init/initramfs.c index 644fc01ad5f0..4f5ba75aaa7c 100644 --- a/init/initramfs.c +++ b/init/initramfs.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
8 | #include <linux/syscalls.h> | 8 | #include <linux/syscalls.h> |
9 | #include <linux/utime.h> | ||
9 | 10 | ||
10 | static __initdata char *message; | 11 | static __initdata char *message; |
11 | static void __init error(char *x) | 12 | static void __init error(char *x) |
@@ -72,6 +73,49 @@ static void __init free_hash(void) | |||
72 | } | 73 | } |
73 | } | 74 | } |
74 | 75 | ||
76 | static long __init do_utime(char __user *filename, time_t mtime) | ||
77 | { | ||
78 | struct timespec t[2]; | ||
79 | |||
80 | t[0].tv_sec = mtime; | ||
81 | t[0].tv_nsec = 0; | ||
82 | t[1].tv_sec = mtime; | ||
83 | t[1].tv_nsec = 0; | ||
84 | |||
85 | return do_utimes(AT_FDCWD, filename, t, AT_SYMLINK_NOFOLLOW); | ||
86 | } | ||
87 | |||
88 | static __initdata LIST_HEAD(dir_list); | ||
89 | struct dir_entry { | ||
90 | struct list_head list; | ||
91 | char *name; | ||
92 | time_t mtime; | ||
93 | }; | ||
94 | |||
95 | static void __init dir_add(const char *name, time_t mtime) | ||
96 | { | ||
97 | struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL); | ||
98 | if (!de) | ||
99 | panic("can't allocate dir_entry buffer"); | ||
100 | INIT_LIST_HEAD(&de->list); | ||
101 | de->name = kstrdup(name, GFP_KERNEL); | ||
102 | de->mtime = mtime; | ||
103 | list_add(&de->list, &dir_list); | ||
104 | } | ||
105 | |||
106 | static void __init dir_utime(void) | ||
107 | { | ||
108 | struct dir_entry *de, *tmp; | ||
109 | list_for_each_entry_safe(de, tmp, &dir_list, list) { | ||
110 | list_del(&de->list); | ||
111 | do_utime(de->name, de->mtime); | ||
112 | kfree(de->name); | ||
113 | kfree(de); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | static __initdata time_t mtime; | ||
118 | |||
75 | /* cpio header parsing */ | 119 | /* cpio header parsing */ |
76 | 120 | ||
77 | static __initdata unsigned long ino, major, minor, nlink; | 121 | static __initdata unsigned long ino, major, minor, nlink; |
@@ -97,6 +141,7 @@ static void __init parse_header(char *s) | |||
97 | uid = parsed[2]; | 141 | uid = parsed[2]; |
98 | gid = parsed[3]; | 142 | gid = parsed[3]; |
99 | nlink = parsed[4]; | 143 | nlink = parsed[4]; |
144 | mtime = parsed[5]; | ||
100 | body_len = parsed[6]; | 145 | body_len = parsed[6]; |
101 | major = parsed[7]; | 146 | major = parsed[7]; |
102 | minor = parsed[8]; | 147 | minor = parsed[8]; |
@@ -130,6 +175,7 @@ static inline void __init eat(unsigned n) | |||
130 | count -= n; | 175 | count -= n; |
131 | } | 176 | } |
132 | 177 | ||
178 | static __initdata char *vcollected; | ||
133 | static __initdata char *collected; | 179 | static __initdata char *collected; |
134 | static __initdata int remains; | 180 | static __initdata int remains; |
135 | static __initdata char *collect; | 181 | static __initdata char *collect; |
@@ -271,6 +317,7 @@ static int __init do_name(void) | |||
271 | if (wfd >= 0) { | 317 | if (wfd >= 0) { |
272 | sys_fchown(wfd, uid, gid); | 318 | sys_fchown(wfd, uid, gid); |
273 | sys_fchmod(wfd, mode); | 319 | sys_fchmod(wfd, mode); |
320 | vcollected = kstrdup(collected, GFP_KERNEL); | ||
274 | state = CopyFile; | 321 | state = CopyFile; |
275 | } | 322 | } |
276 | } | 323 | } |
@@ -278,12 +325,14 @@ static int __init do_name(void) | |||
278 | sys_mkdir(collected, mode); | 325 | sys_mkdir(collected, mode); |
279 | sys_chown(collected, uid, gid); | 326 | sys_chown(collected, uid, gid); |
280 | sys_chmod(collected, mode); | 327 | sys_chmod(collected, mode); |
328 | dir_add(collected, mtime); | ||
281 | } else if (S_ISBLK(mode) || S_ISCHR(mode) || | 329 | } else if (S_ISBLK(mode) || S_ISCHR(mode) || |
282 | S_ISFIFO(mode) || S_ISSOCK(mode)) { | 330 | S_ISFIFO(mode) || S_ISSOCK(mode)) { |
283 | if (maybe_link() == 0) { | 331 | if (maybe_link() == 0) { |
284 | sys_mknod(collected, mode, rdev); | 332 | sys_mknod(collected, mode, rdev); |
285 | sys_chown(collected, uid, gid); | 333 | sys_chown(collected, uid, gid); |
286 | sys_chmod(collected, mode); | 334 | sys_chmod(collected, mode); |
335 | do_utime(collected, mtime); | ||
287 | } | 336 | } |
288 | } | 337 | } |
289 | return 0; | 338 | return 0; |
@@ -294,6 +343,8 @@ static int __init do_copy(void) | |||
294 | if (count >= body_len) { | 343 | if (count >= body_len) { |
295 | sys_write(wfd, victim, body_len); | 344 | sys_write(wfd, victim, body_len); |
296 | sys_close(wfd); | 345 | sys_close(wfd); |
346 | do_utime(vcollected, mtime); | ||
347 | kfree(vcollected); | ||
297 | eat(body_len); | 348 | eat(body_len); |
298 | state = SkipIt; | 349 | state = SkipIt; |
299 | return 0; | 350 | return 0; |
@@ -311,6 +362,7 @@ static int __init do_symlink(void) | |||
311 | clean_path(collected, 0); | 362 | clean_path(collected, 0); |
312 | sys_symlink(collected + N_ALIGN(name_len), collected); | 363 | sys_symlink(collected + N_ALIGN(name_len), collected); |
313 | sys_lchown(collected, uid, gid); | 364 | sys_lchown(collected, uid, gid); |
365 | do_utime(collected, mtime); | ||
314 | state = SkipIt; | 366 | state = SkipIt; |
315 | next_state = Reset; | 367 | next_state = Reset; |
316 | return 0; | 368 | return 0; |
@@ -466,6 +518,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) | |||
466 | buf += inptr; | 518 | buf += inptr; |
467 | len -= inptr; | 519 | len -= inptr; |
468 | } | 520 | } |
521 | dir_utime(); | ||
469 | kfree(window); | 522 | kfree(window); |
470 | kfree(name_buf); | 523 | kfree(name_buf); |
471 | kfree(symlink_buf); | 524 | kfree(symlink_buf); |