X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/27da8141d21cfbfc29675510737ee05bdfd4a2b1..2a49601f69e08f06fb2727d869d420daacdd09d5:/methods/rred.cc diff --git a/methods/rred.cc b/methods/rred.cc index 2a70a9f91..7c65f8f92 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -15,7 +15,6 @@ #include #include #include -#include #include /*}}}*/ /** \brief RredMethod - ed-style incremential patch method {{{ @@ -37,13 +36,10 @@ class RredMethod : public pkgAcqMethod { // return values enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE, MMAP_FAILED}; - State applyFile(FileFd &ed_cmds, FILE *in_file, FILE *out_file, + State applyFile(FileFd &ed_cmds, FileFd &in_file, FileFd &out_file, unsigned long &line, char *buffer, Hashes *hash) const; - void ignoreLineInFile(FILE *fin, char *buffer) const; void ignoreLineInFile(FileFd &fin, char *buffer) const; - void copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines, - Hashes *hash, char *buffer) const; - void copyLinesFromFileToFile(FileFd &fin, FILE *fout, unsigned int lines, + void copyLinesFromFileToFile(FileFd &fin, FileFd &fout, unsigned int lines, Hashes *hash, char *buffer) const; State patchFile(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const; @@ -72,7 +68,7 @@ public: * \param hash the created file for correctness * \return the success State of the ed command executor */ -RredMethod::State RredMethod::applyFile(FileFd &ed_cmds, FILE *in_file, FILE *out_file, +RredMethod::State RredMethod::applyFile(FileFd &ed_cmds, FileFd &in_file, FileFd &out_file, unsigned long &line, char *buffer, Hashes *hash) const { // get the current command and parse it if (ed_cmds.ReadLine(buffer, BUF_SIZE) == NULL) { @@ -178,39 +174,19 @@ RredMethod::State RredMethod::applyFile(FileFd &ed_cmds, FILE *in_file, FILE *ou return ED_OK; } /*}}}*/ -void RredMethod::copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines,/*{{{*/ - Hashes *hash, char *buffer) const { - while (0 < lines--) { - do { - fgets(buffer, BUF_SIZE, fin); - size_t const written = fwrite(buffer, 1, strlen(buffer), fout); - hash->Add((unsigned char*)buffer, written); - } while (strlen(buffer) == (BUF_SIZE - 1) && - buffer[BUF_SIZE - 2] != '\n'); - } -} - /*}}}*/ -void RredMethod::copyLinesFromFileToFile(FileFd &fin, FILE *fout, unsigned int lines,/*{{{*/ +void RredMethod::copyLinesFromFileToFile(FileFd &fin, FileFd &fout, unsigned int lines,/*{{{*/ Hashes *hash, char *buffer) const { while (0 < lines--) { do { fin.ReadLine(buffer, BUF_SIZE); - size_t const written = fwrite(buffer, 1, strlen(buffer), fout); - hash->Add((unsigned char*)buffer, written); + unsigned long long const towrite = strlen(buffer); + fout.Write(buffer, towrite); + hash->Add((unsigned char*)buffer, towrite); } while (strlen(buffer) == (BUF_SIZE - 1) && buffer[BUF_SIZE - 2] != '\n'); } } /*}}}*/ -void RredMethod::ignoreLineInFile(FILE *fin, char *buffer) const { /*{{{*/ - fgets(buffer, BUF_SIZE, fin); - while (strlen(buffer) == (BUF_SIZE - 1) && - buffer[BUF_SIZE - 2] != '\n') { - fgets(buffer, BUF_SIZE, fin); - buffer[0] = ' '; - } -} - /*}}}*/ void RredMethod::ignoreLineInFile(FileFd &fin, char *buffer) const { /*{{{*/ fin.ReadLine(buffer, BUF_SIZE); while (strlen(buffer) == (BUF_SIZE - 1) && @@ -223,20 +199,18 @@ void RredMethod::ignoreLineInFile(FileFd &fin, char *buffer) const { /*{{{*/ RredMethod::State RredMethod::patchFile(FileFd &Patch, FileFd &From, /*{{{*/ FileFd &out_file, Hashes *hash) const { char buffer[BUF_SIZE]; - FILE* fFrom = fdopen(From.Fd(), "r"); - FILE* fTo = fdopen(out_file.Fd(), "w"); /* we do a tail recursion to read the commands in the right order */ unsigned long line = -1; // assign highest possible value - State const result = applyFile(Patch, fFrom, fTo, line, buffer, hash); + State const result = applyFile(Patch, From, out_file, line, buffer, hash); /* read the rest from infile */ if (result == ED_OK) { - while (fgets(buffer, BUF_SIZE, fFrom) != NULL) { - size_t const written = fwrite(buffer, 1, strlen(buffer), fTo); - hash->Add((unsigned char*)buffer, written); + while (From.ReadLine(buffer, BUF_SIZE) != NULL) { + unsigned long long const towrite = strlen(buffer); + out_file.Write(buffer, towrite); + hash->Add((unsigned char*)buffer, towrite); } - fflush(fTo); } return result; } @@ -252,6 +226,21 @@ struct EdCommand { char type; }; #define IOV_COUNT 1024 /* Don't really want IOV_MAX since it can be arbitrarily large */ +static ssize_t retry_writev(int fd, const struct iovec *iov, int iovcnt) { + ssize_t Res; + errno = 0; + ssize_t i = 0; + do { + Res = writev(fd, iov + i, iovcnt); + if (Res < 0 && errno == EINTR) + continue; + if (Res < 0) + return _error->Errno("writev",_("Write error")); + iovcnt -= Res; + i += Res; + } while (Res > 0 && iovcnt > 0); + return i; +} #endif /*}}}*/ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ @@ -260,7 +249,9 @@ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ MMap ed_cmds(Patch, MMap::ReadOnly); MMap in_file(From, MMap::ReadOnly); - if (ed_cmds.Size() == 0 || in_file.Size() == 0) + unsigned long long const ed_size = ed_cmds.Size(); + unsigned long long const in_size = in_file.Size(); + if (ed_size == 0 || in_size == 0) return MMAP_FAILED; EdCommand* commands = 0; @@ -269,10 +260,10 @@ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ const char* begin = (char*) ed_cmds.Data(); const char* end = begin; - const char* ed_end = (char*) ed_cmds.Data() + ed_cmds.Size(); + const char* ed_end = (char*) ed_cmds.Data() + ed_size; const char* input = (char*) in_file.Data(); - const char* input_end = (char*) in_file.Data() + in_file.Size(); + const char* input_end = (char*) in_file.Data() + in_size; size_t i; @@ -356,7 +347,12 @@ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ } if(command_count == command_alloc) { command_alloc = (command_alloc + 64) * 3 / 2; - commands = (EdCommand*) realloc(commands, command_alloc * sizeof(EdCommand)); + EdCommand* newCommands = (EdCommand*) realloc(commands, command_alloc * sizeof(EdCommand)); + if (newCommands == NULL) { + free(commands); + return MMAP_FAILED; + } + commands = newCommands; } commands[command_count++] = cmd; } @@ -395,7 +391,7 @@ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ hash->Add((const unsigned char*) begin, input - begin); if(++iov_size == IOV_COUNT) { - writev(out_file.Fd(), iov, IOV_COUNT); + retry_writev(out_file.Fd(), iov, IOV_COUNT); iov_size = 0; } } @@ -420,7 +416,7 @@ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ iov[iov_size].iov_len); if(++iov_size == IOV_COUNT) { - writev(out_file.Fd(), iov, IOV_COUNT); + retry_writev(out_file.Fd(), iov, IOV_COUNT); iov_size = 0; } } @@ -435,15 +431,15 @@ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From, /*{{{*/ } if(iov_size) { - writev(out_file.Fd(), iov, iov_size); + retry_writev(out_file.Fd(), iov, iov_size); iov_size = 0; } for(i = 0; i < iov_size; i += IOV_COUNT) { if(iov_size - i < IOV_COUNT) - writev(out_file.Fd(), iov + i, iov_size - i); + retry_writev(out_file.Fd(), iov + i, iov_size - i); else - writev(out_file.Fd(), iov + i, IOV_COUNT); + retry_writev(out_file.Fd(), iov + i, IOV_COUNT); } delete [] iov;