[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: