More robust file content copy in copy_tree()
Bail out on read(2) failure, continue on EINTR, support short writes and increase chunk size.
This commit is contained in:
		
				
					committed by
					
						
						Serge Hallyn
					
				
			
			
				
	
			
			
			
						parent
						
							1d281273b1
						
					
				
				
					commit
					f606314f0c
				
			@@ -691,6 +691,42 @@ static int copy_special (const char *src, const char *dst,
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * full_write - write entire buffer
 | 
			
		||||
 *
 | 
			
		||||
 * Write up to count bytes from the buffer starting at buf to the
 | 
			
		||||
 * file referred to by the file descriptor fd.
 | 
			
		||||
 * Retry in case of a short write.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns the number of bytes written on success, -1 on error.
 | 
			
		||||
 */
 | 
			
		||||
static ssize_t full_write(int fd, const void *buf, size_t count) {
 | 
			
		||||
	ssize_t written = 0;
 | 
			
		||||
 | 
			
		||||
	while (count > 0) {
 | 
			
		||||
		ssize_t res;
 | 
			
		||||
 | 
			
		||||
		res = write(fd, buf, count);
 | 
			
		||||
		if (res < 0) {
 | 
			
		||||
			if (errno == EINTR) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return res;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (res == 0) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		written += res;
 | 
			
		||||
		buf = (const unsigned char*)buf + res;
 | 
			
		||||
		count -= (size_t)res;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return written;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * copy_file - copy a file
 | 
			
		||||
 *
 | 
			
		||||
@@ -710,8 +746,6 @@ static int copy_file (const char *src, const char *dst,
 | 
			
		||||
	int err = 0;
 | 
			
		||||
	int ifd;
 | 
			
		||||
	int ofd;
 | 
			
		||||
	char buf[1024];
 | 
			
		||||
	ssize_t cnt;
 | 
			
		||||
 | 
			
		||||
	ifd = open (src, O_RDONLY|O_NOFOLLOW);
 | 
			
		||||
	if (ifd < 0) {
 | 
			
		||||
@@ -753,8 +787,24 @@ static int copy_file (const char *src, const char *dst,
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
 | 
			
		||||
		if (write (ofd, buf, (size_t)cnt) != cnt) {
 | 
			
		||||
	while (true) {
 | 
			
		||||
		char buf[8192];
 | 
			
		||||
		ssize_t cnt;
 | 
			
		||||
 | 
			
		||||
		cnt = read (ifd, buf, sizeof buf);
 | 
			
		||||
		if (cnt < 0) {
 | 
			
		||||
			if (errno == EINTR) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			(void) close (ofd);
 | 
			
		||||
			(void) close (ifd);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		if (cnt == 0) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (full_write (ofd, buf, (size_t)cnt) < 0) {
 | 
			
		||||
			(void) close (ofd);
 | 
			
		||||
			(void) close (ifd);
 | 
			
		||||
			return -1;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user