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);
}