+ FetchResult Res;
+ Res.Filename = Itm->DestFile;
+ if (Itm->Uri.empty())
+ {
+ Path = Itm->DestFile;
+ Itm->DestFile.append(".result");
+ } else
+ URIStart(Res);
+
+ std::vector<std::string> patchpaths;
+ Patch patch;
+
+ if (FileExists(Path + ".ed") == true)
+ patchpaths.push_back(Path + ".ed");
+ else
+ {
+ _error->PushToStack();
+ std::vector<std::string> patches = GetListOfFilesInDir(flNotFile(Path), "gz", true, false);
+ _error->RevertToStack();
+
+ std::string const baseName = Path + ".ed.";
+ for (std::vector<std::string>::const_iterator p = patches.begin();
+ p != patches.end(); ++p)
+ if (p->compare(0, baseName.length(), baseName) == 0)
+ patchpaths.push_back(*p);
+ }
+
+ std::string patch_name;
+ for (std::vector<std::string>::iterator I = patchpaths.begin();
+ I != patchpaths.end();
+ I++)
+ {
+ patch_name = *I;
+ if (Debug == true)
+ std::clog << "Patching " << Path << " with " << patch_name
+ << std::endl;
+
+ FileFd p;
+ // all patches are compressed, even if the name doesn't reflect it
+ if (p.Open(patch_name, FileFd::ReadOnly, FileFd::Gzip) == false) {
+ std::cerr << "Could not open patch file " << patch_name << std::endl;
+ _error->DumpErrors(std::cerr);
+ abort();
+ }
+ patch.read_diff(p);
+ p.Close();
+ }
+
+ if (Debug == true)
+ std::clog << "Applying patches against " << Path
+ << " and writing results to " << Itm->DestFile
+ << std::endl;
+
+ FILE *inp = fopen(Path.c_str(), "r");
+ FILE *out = fopen(Itm->DestFile.c_str(), "w");
+
+ Hashes hash;
+
+ patch.apply_against_file(out, inp, &hash);
+
+ fclose(out);
+ fclose(inp);
+
+ if (Debug == true) {
+ std::clog << "rred: finished file patching of " << Path << "." << std::endl;
+ }
+
+ 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"));
+
+ struct utimbuf timebuf;
+ timebuf.actime = bufbase.st_atime;
+ timebuf.modtime = bufpatch.st_mtime;
+ if (utime(Itm->DestFile.c_str(), &timebuf) != 0)
+ return _error->Errno("utime", _("Failed to set modification time"));
+
+ if (stat(Itm->DestFile.c_str(), &bufbase) != 0)
+ return _error->Errno("stat", _("Failed to stat"));
+
+ Res.LastModified = bufbase.st_mtime;
+ Res.Size = bufbase.st_size;
+ Res.TakeHashes(hash);
+ URIDone(Res);
+
+ return true;
+ }
+
+ public:
+ RredMethod() : pkgAcqMethod("2.0",SingleInstance | SendConfig) {}
+};
+
+int main(int argc, char **argv)