X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/c55451ff2e5a098a6431dfd1be322f7113a86002..99aa69c74f27a70d585510b817561fbf20ac7fb5:/ftparchive/writer.cc diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc index 4e6c9a77d..58e32dade 100644 --- a/ftparchive/writer.cc +++ b/ftparchive/writer.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "cachedb.h" @@ -54,14 +55,10 @@ inline void SetTFRewriteData(struct TFRewriteData &tfrd, // FTWScanner::FTWScanner - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -FTWScanner::FTWScanner() +FTWScanner::FTWScanner(string const &Arch): Arch(Arch) { 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 /*{{{*/ @@ -89,15 +86,17 @@ int FTWScanner::ScannerFTW(const char *File,const struct stat *sb,int Flag) // FTWScanner::ScannerFile - File Scanner /*{{{*/ // --------------------------------------------------------------------- /* */ -int FTWScanner::ScannerFile(const char *File, bool ReadLink) +int FTWScanner::ScannerFile(const char *File, bool const &ReadLink) { const char *LastComponent = strrchr(File, '/'); + char *RealPath = NULL; + if (LastComponent == NULL) LastComponent = File; else LastComponent++; - vector::iterator I; + vector::const_iterator I; for(I = Owner->Patterns.begin(); I != Owner->Patterns.end(); ++I) { if (fnmatch((*I).c_str(), LastComponent, 0) == 0) @@ -111,10 +110,13 @@ int FTWScanner::ScannerFile(const char *File, bool ReadLink) given are not links themselves. */ char Jnk[2]; Owner->OriginalPath = File; - if (ReadLink && Owner->RealPath != 0 && + if (ReadLink && readlink(File,Jnk,sizeof(Jnk)) != -1 && - realpath(File,Owner->RealPath) != 0) - Owner->DoPackage(Owner->RealPath); + (RealPath = realpath(File,NULL)) != 0) + { + Owner->DoPackage(RealPath); + free(RealPath); + } else Owner->DoPackage(File); @@ -127,7 +129,7 @@ int FTWScanner::ScannerFile(const char *File, bool ReadLink) { Owner->NewLine(1); - bool Type = _error->PopMessage(Err); + bool const Type = _error->PopMessage(Err); if (Type == true) cerr << _("E: ") << Err << endl; else @@ -148,20 +150,22 @@ int FTWScanner::ScannerFile(const char *File, bool ReadLink) // FTWScanner::RecursiveScan - Just scan a directory tree /*{{{*/ // --------------------------------------------------------------------- /* */ -bool FTWScanner::RecursiveScan(string Dir) +bool FTWScanner::RecursiveScan(string const &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(),ScannerFTW,30); + int const Res = ftw(Dir.c_str(),ScannerFTW,30); // Error treewalking? if (Res != 0) @@ -178,15 +182,17 @@ bool FTWScanner::RecursiveScan(string Dir) // --------------------------------------------------------------------- /* This is an alternative to using FTW to locate files, it reads the list of files from another file. */ -bool FTWScanner::LoadFileList(string Dir,string File) +bool FTWScanner::LoadFileList(string const &Dir, string const &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; @@ -236,7 +242,7 @@ bool FTWScanner::LoadFileList(string Dir,string File) /* */ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, unsigned long &DeLinkBytes, - off_t FileSize) + off_t const &FileSize) { // See if this isn't an internaly prefix'd file name. if (InternalPrefix.empty() == false && @@ -293,26 +299,26 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, // PackagesWriter::PackagesWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides, - string aArch) : - Db(DB),Stats(Db.Stats), Arch(aArch) +PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string const &ExtOverrides, + string const &Arch) : + FTWScanner(Arch), Db(DB), Stats(Db.Stats), TransWriter(NULL) { Output = stdout; - SetExts(".deb .udeb .foo .bar .baz"); - AddPattern("*.deb"); + SetExts(".deb .udeb"); 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); + DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false); 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; @@ -328,23 +334,22 @@ PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides, // FTWScanner::SetExts - Set extensions to support /*{{{*/ // --------------------------------------------------------------------- /* */ -bool FTWScanner::SetExts(string Vals) +bool FTWScanner::SetExts(string const &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) + string::size_type const Space = Vals.find(' ',Start); + string::size_type const Length = ((Space == string::npos) ? Vals.length() : Space) - Start; + if ( Arch.empty() == false ) { - Length = Vals.length()-Start; + AddPattern(string("*_") + Arch + Vals.substr(Start, Length)); + AddPattern(string("*_all") + Vals.substr(Start, Length)); } else - { - Length = Space-Start; - } - AddPattern(string("*") + Vals.substr(Start, Length)); + AddPattern(string("*") + Vals.substr(Start, Length)); + Start += Length + 1; } @@ -360,7 +365,7 @@ bool FTWScanner::SetExts(string Vals) bool PackagesWriter::DoPackage(string FileName) { // Pull all the data we need form the DB - if (Db.GetFileInfo(FileName, true, DoContents, true, DoMD5, DoSHA1, DoSHA256) + if (Db.GetFileInfo(FileName, true, DoContents, true, DoMD5, DoSHA1, DoSHA256, DoAlwaysStat) == false) { return false; @@ -444,6 +449,8 @@ bool PackagesWriter::DoPackage(string FileName) descmd5.Add(desc.c_str()); DescriptionMd5 = descmd5.Result().Value(); SetTFRewriteData(Changes[End++], "Description-md5", DescriptionMd5.c_str()); + if (TransWriter != NULL) + TransWriter->DoPackage(Package, desc, DescriptionMd5); } // Rewrite the maintainer field if necessary @@ -475,7 +482,7 @@ bool PackagesWriter::DoPackage(string FileName) SetTFRewriteData(Changes[End++], "Suggests", OptionalStr.c_str()); } - for (map::iterator I = OverItem->FieldOverride.begin(); + for (map::const_iterator I = OverItem->FieldOverride.begin(); I != OverItem->FieldOverride.end(); I++) SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str()); @@ -490,11 +497,60 @@ bool PackagesWriter::DoPackage(string FileName) } /*}}}*/ +// TranslationWriter::TranslationWriter - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* Create a Translation-Master file for this Packages file */ +TranslationWriter::TranslationWriter(string const &File, string const &TransCompress, + mode_t const &Permissions) : Output(NULL), + RefCounter(0) +{ + if (File.empty() == true) + return; + + Comp = new MultiCompress(File, TransCompress, Permissions); + Output = Comp->Input; +} + /*}}}*/ +// TranslationWriter::DoPackage - Process a single package /*{{{*/ +// --------------------------------------------------------------------- +/* Create a Translation-Master file for this Packages file */ +bool TranslationWriter::DoPackage(string const &Pkg, string const &Desc, + string const &MD5) +{ + if (Output == NULL) + return true; + + // Different archs can include different versions and therefore + // different descriptions - so we need to check for both name and md5. + string const Record = Pkg + ":" + MD5; + + if (Included.find(Record) != Included.end()) + return true; + + fprintf(Output, "Package: %s\nDescription-md5: %s\nDescription-en: %s\n", + Pkg.c_str(), MD5.c_str(), Desc.c_str()); + + Included.insert(Record); + return true; +} + /*}}}*/ +// TranslationWriter::~TranslationWriter - Destructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +TranslationWriter::~TranslationWriter() +{ + if (Comp == NULL) + return; + + delete Comp; +} + /*}}}*/ + // SourcesWriter::SourcesWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -SourcesWriter::SourcesWriter(string BOverrides,string SOverrides, - string ExtOverrides) +SourcesWriter::SourcesWriter(string const &BOverrides,string const &SOverrides, + string const &ExtOverrides) { Output = stdout; AddPattern("*.dsc"); @@ -554,7 +610,12 @@ bool SourcesWriter::DoPackage(string FileName) 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'; @@ -645,12 +706,22 @@ bool SourcesWriter::DoPackage(string FileName) } // Add the dsc to the files hash list - 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(), - Tags.FindS("Files").c_str()); - + string const strippedName = flNotDir(FileName); + std::ostringstream ostreamFiles; + ostreamFiles << "\n " << string(MD5.Result()) << " " << St.st_size << " " + << strippedName << "\n " << Tags.FindS("Files"); + string const Files = ostreamFiles.str(); + + std::ostringstream ostreamSha1; + ostreamSha1 << "\n " << string(SHA1.Result()) << " " << St.st_size << " " + << strippedName << "\n " << Tags.FindS("Checksums-Sha1"); + string const ChecksumsSha1 = ostreamSha1.str(); + + std::ostringstream ostreamSha256; + ostreamSha256 << "\n " << string(SHA256.Result()) << " " << St.st_size << " " + << strippedName << "\n " << Tags.FindS("Checksums-Sha256"); + string const ChecksumsSha256 = ostreamSha256.str(); + // Strip the DirStrip prefix from the FileName and add the PathPrefix string NewFileName; if (DirStrip.empty() == false && @@ -667,7 +738,8 @@ bool SourcesWriter::DoPackage(string FileName) // Perform the delinking operation over all of the files string ParseJnk; - const char *C = Files; + const char *C = Files.c_str(); + char *RealPath = NULL; for (;isspace(*C); C++); while (*C != 0) { @@ -679,10 +751,11 @@ bool SourcesWriter::DoPackage(string FileName) 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; + free(RealPath); if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St.st_size) == false) return false; } @@ -693,12 +766,14 @@ bool SourcesWriter::DoPackage(string FileName) 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++],"Files",Files.c_str()); + SetTFRewriteData(Changes[End++],"Checksums-Sha1",ChecksumsSha1.c_str()); + SetTFRewriteData(Changes[End++],"Checksums-Sha256",ChecksumsSha256.c_str()); if (Directory != "./") SetTFRewriteData(Changes[End++],"Directory",Directory.c_str()); SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str()); @@ -719,7 +794,7 @@ bool SourcesWriter::DoPackage(string FileName) if (NewMaint.empty() == false) SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str()); - for (map::iterator I = SOverItem->FieldOverride.begin(); + for (map::const_iterator I = SOverItem->FieldOverride.begin(); I != SOverItem->FieldOverride.end(); I++) SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str()); @@ -739,11 +814,11 @@ bool SourcesWriter::DoPackage(string FileName) // ContentsWriter::ContentsWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -ContentsWriter::ContentsWriter(string DB) : - Db(DB), Stats(Db.Stats) +ContentsWriter::ContentsWriter(string const &DB, string const &Arch) : + FTWScanner(Arch), Db(DB), Stats(Db.Stats) { - AddPattern("*.deb"); + SetExts(".deb"); Output = stdout; } /*}}}*/ @@ -751,9 +826,9 @@ ContentsWriter::ContentsWriter(string DB) : // --------------------------------------------------------------------- /* If Package is the empty string the control record will be parsed to determine what the package name is. */ -bool ContentsWriter::DoPackage(string FileName,string Package) +bool ContentsWriter::DoPackage(string FileName, string Package) { - if (!Db.GetFileInfo(FileName, Package.empty(), true, false, false, false, false)) + if (!Db.GetFileInfo(FileName, Package.empty(), true, false, false, false, false, false)) { return false; } @@ -772,7 +847,7 @@ bool ContentsWriter::DoPackage(string FileName,string Package) // ContentsWriter::ReadFromPkgs - Read from a packages file /*{{{*/ // --------------------------------------------------------------------- /* */ -bool ContentsWriter::ReadFromPkgs(string PkgFile,string PkgCompress) +bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompress) { MultiCompress Pkgs(PkgFile,PkgCompress,0,false); if (_error->PendingError() == true) @@ -827,7 +902,7 @@ bool ContentsWriter::ReadFromPkgs(string PkgFile,string PkgCompress) // ReleaseWriter::ReleaseWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -ReleaseWriter::ReleaseWriter(string DB) +ReleaseWriter::ReleaseWriter(string const &DB) { AddPattern("Packages"); AddPattern("Packages.gz"); @@ -841,7 +916,7 @@ ReleaseWriter::ReleaseWriter(string DB) AddPattern("md5sum.txt"); Output = stdout; - time_t now = time(NULL); + time_t const now = time(NULL); char datestr[128]; if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S UTC", gmtime(&now)) == 0) @@ -849,6 +924,15 @@ ReleaseWriter::ReleaseWriter(string DB) datestr[0] = '\0'; } + time_t const validuntil = now + _config->FindI("APT::FTPArchive::Release::ValidTime", 0); + char validstr[128] = ""; + if (now == validuntil || + strftime(validstr, sizeof(validstr), "%a, %d %b %Y %H:%M:%S UTC", + gmtime(&validuntil)) == 0) + { + datestr[0] = '\0'; + } + map Fields; Fields["Origin"] = ""; Fields["Label"] = ""; @@ -856,6 +940,7 @@ ReleaseWriter::ReleaseWriter(string DB) Fields["Version"] = ""; Fields["Codename"] = ""; Fields["Date"] = datestr; + Fields["Valid-Until"] = validstr; Fields["Architectures"] = ""; Fields["Components"] = ""; Fields["Description"] = ""; @@ -928,7 +1013,7 @@ bool ReleaseWriter::DoPackage(string FileName) void ReleaseWriter::Finish() { fprintf(Output, "MD5Sum:\n"); - for(map::iterator I = CheckSums.begin(); + for(map::const_iterator I = CheckSums.begin(); I != CheckSums.end(); ++I) { @@ -939,7 +1024,7 @@ void ReleaseWriter::Finish() } fprintf(Output, "SHA1:\n"); - for(map::iterator I = CheckSums.begin(); + for(map::const_iterator I = CheckSums.begin(); I != CheckSums.end(); ++I) { @@ -950,7 +1035,7 @@ void ReleaseWriter::Finish() } fprintf(Output, "SHA256:\n"); - for(map::iterator I = CheckSums.begin(); + for(map::const_iterator I = CheckSums.begin(); I != CheckSums.end(); ++I) {