On Wed, Nov 23, 2011 at 05:20:36PM +0100, Michael Vogt wrote: >On Wed, Nov 23, 2011 at 04:09:23PM +0000, Steve McIntyre wrote: >> On Wed, Nov 23, 2011 at 05:01:13PM +0100, Michael Vogt wrote: >> >On Mon, Nov 21, 2011 at 06:57:41PM +0100, Julian Andres Klode wrote: >> >> On Mon, Nov 21, 2011 at 01:03:08PM +0100, David Kalnischkies wrote: >> >> > On Mon, Nov 21, 2011 at 01:26, Steve McIntyre <st...@einval.com> wrote: >> >> > > I've just added support for translated description files into >[..] >> >> It would be great if someone who actually needs it takes a look >> >> at it. That said, I have pushed out the following patch to >> >> the debian-experimental2 branch, please test it (I didn't >> >> test it, but it compiles and looks logically right). >> >[..] >> > >> >Thanks! This looks fine, I still changed it a bit to make use of the >> >APT::Configuration::getCompressionTypes() code so that we have only a >> >single place to add new compression types. Needs some serious testing >> >still. >> >> My own testing suggests it's necessary but not sufficient. The code in >> indexcopy.cc needs updating too to support things other than >> uncompressed and gzipped files. I've got a grotty patch that works for >> me but you *will* want to refactor. :-) > >Oh, indeed, that code needs some serious love in general. But please >send us the patch :)
I'm cleaning it up slightly to apply against current debian-sid right now, but here is the diff against 0.8.10. The main change is that I've factored out the decompressor code in IndexCopy::CopyPackages() and TranslationsCopy::CopyTranslations() into a single common function, rather than the current repeated code. Then I've added support for bzip2 and xz there, by forking and execing the right decompression tool. I'm not a C++ developer by any means, as you'll probably tell. :-) You'll definitely want to move DecompressFile() somewhere else... A *much* better solution IMHO would be to extend class FileFd (which already has ReadOnlyGzip as an option) for either specific support for other compression methods, or to replace it with a generic option ReadOnlyCompressed that can do the right thing. *BUT* that will then mean linking directly with libbz2, liblzma etc. which we may not want due to extra library dependencies. -- Steve McIntyre, Cambridge, UK. st...@einval.com < sladen> I actually stayed in a hotel and arrived to find a post-it note stuck to the mini-bar saying "Paul: This fridge and fittings are the correct way around and do not need altering"
diff -uNrBb apt-0.8.10.old/apt-pkg//cdrom.cc apt-0.8.10/apt-pkg//cdrom.cc --- apt-0.8.10.old/apt-pkg//cdrom.cc 2010-08-24 16:58:13.000000000 +0100 +++ apt-0.8.10/apt-pkg//cdrom.cc 2011-11-23 02:09:11.055019767 +0000 @@ -78,7 +78,8 @@ /* Aha! We found some package files. We assume that everything under this dir is controlled by those package files so we don't look down anymore */ - if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0) + if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0 || + stat("Packages.bz2",&Buf) == 0 || stat("Packages.xz",&Buf) == 0) { List.push_back(CD); @@ -86,7 +87,8 @@ if (_config->FindB("APT::CDROM::Thorough",false) == false) return true; } - if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0) + if (stat("Packages",&Buf) == 0 || stat("Packages.gz",&Buf) == 0 || + stat("Packages.bz2",&Buf) == 0 || stat("Packages.xz",&Buf) == 0) { SList.push_back(CD); @@ -95,7 +97,7 @@ return true; } - // see if we find translatin indexes + // see if we find translatin indices if (stat("i18n",&Buf) == 0) { D = opendir("i18n"); @@ -106,8 +108,11 @@ if (_config->FindB("Debug::aptcdrom",false) == true) std::clog << "found translations: " << Dir->d_name << "\n"; string file = Dir->d_name; - if(file.substr(file.size()-3,file.size()) == ".gz") + if(file.substr(file.size()-3,file.size()) == ".gz" || + file.substr(file.size()-3,file.size()) == ".xz") file = file.substr(0,file.size()-3); + if(file.substr(file.size()-4,file.size()) == ".bz2") + file = file.substr(0,file.size()-4); TransList.push_back(CD+"i18n/"+ file); } } @@ -251,7 +256,9 @@ { struct stat Buf; if (stat((List[I] + Name).c_str(),&Buf) != 0 && - stat((List[I] + Name + ".gz").c_str(),&Buf) != 0) + stat((List[I] + Name + ".gz").c_str(),&Buf) != 0 && + stat((List[I] + Name + ".bz2").c_str(),&Buf) != 0 && + stat((List[I] + Name + ".xz").c_str(),&Buf) != 0) _error->Errno("stat","Failed to stat %s%s",List[I].c_str(), Name); Inodes[I] = Buf.st_ino; diff -uNrBb apt-0.8.10.old/apt-pkg//indexcopy.cc apt-0.8.10/apt-pkg//indexcopy.cc --- apt-0.8.10.old/apt-pkg//indexcopy.cc 2010-09-07 14:19:57.000000000 +0100 +++ apt-0.8.10/apt-pkg//indexcopy.cc 2011-11-23 04:01:56.038989999 +0000 @@ -34,7 +34,83 @@ using namespace std; + /*}}}*/ +// DecompressFile - wrapper for decompressing gzip/bzip2/xz compressed files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool DecompressFile(string Filename, int *fd, unsigned long *FileSize) +{ + string CompressProg; + string CompressProgFind; + FileFd From; + struct stat Buf; + *fd = -1; + + if (stat((Filename + ".gz").c_str(), &Buf) == 0) + { + CompressProg = "gzip"; + CompressProgFind = "Dir::bin::gzip"; + From.Open(Filename + ".gz",FileFd::ReadOnly); + } + else if (stat((Filename + ".bz2").c_str(), &Buf) == 0) + { + CompressProg = "bzip2"; + CompressProgFind = "Dir::bin::bzip2"; + From.Open(Filename + ".bz2",FileFd::ReadOnly); + } + else if (stat((Filename + ".xz").c_str(), &Buf) == 0) + { + CompressProg = "xz"; + CompressProgFind = "Dir::bin::xz"; + From.Open(Filename + ".xz",FileFd::ReadOnly); + } + else + { + return _error->Errno("decompressor", "Unable to parse file"); + } + + if (_error->PendingError() == true) + return -1; + + *FileSize = Buf.st_size; + + // Get a temp file + FILE *tmp = tmpfile(); + if (tmp == 0) + return _error->Errno("tmpfile","Unable to create a tmp file"); + *fd = dup(fileno(tmp)); + fclose(tmp); + + // Fork decompressor + pid_t Process = fork(); + if (Process < 0) + return _error->Errno("fork","Couldn't fork to run decompressor"); + + // The child + if (Process == 0) + { + dup2(From.Fd(),STDIN_FILENO); + dup2(*fd,STDOUT_FILENO); + SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDOUT_FILENO,false); + + const char *Args[3]; + string Tmp = _config->Find(CompressProgFind, CompressProg); + Args[0] = Tmp.c_str(); + Args[1] = "-d"; + Args[2] = 0; + if(execvp(Args[0],(char **)Args)) + return(_error->Errno("decompressor","decompress failed")); + /* Should never get here */ + exit(100); + } + // Wait for decompress to finish + if (ExecWait(Process,CompressProg.c_str(),false) == false) + return false; + + return true; +} // IndexCopy::CopyPackages - Copy the package files from the CD /*{{{*/ // --------------------------------------------------------------------- @@ -58,7 +134,9 @@ { struct stat Buf; if (stat(string(*I + GetFileName()).c_str(),&Buf) != 0 && - stat(string(*I + GetFileName() + ".gz").c_str(),&Buf) != 0) + stat(string(*I + GetFileName() + ".gz").c_str(),&Buf) != 0 && + stat(string(*I + GetFileName() + ".xz").c_str(),&Buf) != 0 && + stat(string(*I + GetFileName() + ".bz2").c_str(),&Buf) != 0) return _error->Errno("stat","Stat failed for %s", string(*I + GetFileName()).c_str()); TotalSize += Buf.st_size; @@ -82,46 +160,14 @@ } else { - FileFd From(*I + GetFileName() + ".gz",FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - FileSize = From.Size(); - - // Get a temp file - FILE *tmp = tmpfile(); - if (tmp == 0) - return _error->Errno("tmpfile","Unable to create a tmp file"); - Pkg.Fd(dup(fileno(tmp))); - fclose(tmp); - - // Fork gzip - pid_t Process = fork(); - if (Process < 0) - return _error->Errno("fork","Couldn't fork gzip"); - - // The child - if (Process == 0) - { - dup2(From.Fd(),STDIN_FILENO); - dup2(Pkg.Fd(),STDOUT_FILENO); - SetCloseExec(STDIN_FILENO,false); - SetCloseExec(STDOUT_FILENO,false); - - const char *Args[3]; - string Tmp = _config->Find("Dir::bin::gzip","gzip"); - Args[0] = Tmp.c_str(); - Args[1] = "-d"; - Args[2] = 0; - execvp(Args[0],(char **)Args); - exit(100); - } - - // Wait for gzip to finish - if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false) - return _error->Error("gzip failed, perhaps the disk is full."); - + int fd; + if (!DecompressFile(string(*I + GetFileName()), &fd, &FileSize)) + return _error->Errno("decompress","Decompress failed for %s", + string(*I + GetFileName()).c_str()); + Pkg.Fd(dup(fd)); Pkg.Seek(0); } + pkgTagFile Parser(&Pkg); if (_error->PendingError() == true) return false; @@ -769,8 +816,11 @@ for (vector<string>::iterator I = List.begin(); I != List.end(); I++) { struct stat Buf; + if (stat(string(*I).c_str(),&Buf) != 0 && - stat(string(*I + ".gz").c_str(),&Buf) != 0) + stat(string(*I + ".gz").c_str(),&Buf) != 0 && + stat(string(*I + ".bz2").c_str(),&Buf) != 0 && + stat(string(*I + ".xz").c_str(),&Buf) != 0) return _error->Errno("stat","Stat failed for %s", string(*I).c_str()); TotalSize += Buf.st_size; @@ -794,44 +844,10 @@ } else { - FileFd From(*I + ".gz",FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - FileSize = From.Size(); - - // Get a temp file - FILE *tmp = tmpfile(); - if (tmp == 0) - return _error->Errno("tmpfile","Unable to create a tmp file"); - Pkg.Fd(dup(fileno(tmp))); - fclose(tmp); - - // Fork gzip - pid_t Process = fork(); - if (Process < 0) - return _error->Errno("fork","Couldn't fork gzip"); - - // The child - if (Process == 0) - { - dup2(From.Fd(),STDIN_FILENO); - dup2(Pkg.Fd(),STDOUT_FILENO); - SetCloseExec(STDIN_FILENO,false); - SetCloseExec(STDOUT_FILENO,false); - - const char *Args[3]; - string Tmp = _config->Find("Dir::bin::gzip","gzip"); - Args[0] = Tmp.c_str(); - Args[1] = "-d"; - Args[2] = 0; - execvp(Args[0],(char **)Args); - exit(100); - } - - // Wait for gzip to finish - if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false) - return _error->Error("gzip failed, perhaps the disk is full."); - + int fd; + if (!DecompressFile(*I, &fd, &FileSize)) + return _error->Errno("decompress","Decompress failed for %s", (*I).c_str()); + Pkg.Fd(dup(fd)); Pkg.Seek(0); } pkgTagFile Parser(&Pkg);