From b1de290eee2476737581409ae33121dfdbc8c5e4 Mon Sep 17 00:00:00 2001 From: James Blades Date: Sun, 13 Jan 2019 21:26:39 -0700 Subject: [PATCH] [Issue #23] Allow larger than 2GB files to be read. `read` and `write` return a signed int, meaning that they can only read up to 2 billion bytes (2GB) at a time. bsdiff and bspatch were expecting the entire file to be read (or written, respectively) in a single call to `read` or `write`, which is only possible if they are less than 2GB in size. There are also other times in which a single function call would be inadequate for IO, for instance in the case where a device is busy. The fix for this was to place the functions in a loop and continue as long as at least 1 byte was transferred (in or out). If an error, or 0 return value, comes back from the transfer, break out of the loop and return the total number of bytes that had been transferred up to that point. Updated the .gitignore file to ignore vim swap files, as well as the autoconf (generated) files and the executables. --- .gitignore | 18 ++++++++++++++++++ bsdiff.c | 23 +++++++++++++++++++++-- bspatch.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 4e13492..867f2bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.*.sw* .deps/* .libs/* *.lo @@ -9,3 +10,20 @@ NEWS README ChangeLog COPYING +INSTALL +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +compile +config.h +config.h.in +config.log +config.status +configure +depcomp +install-sh +missing +stamp-h1 +/bsdiff +/bspatch diff --git a/bsdiff.c b/bsdiff.c index 628f1c1..44f9a2b 100644 --- a/bsdiff.c +++ b/bsdiff.c @@ -373,6 +373,25 @@ static int bz2_write(struct bsdiff_stream* stream, const void* buffer, int size) return 0; } +static off_t readFileToBuffer(int fd, uint8_t* buffer, off_t bufferSize) +{ + off_t bytesRead = 0; + int ret; + while (bytesRead < bufferSize) + { + ret = read(fd, buffer + bytesRead, bufferSize - bytesRead); + if (ret > 0) + { + bytesRead += ret; + } + else + { + break; + } + } + return bytesRead; +} + int main(int argc,char *argv[]) { int fd; @@ -397,7 +416,7 @@ int main(int argc,char *argv[]) ((oldsize=lseek(fd,0,SEEK_END))==-1) || ((old=malloc(oldsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0) || - (read(fd,old,oldsize)!=oldsize) || + (readFileToBuffer(fd,old,oldsize)!=oldsize) || (close(fd)==-1)) err(1,"%s",argv[1]); @@ -407,7 +426,7 @@ int main(int argc,char *argv[]) ((newsize=lseek(fd,0,SEEK_END))==-1) || ((new=malloc(newsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0) || - (read(fd,new,newsize)!=newsize) || + (readFileToBuffer(fd,new,newsize)!=newsize) || (close(fd)==-1)) err(1,"%s",argv[2]); /* Create the patch file */ diff --git a/bspatch.c b/bspatch.c index b544914..1c9bd91 100644 --- a/bspatch.c +++ b/bspatch.c @@ -121,6 +121,44 @@ static int bz2_read(const struct bspatch_stream* stream, void* buffer, int lengt return 0; } +static off_t readFileToBuffer(int fd, uint8_t* buffer, off_t bufferSize) +{ + off_t bytesRead = 0; + int ret; + while (bytesRead < bufferSize) + { + ret = read(fd, buffer + bytesRead, bufferSize - bytesRead); + if (ret > 0) + { + bytesRead += ret; + } + else + { + break; + } + } + return bytesRead; +} + +static off_t writeFileFromBuffer(int fd, uint8_t* buffer, off_t bufferSize) +{ + off_t bytesWritten = 0; + int ret; + while (bytesWritten < bufferSize) + { + ret = write(fd, buffer + bytesWritten, bufferSize - bytesWritten); + if (ret > 0) + { + bytesWritten += ret; + } + else + { + break; + } + } + return bytesWritten; +} + int main(int argc,char * argv[]) { FILE * f; @@ -160,7 +198,7 @@ int main(int argc,char * argv[]) ((oldsize=lseek(fd,0,SEEK_END))==-1) || ((old=malloc(oldsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0) || - (read(fd,old,oldsize)!=oldsize) || + (readFileToBuffer(fd,old,oldsize)!=oldsize) || (fstat(fd, &sb)) || (close(fd)==-1)) err(1,"%s",argv[1]); if((new=malloc(newsize+1))==NULL) err(1,NULL); @@ -179,7 +217,7 @@ int main(int argc,char * argv[]) /* Write the new file */ if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,sb.st_mode))<0) || - (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) + (writeFileFromBuffer(fd,new,newsize)!=newsize) || (close(fd)==-1)) err(1,"%s",argv[2]); free(new);