cp(1) fails to copy file from /proc
Hello,
I'm not sure wheter this is a bug or a feature... However, I just noticed
that cp(1) fails to copy /proc/cpuinfo to the file system (tested on i686 and
x86_64 lenny systems):
$ wc -l /proc/cpuinfo 200 /proc/cpuinfo
$ cp /proc/cpuinfo /tmp
$ echo $?
0
$ wc -l /tmp/cpuinfo
125 /tmp/cpuinfo
The first part of the file is copied correctly, but the rest is missing.
Running strace(1) on cp reveals that cp requests to read 4 kB, receives less
(but still >0), writes the received data to the destination file and exits:
$ strace cp /proc/cpuinfo /tmp
[...]
open("/proc/cpuinfo", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
open("/tmp/cpuinfo", O_WRONLY|O_CREAT|O_EXCL, 0444) = 4
fstat(4, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, "processor\t: 0\nvendor_id\t: Genuine"..., 4096) = 3535
write(4, "processor\t: 0\nvendor_id\t: Genuine"..., 3535) = 3535
close(4) = 0
close(3) = 0
close(0) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
Subsequent read(2)s would have returned more data (and thus allowed cp to
successfully copy the file), as running strace on the the attached test
program shows:
$ strace ./a.out /proc/cpuinfo /tmp
[...]
open("/proc/cpuinfo", O_RDONLY) = 3
open("/tmp/cpuinfo", O_WRONLY|O_CREAT|O_EXCL, 0777) = 4
read(3, "processor\t: 0\nvendor_id\t: Genuine"..., 8192) = 3535
write(4, "processor\t: 0\nvendor_id\t: Genuine"..., 3535) = 3535
read(3, "processor\t: 5\nvendor_id\t: Genuine"..., 8192) = 2121
write(4, "processor\t: 5\nvendor_id\t: Genuine"..., 2121) = 2121
read(3, ""..., 8192) = 0
exit_group(0) = ?
What's the problem here? Is this a bug in cp, in the proc file system, or is
cp simply not supposed to work on such file systems?
TIA, Jukka
--
This email fills a much-needed gap in the archives.
#include <err.h>
#include <fcntl.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
char buf[8*1024], *bufp;
int in, out;
int nread, nwritten, nleft;
if ((in = open(argv[1], O_RDONLY, 0)) == -1) {
err(1, "open(src)");
}
if ((out = open(argv[2], O_WRONLY|O_CREAT|O_EXCL, 0777)) == -1) {
err(1, "open(dst)");
}
while ((nread = read(in, buf, sizeof buf)) > 0) {
nleft = nread;
bufp = buf;
while (nleft > 0) {
if ((nwritten = write(out, bufp, nleft)) == -1) {
err(1, "write");
}
nleft -= nwritten;
bufp += nwritten;
}
}
if (nread == -1) {
err(1, "read");
}
return 0;
}
Reply to: