// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: writer.cc,v 1.2 2001/02/20 07:03:18 jgg Exp $
+// $Id: writer.cc,v 1.14 2004/03/24 01:40:43 mdz Exp $
/* ######################################################################
Writer
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "writer.h"
-#endif
-
#include "writer.h"
+#include <apti18n.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/md5.h>
+#include <apt-pkg/sha1.h>
+#include <apt-pkg/sha256.h>
#include <apt-pkg/deblistparser.h>
#include <sys/types.h>
#include <unistd.h>
+#include <ctime>
#include <ftw.h>
+#include <fnmatch.h>
+#include <iostream>
+#include <memory>
#include "cachedb.h"
#include "apt-ftparchive.h"
#include "multicompress.h"
/*}}}*/
-
+using namespace std;
FTWScanner *FTWScanner::Owner;
+// SetTFRewriteData - Helper for setting rewrite lists /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+inline void SetTFRewriteData(struct TFRewriteData &tfrd,
+ const char *tag,
+ const char *rewrite,
+ const char *newtag = 0)
+{
+ tfrd.Tag = tag;
+ tfrd.Rewrite = rewrite;
+ tfrd.NewTag = newtag;
+}
+ /*}}}*/
+
// FTWScanner::FTWScanner - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
{
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)
// ---------------------------------------------------------------------
/* 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<string>::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
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
bool Type = _error->PopMessage(Err);
if (Type == true)
- c1out << "E: " << Err << endl;
+ cerr << _("E: ") << Err << endl;
else
- c1out << "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;
}
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;
}
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
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;
}
/* */
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 &&
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);
}
}
}
- 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;
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) :
- 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);
+ LongDescription = _config->FindB("APT::FTPArchive::LongDescription",true);
if (Db.Loaded() == false)
DoContents = false;
-
+
// Read the override file
if (Overrides.empty() == false && Over.ReadOverride(Overrides) == false)
return;
else
NoOverride = true;
+
+ if (ExtOverrides.empty() == false)
+ Over.ReadExtraOverride(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<Override::Item> 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.Section = Tags.FindS("Section");
- Tmp.Priority = Tags.FindS("Priority");
+ OverItem = auto_ptr<Override::Item>(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;
NewFileName = FileName;
if (PathPrefix.empty() == false)
NewFileName = flCombine(PathPrefix,NewFileName);
-
+
+ /* Configuration says we don't want to include the long Description
+ in the package file - instead we want to ship a separated file */
+ string desc;
+ if (LongDescription == false) {
+ desc = Tags.FindS("Description").append("\n");
+ OverItem->FieldOverride["Description"] = desc.substr(0, desc.find('\n')).c_str();
+ }
+
// This lists all the changes to the fields we are going to make.
- TFRewriteData Changes[] = {{"Size",Size},
- {"MD5sum",MD5Res.c_str()},
- {"Filename",NewFileName.c_str()},
- {"Section",OverItem->Section.c_str()},
- {"Priority",OverItem->Priority.c_str()},
- {"Status",0},
- {"Optional",0},
- {}, // For maintainer
- {}, // For Suggests
- {}};
+ // (7 hardcoded + maintainer + suggests + end marker)
+ TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1+1];
+
unsigned int End = 0;
- for (End = 0; Changes[End].Tag != 0; End++);
-
+ SetTFRewriteData(Changes[End++], "Size", Size);
+ 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);
+ SetTFRewriteData(Changes[End++], "Optional", 0);
+
+ string DescriptionMd5;
+ if (LongDescription == false) {
+ MD5Summation descmd5;
+ descmd5.Add(desc.c_str());
+ DescriptionMd5 = descmd5.Result().Value();
+ SetTFRewriteData(Changes[End++], "Description-md5", DescriptionMd5.c_str());
+ }
+
// Rewrite the maintainer field if necessary
bool MaintFailed;
string NewMaint = OverItem->SwapMaint(Tags.FindS("Maintainer"),MaintFailed);
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)
- {
- Changes[End].Rewrite = NewMaint.c_str();
- Changes[End++].Tag = "Maintainer";
- }
+ SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
/* Get rid of the Optional tag. This is an ugly, ugly, ugly hack that
- dpkg-scanpackages does.. Well sort of. dpkg-scanpackages just does renaming
+ dpkg-scanpackages does. Well sort of. dpkg-scanpackages just does renaming
but dpkg does this append bit. So we do the append bit, at least that way the
status file and package file will remain similar. There are other transforms
but optional is the only legacy one still in use for some lazy reason. */
{
if (Tags.FindS("Suggests").empty() == false)
OptionalStr = Tags.FindS("Suggests") + ", " + OptionalStr;
- Changes[End].Rewrite = OptionalStr.c_str();
- Changes[End++].Tag = "Suggests";
+ SetTFRewriteData(Changes[End++], "Suggests", OptionalStr.c_str());
}
-
+
+ for (map<string,string>::iterator I = OverItem->FieldOverride.begin();
+ I != OverItem->FieldOverride.end(); I++)
+ SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
+
+ SetTFRewriteData(Changes[End++], 0, 0);
+
// Rewrite and store the fields.
if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes) == false)
return false;
// SourcesWriter::SourcesWriter - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-SourcesWriter::SourcesWriter(string BOverrides,string SOverrides)
+SourcesWriter::SourcesWriter(string BOverrides,string SOverrides,
+ string ExtOverrides)
{
Output = stdout;
- Ext[0] = ".dsc";
- Ext[1] = 0;
+ AddPattern("*.dsc");
DeLinkLimit = 0;
Buffer = 0;
BufSize = 0;
return;
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);
- if (SOverrides.empty() == false && FileExists(SOverrides) == true &&
- SOver.ReadOverride(SOverrides,true) == false)
- return;
-// _error->DumpErrors();
+ if (SOverrides.empty() == false && FileExists(SOverrides) == true)
+ SOver.ReadOverride(SOverrides,true);
}
/*}}}*/
// SourcesWriter::DoPackage - Process a single package /*{{{*/
// 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<Override::Item> OverItem(0);
+ if (Bins.empty() == false)
{
strcpy(Buffer,Bins.c_str());
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<Override::Item> 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)
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<Override::Item>(new Override::Item);
}
- Override::Item *SOverItem = SOver.GetItem(Tags.FindS("Source"));
- if (SOverItem == 0)
+ auto_ptr<Override::Item> SOverItem(SOver.GetItem(Tags.FindS("Source")));
+ // const auto_ptr<Override::Item> 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<Override::Item>(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<Override::Item>(new Override::Item);
+ *SOverItem = *OverItem;
+ }
}
// Add the dsc to the files hash list
string NewFileName;
if (DirStrip.empty() == false &&
FileName.length() > DirStrip.length() &&
- stringcmp(OriginalPath,OriginalPath + DirStrip.length(),
- DirStrip.begin(),DirStrip.end()) == 0)
+ stringcmp(DirStrip,OriginalPath,OriginalPath + DirStrip.length()) == 0)
NewFileName = string(OriginalPath + DirStrip.length());
else
NewFileName = OriginalPath;
if (PathPrefix.empty() == false)
NewFileName = flCombine(PathPrefix,NewFileName);
-
+
string Directory = flNotFile(OriginalPath);
string Package = Tags.FindS("Source");
-
+
// Perform the delinking operation over all of the files
string ParseJnk;
const char *C = Files;
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;
}
}
Directory = flNotFile(NewFileName);
if (Directory.length() > 2)
Directory.erase(Directory.end()-1);
-
+
// This lists all the changes to the fields we are going to make.
- TFRewriteData Changes[] = {{"Source",Package.c_str(),"Package"},
- {"Files",Files},
- {"Directory",Directory.c_str()},
- {"Section",SOverItem->Section.c_str()},
- {"Priority",BestPrio.c_str()},
- {"Status",0},
- {}, // For maintainer
- {}};
+ // (5 hardcoded + maintainer + end marker)
+ TFRewriteData Changes[5+1+SOverItem->FieldOverride.size()+1];
+
unsigned int End = 0;
- for (End = 0; Changes[End].Tag != 0; End++);
+ SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
+ SetTFRewriteData(Changes[End++],"Files",Files);
+ if (Directory != "./")
+ SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
+ SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
+ SetTFRewriteData(Changes[End++],"Status",0);
// Rewrite the maintainer field if necessary
bool MaintFailed;
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)
- {
- Changes[End].Rewrite = NewMaint.c_str();
- Changes[End++].Tag = "Maintainer";
- }
+ SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
+
+ for (map<string,string>::iterator I = SOverItem->FieldOverride.begin();
+ I != SOverItem->FieldOverride.end(); I++)
+ SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str());
+
+ SetTFRewriteData(Changes[End++], 0, 0);
// Rewrite and store the fields.
if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes) == false)
Db(DB), Stats(Db.Stats)
{
- Ext[0] = ".deb";
- Ext[1] = 0;
+ AddPattern("*.deb");
Output = stdout;
}
/*}}}*/
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");
}
// Open the package file
int CompFd = -1;
- int Proc = -1;
+ pid_t Proc = -1;
if (Pkgs.OpenOld(CompFd,Proc) == false)
return false;
return true;
}
+
/*}}}*/
+
+// ReleaseWriter::ReleaseWriter - Constructor /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+ReleaseWriter::ReleaseWriter(string DB)
+{
+ AddPattern("Packages");
+ AddPattern("Packages.gz");
+ AddPattern("Packages.bz2");
+ AddPattern("Packages.lzma");
+ AddPattern("Sources");
+ AddPattern("Sources.gz");
+ AddPattern("Sources.bz2");
+ AddPattern("Sources.lzma");
+ 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<string,string> Fields;
+ Fields["Origin"] = "";
+ Fields["Label"] = "";
+ Fields["Suite"] = "";
+ Fields["Version"] = "";
+ Fields["Codename"] = "";
+ Fields["Date"] = datestr;
+ Fields["Architectures"] = "";
+ Fields["Components"] = "";
+ Fields["Description"] = "";
+
+ for(map<string,string>::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<string,struct CheckSum>::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<string,struct CheckSum>::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<string,struct CheckSum>::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());
+ }
+}
+