shithub: clone

Download patch

ref: 3b432f653f67dec73729a68d53299df2a107e573
parent: 50b8eca6b085d2832dc14633e7de2efacbb0a5ce
author: kvik <kvik@a-b.xyz>
date: Sun Mar 3 15:11:46 EST 2019

correctly handle partial reads

--- a/clone.c
+++ b/clone.c
@@ -25,6 +25,7 @@
 
 typedef struct {
 	File *f;
+	long sz;
 	vlong offset;
 } Blk;
 
@@ -361,6 +362,7 @@
 vlong
 blklist(File *f, Blk **bp)
 {
+	long odd;
 	vlong i, nblk;
 	Blk *b, *p;
 
@@ -367,16 +369,20 @@
 	if(f->length == 0)
 		return 0;
 	nblk = f->length / blksz;
+	odd = f->length % blksz;
 	if(nblk == 0)
 		nblk = 1;
-	else if(nblk % blksz > 0)
+	else if(odd > 0)
 		nblk++;
 
 	b = p = emalloc(sizeof(Blk) * nblk);
 	for(i = 0; i < nblk; i++, p++){
 		p->f = f;
+		p->sz = blksz;
 		p->offset = blksz * i;
 	}
+	if(odd > 0)
+		b[nblk-1].sz = odd;
 
 	*bp = b;
 	return nblk;
@@ -416,12 +422,29 @@
 	return ret;
 }
 
+long
+preadn(int fd, void *buf, long nbytes, vlong offset)
+{
+	long nr, n;
+	vlong o;
+	char *p;
+	
+	nr = 0, n = nbytes, o = offset, p = buf;
+	while(nr < nbytes){
+		if((n = pread(fd, p, n, o)) < 0)
+			return -1;
+		if(n == 0)
+			break;
+		nr += n, o += n, p += n;
+	}
+	return nr;
+}
+
 void
 blkproc(void *)
 {
 	int sfd, dfd;
 	long n;
-	vlong off;
 	char *buf;
 	File *f;
 	Blk *b;
@@ -437,12 +460,11 @@
 		f = b->f;
 		sfd = f->sfd;
 		dfd = f->dfd;
-		off = b->offset;
-		if((n = pread(sfd, buf, blksz, off)) < 0){
+		if((n = preadn(sfd, buf, b->sz, b->offset)) < 0){
 			error("can't read: %r");
 			sendul(f->errchan, ~0);
 		}
-		if(n > 0 && pwrite(dfd, buf, n, off) != n){
+		if(n > 0 && pwrite(dfd, buf, n, b->offset) != n){
 			error("can't write: %r");
 			sendul(f->errchan, ~0);
 		}