##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "writer.h"
-#endif
-
#include "writer.h"
#include <apti18n.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 <ftw.h>
#include <fnmatch.h>
#include <iostream>
+#include <memory>
#include "cachedb.h"
#include "apt-ftparchive.h"
{
ErrorPrinted = false;
NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
- RealPath = 0;
- long PMax = pathconf(".",_PC_PATH_MAX);
- if (PMax > 0)
- RealPath = new char[PMax];
}
/*}}}*/
// FTWScanner::Scanner - FTW Scanner /*{{{*/
// ---------------------------------------------------------------------
/* 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)
{
if (Flag != FTW_F)
return 0;
+ return ScannerFile(File, true);
+}
+ /*}}}*/
+// FTWScanner::ScannerFile - File Scanner /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int FTWScanner::ScannerFile(const char *File, bool ReadLink)
+{
const char *LastComponent = strrchr(File, '/');
+ char *RealPath = NULL;
+
if (LastComponent == NULL)
LastComponent = File;
else
given are not links themselves. */
char Jnk[2];
Owner->OriginalPath = File;
- if (Owner->RealPath != 0 && readlink(File,Jnk,sizeof(Jnk)) != -1 &&
- realpath(File,Owner->RealPath) != 0)
- Owner->DoPackage(Owner->RealPath);
+ if (ReadLink &&
+ readlink(File,Jnk,sizeof(Jnk)) != -1 &&
+ (RealPath = realpath(File,NULL)) != 0)
+ {
+ Owner->DoPackage(RealPath);
+ free(RealPath);
+ }
else
Owner->DoPackage(File);
/* */
bool FTWScanner::RecursiveScan(string Dir)
{
+ char *RealPath = NULL;
/* If noprefix is set then jam the scan root in, so we don't generate
link followed paths out of control */
if (InternalPrefix.empty() == true)
{
- if (realpath(Dir.c_str(),RealPath) == 0)
+ if ((RealPath = realpath(Dir.c_str(),NULL)) == 0)
return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
- InternalPrefix = RealPath;
+ InternalPrefix = RealPath;
+ free(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)
of files from another file. */
bool FTWScanner::LoadFileList(string Dir,string File)
{
+ char *RealPath = NULL;
/* If noprefix is set then jam the scan root in, so we don't generate
link followed paths out of control */
if (InternalPrefix.empty() == true)
{
- if (realpath(Dir.c_str(),RealPath) == 0)
+ if ((RealPath = realpath(Dir.c_str(),NULL)) == 0)
return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
InternalPrefix = RealPath;
+ free(RealPath);
}
Owner = this;
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 &&
NewLine(1);
ioprintf(c1out, _(" DeLink %s [%s]\n"), (OriginalPath + InternalPrefix.length()),
- SizeToStr(St.st_size).c_str());
+ SizeToStr(FileSize).c_str());
c1out << flush;
if (NoLinkAct == false)
}
}
- DeLinkBytes += St.st_size;
+ DeLinkBytes += FileSize;
if (DeLinkBytes/1024 >= DeLinkLimit)
ioprintf(c1out, _(" DeLink limit of %sB hit.\n"), SizeToStr(DeLinkBytes).c_str());
}
// 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;
// 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
}
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.
// (7 hardcoded + maintainer + suggests + end marker)
- TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1];
+ TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1+1];
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);
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);
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. */
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);
char *BlkEnd = Buffer + St.st_size;
MD5Summation MD5;
MD5.Add((unsigned char *)Start,BlkEnd - Start);
-
+
+ SHA1Summation SHA1;
+ SHA256Summation SHA256;
+ SHA1.Add((unsigned char *)Start,BlkEnd - Start);
+ SHA256.Add((unsigned char *)Start,BlkEnd - Start);
+
// Add an extra \n to the end, just in case
*BlkEnd++ = '\n';
}
auto_ptr<Override::Item> SOverItem(SOver.GetItem(Tags.FindS("Source")));
- const auto_ptr<Override::Item> autoSOverItem(SOverItem);
+ // const auto_ptr<Override::Item> autoSOverItem(SOverItem);
if (SOverItem.get() == 0)
{
+ 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 const strippedName = flNotDir(FileName);
char Files[1000];
snprintf(Files,sizeof(Files),"\n %s %lu %s\n %s",
string(MD5.Result()).c_str(),St.st_size,
- flNotDir(FileName).c_str(),
+ strippedName.c_str(),
Tags.FindS("Files").c_str());
-
+
+ char ChecksumsSha1[1000];
+ snprintf(ChecksumsSha1,sizeof(ChecksumsSha1),"\n %s %lu %s\n %s",
+ string(SHA1.Result()).c_str(),St.st_size,
+ strippedName.c_str(),
+ Tags.FindS("Checksums-Sha1").c_str());
+
+ char ChecksumsSha256[1000];
+ snprintf(ChecksumsSha256,sizeof(ChecksumsSha256),"\n %s %lu %s\n %s",
+ string(SHA256.Result()).c_str(),St.st_size,
+ strippedName.c_str(),
+ Tags.FindS("Checksums-Sha256").c_str());
+
// Strip the DirStrip prefix from the FileName and add the PathPrefix
string NewFileName;
if (DirStrip.empty() == false &&
// Perform the delinking operation over all of the files
string ParseJnk;
const char *C = Files;
+ char *RealPath = NULL;
for (;isspace(*C); C++);
while (*C != 0)
{
char Jnk[2];
string OriginalPath = Directory + ParseJnk;
- if (RealPath != 0 && readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 &&
- realpath(OriginalPath.c_str(),RealPath) != 0)
+ if (readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 &&
+ (RealPath = realpath(OriginalPath.c_str(),NULL)) != 0)
{
string RP = RealPath;
- if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St) == false)
+ free(RealPath);
+ if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St.st_size) == false)
return false;
}
}
Directory.erase(Directory.end()-1);
// This lists all the changes to the fields we are going to make.
- // (5 hardcoded + maintainer + end marker)
- TFRewriteData Changes[5+1+SOverItem->FieldOverride.size()+1];
+ // (5 hardcoded + checksums + maintainer + end marker)
+ TFRewriteData Changes[5+2+1+SOverItem->FieldOverride.size()+1];
unsigned int End = 0;
SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
SetTFRewriteData(Changes[End++],"Files",Files);
+ SetTFRewriteData(Changes[End++],"Checksums-Sha1",ChecksumsSha1);
+ SetTFRewriteData(Changes[End++],"Checksums-Sha256",ChecksumsSha256);
if (Directory != "./")
SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
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");
}
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");
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;
(*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());
+ }
}