aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--init/initramfs.c53
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
10static __initdata char *message; 11static __initdata char *message;
11static void __init error(char *x) 12static void __init error(char *x)
@@ -72,6 +73,49 @@ static void __init free_hash(void)
72 } 73 }
73} 74}
74 75
76static 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
88static __initdata LIST_HEAD(dir_list);
89struct dir_entry {
90 struct list_head list;
91 char *name;
92 time_t mtime;
93};
94
95static 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
106static 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
117static __initdata time_t mtime;
118
75/* cpio header parsing */ 119/* cpio header parsing */
76 120
77static __initdata unsigned long ino, major, minor, nlink; 121static __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
178static __initdata char *vcollected;
133static __initdata char *collected; 179static __initdata char *collected;
134static __initdata int remains; 180static __initdata int remains;
135static __initdata char *collect; 181static __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);