Commit 889d51a10712b6fd6175196626de2116858394f4

Authored by Nye Liu
Committed by Linus Torvalds
1 parent 9ba16087d9

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>

Showing 1 changed file with 53 additions and 0 deletions Side-by-side Diff

... ... @@ -6,6 +6,7 @@
6 6 #include <linux/delay.h>
7 7 #include <linux/string.h>
8 8 #include <linux/syscalls.h>
  9 +#include <linux/utime.h>
9 10  
10 11 static __initdata char *message;
11 12 static void __init error(char *x)
... ... @@ -72,6 +73,49 @@
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 119 /* cpio header parsing */
76 120  
77 121 static __initdata unsigned long ino, major, minor, nlink;
... ... @@ -97,6 +141,7 @@
97 141 uid = parsed[2];
98 142 gid = parsed[3];
99 143 nlink = parsed[4];
  144 + mtime = parsed[5];
100 145 body_len = parsed[6];
101 146 major = parsed[7];
102 147 minor = parsed[8];
... ... @@ -130,6 +175,7 @@
130 175 count -= n;
131 176 }
132 177  
  178 +static __initdata char *vcollected;
133 179 static __initdata char *collected;
134 180 static __initdata int remains;
135 181 static __initdata char *collect;
... ... @@ -271,6 +317,7 @@
271 317 if (wfd >= 0) {
272 318 sys_fchown(wfd, uid, gid);
273 319 sys_fchmod(wfd, mode);
  320 + vcollected = kstrdup(collected, GFP_KERNEL);
274 321 state = CopyFile;
275 322 }
276 323 }
277 324  
... ... @@ -278,12 +325,14 @@
278 325 sys_mkdir(collected, mode);
279 326 sys_chown(collected, uid, gid);
280 327 sys_chmod(collected, mode);
  328 + dir_add(collected, mtime);
281 329 } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
282 330 S_ISFIFO(mode) || S_ISSOCK(mode)) {
283 331 if (maybe_link() == 0) {
284 332 sys_mknod(collected, mode, rdev);
285 333 sys_chown(collected, uid, gid);
286 334 sys_chmod(collected, mode);
  335 + do_utime(collected, mtime);
287 336 }
288 337 }
289 338 return 0;
... ... @@ -294,6 +343,8 @@
294 343 if (count >= body_len) {
295 344 sys_write(wfd, victim, body_len);
296 345 sys_close(wfd);
  346 + do_utime(vcollected, mtime);
  347 + kfree(vcollected);
297 348 eat(body_len);
298 349 state = SkipIt;
299 350 return 0;
... ... @@ -311,6 +362,7 @@
311 362 clean_path(collected, 0);
312 363 sys_symlink(collected + N_ALIGN(name_len), collected);
313 364 sys_lchown(collected, uid, gid);
  365 + do_utime(collected, mtime);
314 366 state = SkipIt;
315 367 next_state = Reset;
316 368 return 0;
... ... @@ -466,6 +518,7 @@
466 518 buf += inptr;
467 519 len -= inptr;
468 520 }
  521 + dir_utime();
469 522 kfree(window);
470 523 kfree(name_buf);
471 524 kfree(symlink_buf);