X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/b53c9cea2902572822bbbece5bac236c1bbf846e..769e9f3ea1cbe67d3b98e6db6c956abde2384868:/methods/rred.cc?ds=sidebyside diff --git a/methods/rred.cc b/methods/rred.cc index 91b6dda22..51af37557 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -7,12 +7,13 @@ #include <config.h> +#include <apt-pkg/init.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/error.h> -#include <apt-pkg/acquire-method.h> #include <apt-pkg/strutl.h> #include <apt-pkg/hashes.h> #include <apt-pkg/configuration.h> +#include "aptmethod.h" #include <stddef.h> #include <iostream> @@ -38,7 +39,7 @@ class MemBlock { char *free; MemBlock *next; - MemBlock(size_t size) : size(size), next(NULL) + explicit MemBlock(size_t size) : size(size), next(NULL) { free = start = new char[size]; } @@ -117,7 +118,7 @@ struct Change { size_t add_len; /* bytes */ char *add; - Change(size_t off) + explicit Change(size_t off) { offset = off; del_cnt = add_cnt = add_len = 0; @@ -334,35 +335,30 @@ class Patch { FileChanges filechanges; MemBlock add_text; - static bool retry_fwrite(char *b, size_t l, FILE *f, Hashes *hash) + static bool retry_fwrite(char *b, size_t l, FileFd &f, Hashes *hash) { - size_t r = 1; - while (r > 0 && l > 0) - { - r = fwrite(b, 1, l, f); - if (hash) - hash->Add((unsigned char*)b, r); - l -= r; - b += r; - } - return l == 0; + if (f.Write(b, l) == false) + return false; + if (hash) + hash->Add((unsigned char*)b, l); + return true; } - static void dump_rest(FILE *o, FILE *i, Hashes *hash) + static void dump_rest(FileFd &o, FileFd &i, Hashes *hash) { char buffer[BLOCK_SIZE]; - size_t l; - while (0 < (l = fread(buffer, 1, sizeof(buffer), i))) { - if (!retry_fwrite(buffer, l, o, hash)) + unsigned long long l = 0; + while (i.Read(buffer, sizeof(buffer), &l)) { + if (l ==0 || !retry_fwrite(buffer, l, o, hash)) break; } } - static void dump_lines(FILE *o, FILE *i, size_t n, Hashes *hash) + static void dump_lines(FileFd &o, FileFd &i, size_t n, Hashes *hash) { char buffer[BLOCK_SIZE]; while (n > 0) { - if (fgets(buffer, sizeof(buffer), i) == 0) + if (i.ReadLine(buffer, sizeof(buffer)) == NULL) buffer[0] = '\0'; size_t const l = strlen(buffer); if (l == 0 || buffer[l-1] == '\n') @@ -371,11 +367,11 @@ class Patch { } } - static void skip_lines(FILE *i, int n) + static void skip_lines(FileFd &i, int n) { char buffer[BLOCK_SIZE]; while (n > 0) { - if (fgets(buffer, sizeof(buffer), i) == 0) + if (i.ReadLine(buffer, sizeof(buffer)) == NULL) buffer[0] = '\0'; size_t const l = strlen(buffer); if (l == 0 || buffer[l-1] == '\n') @@ -383,7 +379,7 @@ class Patch { } } - static void dump_mem(FILE *o, char *p, size_t s, Hashes *hash) { + static void dump_mem(FileFd &o, char *p, size_t s, Hashes *hash) { retry_fwrite(p, s, o, hash); } @@ -483,7 +479,7 @@ class Patch { return true; } - void write_diff(FILE *f) + void write_diff(FileFd &f) { unsigned long long line = 0; std::list<struct Change>::reverse_iterator ch; @@ -494,33 +490,42 @@ class Patch { for (ch = filechanges.rbegin(); ch != filechanges.rend(); ++ch) { std::list<struct Change>::reverse_iterator mg_i, mg_e = ch; while (ch->del_cnt == 0 && ch->offset == 0) + { ++ch; + if (unlikely(ch == filechanges.rend())) + return; + } line -= ch->del_cnt; + std::string buf; if (ch->add_cnt > 0) { if (ch->del_cnt == 0) { - fprintf(f, "%llua\n", line); + strprintf(buf, "%llua\n", line); } else if (ch->del_cnt == 1) { - fprintf(f, "%lluc\n", line+1); + strprintf(buf, "%lluc\n", line+1); } else { - fprintf(f, "%llu,%lluc\n", line+1, line+ch->del_cnt); + strprintf(buf, "%llu,%lluc\n", line+1, line+ch->del_cnt); } + f.Write(buf.c_str(), buf.length()); mg_i = ch; do { dump_mem(f, mg_i->add, mg_i->add_len, NULL); } while (mg_i-- != mg_e); - fprintf(f, ".\n"); + buf = ".\n"; + f.Write(buf.c_str(), buf.length()); } else if (ch->del_cnt == 1) { - fprintf(f, "%llud\n", line+1); + strprintf(buf, "%llud\n", line+1); + f.Write(buf.c_str(), buf.length()); } else if (ch->del_cnt > 1) { - fprintf(f, "%llu,%llud\n", line+1, line+ch->del_cnt); + strprintf(buf, "%llu,%llud\n", line+1, line+ch->del_cnt); + f.Write(buf.c_str(), buf.length()); } line -= ch->offset; } } - void apply_against_file(FILE *out, FILE *in, Hashes *hash = NULL) + void apply_against_file(FileFd &out, FileFd &in, Hashes *hash = NULL) { std::list<struct Change>::iterator ch; for (ch = filechanges.begin(); ch != filechanges.end(); ++ch) { @@ -529,10 +534,11 @@ class Patch { dump_mem(out, ch->add, ch->add_len, hash); } dump_rest(out, in, hash); + out.Flush(); } }; -class RredMethod : public pkgAcqMethod { +class RredMethod : public aptMethod { private: bool Debug; @@ -621,7 +627,7 @@ class RredMethod : public pkgAcqMethod { if (p.Open(patch_name, FileFd::ReadOnly, FileFd::Gzip) == false || patch.read_diff(p, &patch_hash) == false) { - _error->DumpErrors(std::cerr); + _error->DumpErrors(std::cerr, GlobalError::DEBUG, false); return false; } p.Close(); @@ -635,14 +641,28 @@ class RredMethod : public pkgAcqMethod { << " and writing results to " << Itm->DestFile << std::endl; - FILE *inp = fopen(Path.c_str(), "r"); - FILE *out = fopen(Itm->DestFile.c_str(), "w"); + FileFd inp, out; + if (inp.Open(Path, FileFd::ReadOnly, FileFd::Extension) == false) + { + std::cerr << "FAILED to open inp " << Path << std::endl; + return _error->Error("Failed to open inp %s", Path.c_str()); + } + if (out.Open(Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::BufferedWrite, FileFd::Extension) == false) + { + std::cerr << "FAILED to open out " << Itm->DestFile << std::endl; + return _error->Error("Failed to open out %s", Itm->DestFile.c_str()); + } Hashes hash(Itm->ExpectedHashes); patch.apply_against_file(out, inp, &hash); - fclose(out); - fclose(inp); + out.Close(); + inp.Close(); + + if (_error->PendingError() == true) { + std::cerr << "FAILED to read or write files" << std::endl; + return false; + } if (Debug == true) { std::clog << "rred: finished file patching of " << Path << "." << std::endl; @@ -651,7 +671,7 @@ class RredMethod : public pkgAcqMethod { struct stat bufbase, bufpatch; if (stat(Path.c_str(), &bufbase) != 0 || stat(patch_name.c_str(), &bufpatch) != 0) - return _error->Errno("stat", _("Failed to stat")); + return _error->Errno("stat", _("Failed to stat %s"), Path.c_str()); struct timeval times[2]; times[0].tv_sec = bufbase.st_atime; @@ -661,7 +681,7 @@ class RredMethod : public pkgAcqMethod { return _error->Errno("utimes",_("Failed to set modification time")); if (stat(Itm->DestFile.c_str(), &bufbase) != 0) - return _error->Errno("stat", _("Failed to stat")); + return _error->Errno("stat", _("Failed to stat %s"), Itm->DestFile.c_str()); Res.LastModified = bufbase.st_mtime; Res.Size = bufbase.st_size; @@ -671,32 +691,29 @@ class RredMethod : public pkgAcqMethod { return true; } - bool Configuration(std::string Message) APT_OVERRIDE - { - if (pkgAcqMethod::Configuration(Message) == false) - return false; - - DropPrivsOrDie(); - - return true; - } - public: - RredMethod() : pkgAcqMethod("2.0",SingleInstance | SendConfig), Debug(false) {} + RredMethod() : aptMethod("rred", "2.0", SendConfig), Debug(false) {} }; int main(int argc, char **argv) { int i; bool just_diff = true; + bool test = false; Patch patch; if (argc <= 1) { - RredMethod Mth; - return Mth.Run(); + return RredMethod().Run(); } - if (argc > 1 && strcmp(argv[1], "-f") == 0) { + // Usage: rred -t input output diff ... + if (argc > 1 && strcmp(argv[1], "-t") == 0) { + // Read config files so we see compressors. + pkgInitConfig(*_config); + just_diff = false; + test = true; + i = 4; + } else if (argc > 1 && strcmp(argv[1], "-f") == 0) { just_diff = false; i = 2; } else { @@ -716,14 +733,24 @@ int main(int argc, char **argv) } } - if (just_diff) { - patch.write_diff(stdout); + if (test) { + FileFd out, inp; + std::cerr << "Patching " << argv[2] << " into " << argv[3] << "\n"; + inp.Open(argv[2], FileFd::ReadOnly,FileFd::Extension); + out.Open(argv[3], FileFd::WriteOnly | FileFd::Create | FileFd::BufferedWrite, FileFd::Extension); + patch.apply_against_file(out, inp); + out.Close(); + } else if (just_diff) { + FileFd out; + out.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly | FileFd::Create); + patch.write_diff(out); + out.Close(); } else { - FILE *out, *inp; - out = stdout; - inp = stdin; - + FileFd out, inp; + out.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly | FileFd::Create | FileFd::BufferedWrite); + inp.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly); patch.apply_against_file(out, inp); + out.Close(); } return 0; }