Unlink files, symlinks, FIFOs, devices etc. (except directories) before
writing them when extracting CPIOs. This stops weird behaviour like:
1) writing through symlinks created in earlier CPIOs. eg foo->bar in
the first CPIO. Having foo as a non-link in a subsequent CPIO,
results in bar being written and foo remaining as a symlink.
2) if the first version of file foo is larger than foo in a
subsequent CPIO, we end up with a mix of the two. ie. neither
the first or second version of /foo.
3) special files like devices, fifo etc. can't be overwritten in
subsequent CPIOS.
With this, the kernel will more closely replicate
for i in *.cpio; do cpio --extract --unconditional < $i ; done
This is a change but it's regarded as fixing broken functionality.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
This is a retransmission.
init/initramfs.c | 3 +++
1 files changed, 3 insertions(+)
Index: linux-2.6.15/init/initramfs.c
==================================================================---
linux-2.6.15.orig/init/initramfs.c
+++ linux-2.6.15/init/initramfs.c
@@ -249,6 +249,7 @@ static int __init do_name(void)
if (dry_run)
return 0;
if (S_ISREG(mode)) {
+ sys_unlink(collected);
if (maybe_link() >= 0) {
wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
if (wfd >= 0) {
@@ -263,6 +264,7 @@ static int __init do_name(void)
sys_chmod(collected, mode);
} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
S_ISFIFO(mode) || S_ISSOCK(mode)) {
+ sys_unlink(collected);
if (maybe_link() == 0) {
sys_mknod(collected, mode, rdev);
sys_chown(collected, uid, gid);
@@ -291,6 +293,7 @@ static int __init do_copy(void)
static int __init do_symlink(void)
{
collected[N_ALIGN(name_len) + body_len] = '\0';
+ sys_unlink(collected);
sys_symlink(collected + N_ALIGN(name_len), collected);
sys_lchown(collected, uid, gid);
state = SkipIt;
Michael Neuling wrote:> Unlink files, symlinks, FIFOs, devices etc. (except directories) before > writing them when extracting CPIOs. This stops weird behaviour like: > 1) writing through symlinks created in earlier CPIOs. eg foo->bar in > the first CPIO. Having foo as a non-link in a subsequent CPIO, > results in bar being written and foo remaining as a symlink. > 2) if the first version of file foo is larger than foo in a > subsequent CPIO, we end up with a mix of the two. ie. neither > the first or second version of /foo. > 3) special files like devices, fifo etc. can't be overwritten in > subsequent CPIOS. > > With this, the kernel will more closely replicate > for i in *.cpio; do cpio --extract --unconditional < $i ; done > > This is a change but it's regarded as fixing broken functionality. > > Signed-off-by: Michael Neuling <mikey@neuling.org>For the kernel, I would regard that as needless code... Coding for a chain of CPIO archives overwriting each other seems like overengineering. Jeff
Unlink files, symlinks, FIFOs, devices etc. (except directories) before
writing them when extracting CPIOs. This stops weird behaviour like:
1) writing through symlinks created in earlier CPIOs. eg foo->bar in
the first CPIO. Having foo as a non-link in a subsequent CPIO,
results in bar being written and foo remaining as a symlink.
2) if the first version of file foo is larger than foo in a
subsequent CPIO, we end up with a mix of the two. ie. neither
the first or second version of /foo.
3) special files like devices, fifo etc. can't be overwritten in
subsequent CPIOS.
With this, the kernel will more closely replicate
for i in *.cpio; do cpio --extract --unconditional < $i ; done
This is a change but it's regarded as fixing broken functionality.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
init/initramfs.c | 3 +++
1 files changed, 3 insertions(+)
Index: linux-2.6.15/init/initramfs.c
==================================================================---
linux-2.6.15.orig/init/initramfs.c
+++ linux-2.6.15/init/initramfs.c
@@ -249,6 +249,7 @@ static int __init do_name(void)
if (dry_run)
return 0;
if (S_ISREG(mode)) {
+ sys_unlink(collected);
if (maybe_link() >= 0) {
wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
if (wfd >= 0) {
@@ -263,6 +264,7 @@ static int __init do_name(void)
sys_chmod(collected, mode);
} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
S_ISFIFO(mode) || S_ISSOCK(mode)) {
+ sys_unlink(collected);
if (maybe_link() == 0) {
sys_mknod(collected, mode, rdev);
sys_chown(collected, uid, gid);
@@ -291,6 +293,7 @@ static int __init do_copy(void)
static int __init do_symlink(void)
{
collected[N_ALIGN(name_len) + body_len] = '\0';
+ sys_unlink(collected);
sys_symlink(collected + N_ALIGN(name_len), collected);
sys_lchown(collected, uid, gid);
state = SkipIt;