X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/1809f8d29cee7a6328be806548317bc99632a61b..cce08fb5aca7dd01706cecea845b183dc62b1717:/ftparchive/writer.cc diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc index 9f053bd2c..59107e02b 100644 --- a/ftparchive/writer.cc +++ b/ftparchive/writer.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: writer.cc,v 1.6 2002/11/11 04:27:51 doogie Exp $ +// $Id: writer.cc,v 1.14 2004/03/24 01:40:43 mdz Exp $ /* ###################################################################### Writer @@ -11,28 +11,28 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#ifdef __GNUG__ -#pragma implementation "writer.h" -#endif - #include "writer.h" +#include #include #include #include #include +#include +#include #include #include #include +#include #include +#include #include #include "cachedb.h" #include "apt-ftparchive.h" #include "multicompress.h" /*}}}*/ - using namespace std; FTWScanner *FTWScanner::Owner; @@ -57,8 +57,6 @@ FTWScanner::FTWScanner() { ErrorPrinted = false; NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true); - TmpExt = 0; - Ext[0] = 0; RealPath = 0; long PMax = pathconf(".",_PC_PATH_MAX); if (PMax > 0) @@ -69,31 +67,42 @@ FTWScanner::FTWScanner() // --------------------------------------------------------------------- /* This is the FTW scanner, it processes each directory element in the directory tree. */ -int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag) +int FTWScanner::ScannerFTW(const char *File,const struct stat *sb,int Flag) { if (Flag == FTW_DNR) { Owner->NewLine(1); - c1out << "W: Unable to read directory " << File << endl; + ioprintf(c1out, _("W: Unable to read directory %s\n"), File); } if (Flag == FTW_NS) { Owner->NewLine(1); - c1out << "W: Unable to stat " << File << endl; + ioprintf(c1out, _("W: Unable to stat %s\n"), File); } if (Flag != FTW_F) return 0; - // See if it is a .deb - if (strlen(File) < 4) - return 0; - - unsigned CurExt = 0; - for (; Owner->Ext[CurExt] != 0; CurExt++) - if (strcmp(File+strlen(File)-strlen(Owner->Ext[CurExt]), - Owner->Ext[CurExt]) == 0) - break; - if (Owner->Ext[CurExt] == 0) + return ScannerFile(File, true); +} + /*}}}*/ +// FTWScanner::ScannerFile - File Scanner /*{{{*/ +// --------------------------------------------------------------------- +/* */ +int FTWScanner::ScannerFile(const char *File, bool ReadLink) +{ + const char *LastComponent = strrchr(File, '/'); + if (LastComponent == NULL) + LastComponent = File; + else + LastComponent++; + + vector::iterator I; + for(I = Owner->Patterns.begin(); I != Owner->Patterns.end(); ++I) + { + if (fnmatch((*I).c_str(), LastComponent, 0) == 0) + break; + } + if (I == Owner->Patterns.end()) return 0; /* Process it. If the file is a link then resolve it into an absolute @@ -101,7 +110,8 @@ int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag) given are not links themselves. */ char Jnk[2]; Owner->OriginalPath = File; - if (Owner->RealPath != 0 && readlink(File,Jnk,sizeof(Jnk)) != -1 && + if (ReadLink && Owner->RealPath != 0 && + readlink(File,Jnk,sizeof(Jnk)) != -1 && realpath(File,Owner->RealPath) != 0) Owner->DoPackage(Owner->RealPath); else @@ -118,16 +128,16 @@ int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag) bool Type = _error->PopMessage(Err); if (Type == true) - cerr << "E: " << Err << endl; + cerr << _("E: ") << Err << endl; else - cerr << "W: " << Err << endl; + cerr << _("W: ") << Err << endl; if (Err.find(File) != string::npos) SeenPath = true; } if (SeenPath == false) - cerr << "E: Errors apply to file '" << File << "'" << endl; + cerr << _("E: Errors apply to file ") << "'" << File << "'" << endl; return 0; } @@ -144,19 +154,19 @@ bool FTWScanner::RecursiveScan(string Dir) if (InternalPrefix.empty() == true) { if (realpath(Dir.c_str(),RealPath) == 0) - return _error->Errno("realpath","Failed to resolve %s",Dir.c_str()); + return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str()); InternalPrefix = RealPath; } // Do recursive directory searching Owner = this; - int Res = ftw(Dir.c_str(),Scanner,30); + int Res = ftw(Dir.c_str(),ScannerFTW,30); // Error treewalking? if (Res != 0) { if (_error->PendingError() == false) - _error->Errno("ftw","Tree walking failed"); + _error->Errno("ftw",_("Tree walking failed")); return false; } @@ -174,14 +184,14 @@ bool FTWScanner::LoadFileList(string Dir,string File) if (InternalPrefix.empty() == true) { if (realpath(Dir.c_str(),RealPath) == 0) - return _error->Errno("realpath","Failed to resolve %s",Dir.c_str()); + return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str()); InternalPrefix = RealPath; } Owner = this; FILE *List = fopen(File.c_str(),"r"); if (List == 0) - return _error->Errno("fopen","Failed to open %s",File.c_str()); + return _error->Errno("fopen",_("Failed to open %s"),File.c_str()); /* We are a tad tricky here.. We prefix the buffer with the directory name, that way if we need a full path with just use line.. Sneaky and @@ -205,12 +215,14 @@ bool FTWScanner::LoadFileList(string Dir,string File) FileName = Line; } +#if 0 struct stat St; int Flag = FTW_F; if (stat(FileName,&St) != 0) Flag = FTW_NS; +#endif - if (Scanner(FileName,&St,Flag) != 0) + if (ScannerFile(FileName, false) != 0) break; } @@ -223,7 +235,7 @@ bool FTWScanner::LoadFileList(string Dir,string File) /* */ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, unsigned long &DeLinkBytes, - struct stat &St) + off_t FileSize) { // See if this isn't an internaly prefix'd file name. if (InternalPrefix.empty() == false && @@ -238,25 +250,26 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, cout << endl; NewLine(1); - c1out << " DeLink " << (OriginalPath + InternalPrefix.length()) - << " [" << SizeToStr(St.st_size) << "B]" << endl << flush; + ioprintf(c1out, _(" DeLink %s [%s]\n"), (OriginalPath + InternalPrefix.length()), + SizeToStr(FileSize).c_str()); + c1out << flush; if (NoLinkAct == false) { char OldLink[400]; if (readlink(OriginalPath,OldLink,sizeof(OldLink)) == -1) - _error->Errno("readlink","Failed to readlink %s",OriginalPath); + _error->Errno("readlink",_("Failed to readlink %s"),OriginalPath); else { if (unlink(OriginalPath) != 0) - _error->Errno("unlink","Failed to unlink %s",OriginalPath); + _error->Errno("unlink",_("Failed to unlink %s"),OriginalPath); else { if (link(FileName.c_str(),OriginalPath) != 0) { // Panic! Restore the symlink symlink(OldLink,OriginalPath); - return _error->Errno("link","*** Failed to link %s to %s", + return _error->Errno("link",_("*** Failed to link %s to %s"), FileName.c_str(), OriginalPath); } @@ -264,9 +277,9 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, } } - DeLinkBytes += St.st_size; + DeLinkBytes += FileSize; if (DeLinkBytes/1024 >= DeLinkLimit) - c1out << " DeLink limit of " << SizeToStr(DeLinkBytes) << "B hit." << endl; + ioprintf(c1out, _(" DeLink limit of %sB hit.\n"), SizeToStr(DeLinkBytes).c_str()); } FileName = OriginalPath; @@ -275,31 +288,23 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, return true; } /*}}}*/ -// FTWScanner::SetExts - Set extensions to support /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool FTWScanner::SetExts(string Vals) -{ - delete [] TmpExt; - TmpExt = new char[Vals.length()+1]; - strcpy(TmpExt,Vals.c_str()); - return TokSplitString(' ',TmpExt,(char **)Ext,sizeof(Ext)/sizeof(Ext[0])); -} - /*}}}*/ // PackagesWriter::PackagesWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides) : - Db(DB),Stats(Db.Stats) +PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides, + string aArch) : + Db(DB),Stats(Db.Stats), Arch(aArch) { Output = stdout; - Ext[0] = ".deb"; - Ext[1] = 0; + SetExts(".deb .udeb .foo .bar .baz"); + AddPattern("*.deb"); DeLinkLimit = 0; // Process the command line options DoMD5 = _config->FindB("APT::FTPArchive::MD5",true); + DoSHA1 = _config->FindB("APT::FTPArchive::SHA1",true); + DoSHA256 = _config->FindB("APT::FTPArchive::SHA256",true); DoContents = _config->FindB("APT::FTPArchive::Contents",true); NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false); @@ -317,60 +322,85 @@ PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides) : _error->DumpErrors(); } + /*}}}*/ +// FTWScanner::SetExts - Set extensions to support /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool FTWScanner::SetExts(string Vals) +{ + ClearPatterns(); + string::size_type Start = 0; + while (Start <= Vals.length()-1) + { + string::size_type Space = Vals.find(' ',Start); + string::size_type Length; + if (Space == string::npos) + { + Length = Vals.length()-Start; + } + else + { + Length = Space-Start; + } + AddPattern(string("*") + Vals.substr(Start, Length)); + Start += Length + 1; + } + + return true; +} + /*}}}*/ // PackagesWriter::DoPackage - Process a single package /*{{{*/ // --------------------------------------------------------------------- /* This method takes a package and gets its control information and - MD5 then writes out a control record with the proper fields rewritten - and the path/size/hash appended. */ + MD5, SHA1 and SHA256 then writes out a control record with the proper fields + rewritten and the path/size/hash appended. */ bool PackagesWriter::DoPackage(string FileName) { - // Open the archive - FileFd F(FileName,FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - - // Stat the file for later - struct stat St; - if (fstat(F.Fd(),&St) != 0) - return _error->Errno("fstat","Failed to stat %s",FileName.c_str()); - // Pull all the data we need form the DB - string MD5Res; - if (Db.SetFile(FileName,St,&F) == false || - Db.LoadControl() == false || - (DoContents == true && Db.LoadContents(true) == false) || - (DoMD5 == true && Db.GetMD5(MD5Res,false) == false)) + if (Db.GetFileInfo(FileName, true, DoContents, true, DoMD5, DoSHA1, DoSHA256) + == false) + { return false; + } - if (Delink(FileName,OriginalPath,Stats.DeLinkBytes,St) == false) + off_t FileSize = Db.GetFileSize(); + if (Delink(FileName,OriginalPath,Stats.DeLinkBytes,FileSize) == false) return false; // Lookup the overide information pkgTagSection &Tags = Db.Control.Section; string Package = Tags.FindS("Package"); - Override::Item Tmp; - Override::Item *OverItem = Over.GetItem(Package); + string Architecture; + // if we generate a Packages file for a given arch, we use it to + // look for overrides. if we run in "simple" mode without the + // "Architecures" variable in the config we use the architecure value + // from the deb file + if(Arch != "") + Architecture = Arch; + else + Architecture = Tags.FindS("Architecture"); + auto_ptr OverItem(Over.GetItem(Package,Architecture)); if (Package.empty() == true) - return _error->Error("Archive had no package field"); - + return _error->Error(_("Archive had no package field")); + // If we need to do any rewriting of the header do it now.. - if (OverItem == 0) + if (OverItem.get() == 0) { if (NoOverride == false) { NewLine(1); - c1out << " " << Package << " has no override entry" << endl; + ioprintf(c1out, _(" %s has no override entry\n"), Package.c_str()); } - OverItem = &Tmp; - Tmp.FieldOverride["Section"] = Tags.FindS("Section"); - Tmp.Priority = Tags.FindS("Priority"); + OverItem = auto_ptr(new Override::Item); + OverItem->FieldOverride["Section"] = Tags.FindS("Section"); + OverItem->Priority = Tags.FindS("Priority"); } char Size[40]; - sprintf(Size,"%lu",St.st_size); + sprintf(Size,"%lu", (unsigned long) FileSize); // Strip the DirStrip prefix from the FileName and add the PathPrefix string NewFileName; @@ -390,7 +420,9 @@ bool PackagesWriter::DoPackage(string FileName) unsigned int End = 0; SetTFRewriteData(Changes[End++], "Size", Size); - SetTFRewriteData(Changes[End++], "MD5sum", MD5Res.c_str()); + SetTFRewriteData(Changes[End++], "MD5sum", Db.MD5Res.c_str()); + SetTFRewriteData(Changes[End++], "SHA1", Db.SHA1Res.c_str()); + SetTFRewriteData(Changes[End++], "SHA256", Db.SHA256Res.c_str()); SetTFRewriteData(Changes[End++], "Filename", NewFileName.c_str()); SetTFRewriteData(Changes[End++], "Priority", OverItem->Priority.c_str()); SetTFRewriteData(Changes[End++], "Status", 0); @@ -404,9 +436,8 @@ bool PackagesWriter::DoPackage(string FileName) if (NoOverride == false) { NewLine(1); - c1out << " " << Package << " maintainer is " << - Tags.FindS("Maintainer") << " not " << - OverItem->OldMaint << endl; + ioprintf(c1out, _(" %s maintainer is %s not %s\n"), + Package.c_str(), Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str()); } } @@ -448,8 +479,7 @@ SourcesWriter::SourcesWriter(string BOverrides,string SOverrides, string ExtOverrides) { Output = stdout; - Ext[0] = ".dsc"; - Ext[1] = 0; + AddPattern("*.dsc"); DeLinkLimit = 0; Buffer = 0; BufSize = 0; @@ -463,6 +493,10 @@ SourcesWriter::SourcesWriter(string BOverrides,string SOverrides, else NoOverride = true; + // WTF?? The logic above: if we can't read binary overrides, don't even try + // reading source overrides. if we can read binary overrides, then say there + // are no overrides. THIS MAKES NO SENSE! -- ajt@d.o, 2006/02/28 + if (ExtOverrides.empty() == false) SOver.ReadExtraOverride(ExtOverrides); @@ -535,10 +569,10 @@ bool SourcesWriter::DoPackage(string FileName) // Lookup the overide information, finding first the best priority. string BestPrio; - char Buffer[1000]; string Bins = Tags.FindS("Binary"); - Override::Item *OverItem = 0; - if (Bins.empty() == false && Bins.length() < sizeof(Buffer)) + char Buffer[Bins.length() + 1]; + auto_ptr OverItem(0); + if (Bins.empty() == false) { strcpy(Buffer,Bins.c_str()); @@ -550,11 +584,9 @@ bool SourcesWriter::DoPackage(string FileName) unsigned char BestPrioV = pkgCache::State::Extra; for (unsigned I = 0; BinList[I] != 0; I++) { - Override::Item *Itm = BOver.GetItem(BinList[I]); - if (Itm == 0) + auto_ptr Itm(BOver.GetItem(BinList[I])); + if (Itm.get() == 0) continue; - if (OverItem == 0) - OverItem = Itm; unsigned char NewPrioV = debListParser::GetPrio(Itm->Priority); if (NewPrioV < BestPrioV || BestPrio.empty() == true) @@ -562,28 +594,36 @@ bool SourcesWriter::DoPackage(string FileName) BestPrioV = NewPrioV; BestPrio = Itm->Priority; } + + if (OverItem.get() == 0) + OverItem = Itm; } } // If we need to do any rewriting of the header do it now.. - Override::Item Tmp; - if (OverItem == 0) + if (OverItem.get() == 0) { if (NoOverride == false) { NewLine(1); - c1out << " " << Tags.FindS("Source") << " has no override entry" << endl; + ioprintf(c1out, _(" %s has no override entry\n"), Tags.FindS("Source").c_str()); } - OverItem = &Tmp; + OverItem = auto_ptr(new Override::Item); } - Override::Item *SOverItem = SOver.GetItem(Tags.FindS("Source")); - if (SOverItem == 0) + auto_ptr SOverItem(SOver.GetItem(Tags.FindS("Source"))); + // const auto_ptr autoSOverItem(SOverItem); + if (SOverItem.get() == 0) { - SOverItem = BOver.GetItem(Tags.FindS("Source")); - if (SOverItem == 0) - SOverItem = OverItem; + ioprintf(c1out, _(" %s has no source override entry\n"), Tags.FindS("Source").c_str()); + SOverItem = auto_ptr(BOver.GetItem(Tags.FindS("Source"))); + if (SOverItem.get() == 0) + { + ioprintf(c1out, _(" %s has no binary override entry either\n"), Tags.FindS("Source").c_str()); + SOverItem = auto_ptr(new Override::Item); + *SOverItem = *OverItem; + } } // Add the dsc to the files hash list @@ -625,7 +665,7 @@ bool SourcesWriter::DoPackage(string FileName) realpath(OriginalPath.c_str(),RealPath) != 0) { string RP = RealPath; - if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St) == false) + if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St.st_size) == false) return false; } } @@ -654,9 +694,8 @@ bool SourcesWriter::DoPackage(string FileName) if (NoOverride == false) { NewLine(1); - c1out << " " << Package << " maintainer is " << - Tags.FindS("Maintainer") << " not " << - OverItem->OldMaint << endl; + ioprintf(c1out, _(" %s maintainer is %s not %s\n"), Package.c_str(), + Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str()); } } if (NewMaint.empty() == false) @@ -686,8 +725,7 @@ ContentsWriter::ContentsWriter(string DB) : Db(DB), Stats(Db.Stats) { - Ext[0] = ".deb"; - Ext[1] = 0; + AddPattern("*.deb"); Output = stdout; } /*}}}*/ @@ -697,26 +735,14 @@ ContentsWriter::ContentsWriter(string DB) : determine what the package name is. */ bool ContentsWriter::DoPackage(string FileName,string Package) { - // Open the archive - FileFd F(FileName,FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - - // Stat the file for later - struct stat St; - if (fstat(F.Fd(),&St) != 0) - return _error->Errno("fstat","Failed too stat %s",FileName.c_str()); - - // Ready the DB - if (Db.SetFile(FileName,St,&F) == false || - Db.LoadContents(false) == false) + if (!Db.GetFileInfo(FileName, Package.empty(), true, false, false, false, false)) + { return false; + } // Parse the package name if (Package.empty() == true) { - if (Db.LoadControl() == false) - return false; Package = Db.Control.Section.FindS("Package"); } @@ -736,7 +762,7 @@ bool ContentsWriter::ReadFromPkgs(string PkgFile,string PkgCompress) // Open the package file int CompFd = -1; - int Proc = -1; + pid_t Proc = -1; if (Pkgs.OpenOld(CompFd,Proc) == false) return false; @@ -777,4 +803,141 @@ bool ContentsWriter::ReadFromPkgs(string PkgFile,string PkgCompress) return true; } + + /*}}}*/ + +// ReleaseWriter::ReleaseWriter - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +ReleaseWriter::ReleaseWriter(string DB) +{ + AddPattern("Packages"); + AddPattern("Packages.gz"); + AddPattern("Packages.bz2"); + AddPattern("Sources"); + AddPattern("Sources.gz"); + AddPattern("Sources.bz2"); + AddPattern("Release"); + AddPattern("md5sum.txt"); + + Output = stdout; + time_t now = time(NULL); + char datestr[128]; + if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S UTC", + gmtime(&now)) == 0) + { + datestr[0] = '\0'; + } + + map Fields; + Fields["Origin"] = ""; + Fields["Label"] = ""; + Fields["Suite"] = ""; + Fields["Version"] = ""; + Fields["Codename"] = ""; + Fields["Date"] = datestr; + Fields["Architectures"] = ""; + Fields["Components"] = ""; + Fields["Description"] = ""; + + for(map::const_iterator I = Fields.begin(); + I != Fields.end(); + ++I) + { + string Config = string("APT::FTPArchive::Release::") + (*I).first; + string Value = _config->Find(Config, (*I).second.c_str()); + if (Value == "") + continue; + + fprintf(Output, "%s: %s\n", (*I).first.c_str(), Value.c_str()); + } +} + /*}}}*/ +// ReleaseWriter::DoPackage - Process a single package /*{{{*/ +// --------------------------------------------------------------------- +bool ReleaseWriter::DoPackage(string FileName) +{ + // Strip the DirStrip prefix from the FileName and add the PathPrefix + string NewFileName; + if (DirStrip.empty() == false && + FileName.length() > DirStrip.length() && + stringcmp(FileName.begin(),FileName.begin() + DirStrip.length(), + DirStrip.begin(),DirStrip.end()) == 0) + { + NewFileName = string(FileName.begin() + DirStrip.length(),FileName.end()); + while (NewFileName[0] == '/') + NewFileName = string(NewFileName.begin() + 1,NewFileName.end()); + } + else + NewFileName = FileName; + + if (PathPrefix.empty() == false) + NewFileName = flCombine(PathPrefix,NewFileName); + + FileFd fd(FileName, FileFd::ReadOnly); + + if (!fd.IsOpen()) + { + return false; + } + + CheckSums[NewFileName].size = fd.Size(); + + MD5Summation MD5; + MD5.AddFD(fd.Fd(), fd.Size()); + CheckSums[NewFileName].MD5 = MD5.Result(); + + fd.Seek(0); + SHA1Summation SHA1; + SHA1.AddFD(fd.Fd(), fd.Size()); + CheckSums[NewFileName].SHA1 = SHA1.Result(); + + fd.Seek(0); + SHA256Summation SHA256; + SHA256.AddFD(fd.Fd(), fd.Size()); + CheckSums[NewFileName].SHA256 = SHA256.Result(); + + fd.Close(); + + return true; +} + /*}}}*/ +// ReleaseWriter::Finish - Output the checksums /*{{{*/ +// --------------------------------------------------------------------- +void ReleaseWriter::Finish() +{ + fprintf(Output, "MD5Sum:\n"); + for(map::iterator I = CheckSums.begin(); + I != CheckSums.end(); + ++I) + { + fprintf(Output, " %s %16ld %s\n", + (*I).second.MD5.c_str(), + (*I).second.size, + (*I).first.c_str()); + } + + fprintf(Output, "SHA1:\n"); + for(map::iterator I = CheckSums.begin(); + I != CheckSums.end(); + ++I) + { + fprintf(Output, " %s %16ld %s\n", + (*I).second.SHA1.c_str(), + (*I).second.size, + (*I).first.c_str()); + } + + fprintf(Output, "SHA256:\n"); + for(map::iterator I = CheckSums.begin(); + I != CheckSums.end(); + ++I) + { + fprintf(Output, " %s %16ld %s\n", + (*I).second.SHA256.c_str(), + (*I).second.size, + (*I).first.c_str()); + } +} +