aboutsummaryrefslogtreecommitdiffstats
path: root/init/initramfs.c
diff options
context:
space:
mode:
authorNye Liu <nyet@nyet.org>2008-10-16 01:01:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-16 14:21:31 -0400
commit889d51a10712b6fd6175196626de2116858394f4 (patch)
tree3dc6575a4f2429cdd320c05de209c88a73a9da1e /init/initramfs.c
parent9ba16087d9f996a93ab6f4453a52a4b24bc1f25c (diff)
initramfs: add option to preserve mtime from initramfs cpio images
When unpacking the cpio into the initramfs, mtimes are not preserved by default. This patch adds an INITRAMFS_PRESERVE_MTIME option that allows mtimes stored in the cpio image to be used when constructing the initramfs. For embedded applications that run exclusively out of the initramfs, this is invaluable: When building embedded application initramfs images, its nice to know when the files were actually created during the build process - that makes it easier to see what files were modified when so we can compare the files that are being used on the image with the files used during the build process. This might help (for example) to determine if the target system has all the updated files you expect to see w/o having to check MD5s etc. In our environment, the whole system runs off the initramfs partition, and seeing the modified times of the shared libraries (for example) helps us find bugs that may have been introduced by the build system incorrectly propogating outdated shared libraries into the image. Similarly, many of the initializion/configuration files in /etc might be dynamically built by the build system, and knowing when they were modified helps us sanity check whether the target system has the "latest" files etc. Finally, we might use last modified times to determine whether a hot fix should be applied or not to the running ramfs. Signed-off-by: Nye Liu <nyet@nyet.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'init/initramfs.c')
-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);