Why doesn't "cat a b > foo" work?
Grant Edwards
grant.b.edwards at gmail.com
Tue Jan 19 20:12:15 UTC 2021
We recently upgraded from an older version of busybox to 1.31.0, and
now there seems to be a problem with 'cat'. If I cat two files to
stdout it works fine, but if I redirect output into a file using ash,
the second file overwrites the first:
# echo abcdefghijk > a
# echo 12345 > b
# cat a b
abcdefghijk
12345
# cat a b > bar
# cat bar
12345
ghijk
# cat a b | cat > bar
# cat bar
abcdefghijk
12345
If I trace system calls, they are virtually identical for the two cases above:
# diff -U999 strace.works strace.broken
--- strace.works
+++ strace.broken
@@ -1,33 +1,33 @@
execve("/bin/cat", ["cat", "a", "b"], [/* 16 vars */]) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40007000
-stat("/etc/ld.so.cache", 0xbedc2a18) = -1 ENOENT (No such file or directory)
+stat("/etc/ld.so.cache", 0xbe9fca18) = -1 ENOENT (No such file or directory)
open("/apps/lib/libc.so.0", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libc.so.0", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=331104, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40008000
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\320\250\0\0004\0\0\0"..., 4096) = 4096
mmap2(NULL, 385024, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40010000
mmap2(0x40010000, 324524, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x40010000
mmap2(0x40067000, 5136, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x4f000) = 0x40067000
mmap2(0x40069000, 16432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40069000
close(3) = 0
munmap(0x40008000, 4096) = 0
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=32664, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x40008000
set_tls(0x400084a0, 0x40008b40, 0x40008b48, 0x400084a0, 0x4000ef74) = 0
mprotect(0xc1000, 4096, PROT_READ) = 0
mprotect(0x40067000, 4096, PROT_READ) = 0
mprotect(0x4000e000, 4096, PROT_READ) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
-ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
+ioctl(1, TCGETS, 0xbe9fc9cc) = -1 ENOTTY (Inappropriate ioctl for device)
getuid32() = 0
open("a", O_RDONLY|O_LARGEFILE) = 3
sendfile64(1, 3, NULL, 16777216) = 12
sendfile64(1, 3, NULL, 16777216) = 0
close(3) = 0
open("b", O_RDONLY|O_LARGEFILE) = 3
sendfile64(1, 3, NULL, 16777216) = 6
sendfile64(1, 3, NULL, 16777216) = 0
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
I wonder if the use of sendfile64() is new, and sendfile64() doesn't
work right in our libc...
Any other suggestions?
More information about the busybox
mailing list