Browse Source

Merge with Matt and update French translation

Patches applied:

 * apt@packages.debian.org/apt--main--0--patch-49
   Merge michael.vogt@canonical.com--2004/apt--status-fd--0

 * apt@packages.debian.org/apt--main--0--patch-50
   Increment libapt-pkg version

 * apt@packages.debian.org/apt--main--0--patch-51
   0.6.30

 * apt@packages.debian.org/apt--main--0--patch-52
   0.6.31

 * apt@packages.debian.org/apt--main--0--patch-53
   Remove debugging from apt.cron.daily

 * apt@packages.debian.org/apt--main--0--patch-54
   allow SHA1Summation to process a file descriptor until EOF

 * apt@packages.debian.org/apt--main--0--patch-55
   Fix syntax in sha1.cc

 * apt@packages.debian.org/apt--main--0--patch-56
   Fix build/install of Polish offline documentation

 * apt@packages.debian.org/apt--main--0--patch-57
   Move CD-ROM handling backend into libapt-pkg

 * apt@packages.debian.org/apt--main--0--patch-58
   Fix compilation errors from apt--auth-cdrom--0

 * michael.vogt@canonical.com--2004--laptop/apt--status-fd--0--base-0
   tag of apt@packages.debian.org/apt--main--0--patch-32

 * michael.vogt@canonical.com--2004--laptop/apt--status-fd--0--patch-1
   

 * michael.vogt@canonical.com--2004--laptop/apt--status-fd--0--patch-2
   * changed version of the library 

 * michael.vogt@canonical.com--2004--laptop/apt--status-fd--0--patch-3
   * merged with matt again

 * michael.vogt@canonical.com--2004--laptop/apt--status-fd--0--patch-4
   * merged with apt--main--0 and fixed permissions in po/

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-1
   tag of michael.vogt@canonical.com--2004--laptop/apt--status-fd--0--patch-4

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-2
   * merged with matt's tree

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-3
   * removed a stupid "<<<" merge in the changelog

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-4
   * star-merged with apt@packages.debian.org/apt--main--0

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-5
   * removed the "pre-fork/post-fork" change and put it into it's own branch, star-merged with matt so that it applies cleanly

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-6
   * cleaned a incorrect log-file merge

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-7
   * removed a conflict in =tagging-method

 * michael.vogt@canonical.com--2004/apt--status-fd--0--patch-8
   * cleaned up the delta so that it no longer contains unreleated whitespace changes

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--base-0
   tag of apt@packages.debian.org/apt--main--0--patch-51

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--patch-1
   * added support for signed cdroms 

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--patch-2
   * merged with apt--main, seperated cmdline/apt-cdrom.cc into a library (apt-pkg/cdrom.{cc,h})

 * michael.vogt@ubuntu.com--2005/apt--auth-cdrom--0--patch-3
   * cleaned up the cmdline/apt-cdrom.cc code
debian/1.8.y
Christian Perrier 18 years ago
parent
commit
1b5a62221c
  1. 776
      apt-pkg/cdrom.cc
  2. 71
      apt-pkg/cdrom.h
  3. 5
      apt-pkg/contrib/fileutl.cc
  4. 2
      apt-pkg/contrib/fileutl.h
  5. 11
      apt-pkg/contrib/sha1.cc
  6. 19
      apt-pkg/deb/dpkgpm.cc
  7. 2
      apt-pkg/deb/dpkgpm.h
  8. 208
      apt-pkg/indexcopy.cc
  9. 16
      apt-pkg/indexcopy.h
  10. 11
      apt-pkg/indexrecords.cc
  11. 4
      apt-pkg/indexrecords.h
  12. 6
      apt-pkg/makefile
  13. 2
      apt-pkg/packagemanager.h
  14. 705
      cmdline/apt-cdrom.cc
  15. 2
      cmdline/makefile
  16. 2
      configure.in
  17. 1
      debian/apt.cron.daily
  18. 22
      debian/changelog
  19. 2
      debian/rules
  20. 180
      doc/pl/offline.pl.sgml
  21. 116
      po/apt-all.pot
  22. 429
      po/bs.po
  23. 448
      po/ca.po
  24. 443
      po/cs.po
  25. 513
      po/da.po
  26. 479
      po/de.UTF-8.po
  27. 479
      po/de.po
  28. 496
      po/el.po
  29. 433
      po/en_GB.po
  30. 483
      po/es.po
  31. 473
      po/eu.po
  32. 444
      po/fi.po
  33. 138
      po/fr.po
  34. 427
      po/he.po
  35. 441
      po/hu.po
  36. 479
      po/it.po
  37. 443
      po/ja.po
  38. 443
      po/ko.po
  39. 119
      po/nb.po
  40. 443
      po/nl.po
  41. 443
      po/nn.po
  42. 119
      po/pl.po
  43. 448
      po/pt.po
  44. 448
      po/pt_BR.po
  45. 586
      po/ro.po
  46. 484
      po/ru.po
  47. 443
      po/sk.po
  48. 119
      po/sl.po
  49. 443
      po/sv.po
  50. 441
      po/tl.po
  51. 447
      po/zh_CN.po
  52. 122
      po/zh_TW.po

776
apt-pkg/cdrom.cc

@ -0,0 +1,776 @@
/*
*/
#ifdef __GNUG__
#pragma implementation "apt-pkg/cdrom.h"
#endif
#include<apt-pkg/init.h>
#include<apt-pkg/error.h>
#include<apt-pkg/cdromutl.h>
#include<apt-pkg/strutl.h>
#include<apt-pkg/cdrom.h>
#include<sstream>
#include<fstream>
#include<config.h>
#include<apti18n.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include "indexcopy.h"
using namespace std;
// FindPackages - Find the package files on the CDROM /*{{{*/
// ---------------------------------------------------------------------
/* We look over the cdrom for package files. This is a recursive
search that short circuits when it his a package file in the dir.
This speeds it up greatly as the majority of the size is in the
binary-* sub dirs. */
bool pkgCdrom::FindPackages(string CD,vector<string> &List,
vector<string> &SList, vector<string> &SigList,
string &InfoDir, pkgCdromStatus *log,
unsigned int Depth)
{
static ino_t Inodes[9];
// if we have a look we "pulse" now
if(log)
log->Update();
if (Depth >= 7)
return true;
if (CD[CD.length()-1] != '/')
CD += '/';
if (chdir(CD.c_str()) != 0)
return _error->Errno("chdir","Unable to change to %s",CD.c_str());
// Look for a .disk subdirectory
struct stat Buf;
if (stat(".disk",&Buf) == 0)
{
if (InfoDir.empty() == true)
InfoDir = CD + ".disk/";
}
// Don't look into directories that have been marked to ingore.
if (stat(".aptignr",&Buf) == 0)
return true;
/* Check _first_ for a signature file as apt-cdrom assumes that all files
under a Packages/Source file are in control of that file and stops
the scanning
*/
if (stat("Release.gpg",&Buf) == 0)
{
SigList.push_back(CD);
}
/* 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)
{
List.push_back(CD);
// Continue down if thorough is given
if (_config->FindB("APT::CDROM::Thorough",false) == false)
return true;
}
if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0)
{
SList.push_back(CD);
// Continue down if thorough is given
if (_config->FindB("APT::CDROM::Thorough",false) == false)
return true;
}
DIR *D = opendir(".");
if (D == 0)
return _error->Errno("opendir","Unable to read %s",CD.c_str());
// Run over the directory
for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
{
// Skip some files..
if (strcmp(Dir->d_name,".") == 0 ||
strcmp(Dir->d_name,"..") == 0 ||
//strcmp(Dir->d_name,"source") == 0 ||
strcmp(Dir->d_name,".disk") == 0 ||
strcmp(Dir->d_name,"experimental") == 0 ||
strcmp(Dir->d_name,"binary-all") == 0 ||
strcmp(Dir->d_name,"debian-installer") == 0)
continue;
// See if the name is a sub directory
struct stat Buf;
if (stat(Dir->d_name,&Buf) != 0)
continue;
if (S_ISDIR(Buf.st_mode) == 0)
continue;
unsigned int I;
for (I = 0; I != Depth; I++)
if (Inodes[I] == Buf.st_ino)
break;
if (I != Depth)
continue;
// Store the inodes weve seen
Inodes[Depth] = Buf.st_ino;
// Descend
if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false)
break;
if (chdir(CD.c_str()) != 0)
return _error->Errno("chdir","Unable to change to %s",CD.c_str());
};
closedir(D);
return !_error->PendingError();
}
// Score - We compute a 'score' for a path /*{{{*/
// ---------------------------------------------------------------------
/* Paths are scored based on how close they come to what I consider
normal. That is ones that have 'dist' 'stable' 'testing' will score
higher than ones without. */
int pkgCdrom::Score(string Path)
{
int Res = 0;
if (Path.find("stable/") != string::npos)
Res += 29;
if (Path.find("/binary-") != string::npos)
Res += 20;
if (Path.find("testing/") != string::npos)
Res += 28;
if (Path.find("unstable/") != string::npos)
Res += 27;
if (Path.find("/dists/") != string::npos)
Res += 40;
if (Path.find("/main/") != string::npos)
Res += 20;
if (Path.find("/contrib/") != string::npos)
Res += 20;
if (Path.find("/non-free/") != string::npos)
Res += 20;
if (Path.find("/non-US/") != string::npos)
Res += 20;
if (Path.find("/source/") != string::npos)
Res += 10;
if (Path.find("/debian/") != string::npos)
Res -= 10;
return Res;
}
/*}}}*/
// DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/
// ---------------------------------------------------------------------
/* Here we drop everything that is not this machines arch */
bool pkgCdrom::DropBinaryArch(vector<string> &List)
{
char S[300];
snprintf(S,sizeof(S),"/binary-%s/",
_config->Find("Apt::Architecture").c_str());
for (unsigned int I = 0; I < List.size(); I++)
{
const char *Str = List[I].c_str();
const char *Res;
if ((Res = strstr(Str,"/binary-")) == 0)
continue;
// Weird, remove it.
if (strlen(Res) < strlen(S))
{
List.erase(List.begin() + I);
I--;
continue;
}
// See if it is our arch
if (stringcmp(Res,Res + strlen(S),S) == 0)
continue;
// Erase it
List.erase(List.begin() + I);
I--;
}
return true;
}
// DropRepeats - Drop repeated files resulting from symlinks /*{{{*/
// ---------------------------------------------------------------------
/* Here we go and stat every file that we found and strip dup inodes. */
bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
{
// Get a list of all the inodes
ino_t *Inodes = new ino_t[List.size()];
for (unsigned int I = 0; I != List.size(); I++)
{
struct stat Buf;
if (stat((List[I] + Name).c_str(),&Buf) != 0 &&
stat((List[I] + Name + ".gz").c_str(),&Buf) != 0)
_error->Errno("stat","Failed to stat %s%s",List[I].c_str(),
Name);
Inodes[I] = Buf.st_ino;
}
if (_error->PendingError() == true)
return false;
// Look for dups
for (unsigned int I = 0; I != List.size(); I++)
{
for (unsigned int J = I+1; J < List.size(); J++)
{
// No match
if (Inodes[J] != Inodes[I])
continue;
// We score the two paths.. and erase one
int ScoreA = Score(List[I]);
int ScoreB = Score(List[J]);
if (ScoreA < ScoreB)
{
List[I] = string();
break;
}
List[J] = string();
}
}
// Wipe erased entries
for (unsigned int I = 0; I < List.size();)
{
if (List[I].empty() == false)
I++;
else
List.erase(List.begin()+I);
}
return true;
}
/*}}}*/
// ReduceSourceList - Takes the path list and reduces it /*{{{*/
// ---------------------------------------------------------------------
/* This takes the list of source list expressed entires and collects
similar ones to form a single entry for each dist */
void pkgCdrom::ReduceSourcelist(string CD,vector<string> &List)
{
sort(List.begin(),List.end());
// Collect similar entries
for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
{
// Find a space..
string::size_type Space = (*I).find(' ');
if (Space == string::npos)
continue;
string::size_type SSpace = (*I).find(' ',Space + 1);
if (SSpace == string::npos)
continue;
string Word1 = string(*I,Space,SSpace-Space);
string Prefix = string(*I,0,Space);
for (vector<string>::iterator J = List.begin(); J != I; J++)
{
// Find a space..
string::size_type Space2 = (*J).find(' ');
if (Space2 == string::npos)
continue;
string::size_type SSpace2 = (*J).find(' ',Space2 + 1);
if (SSpace2 == string::npos)
continue;
if (string(*J,0,Space2) != Prefix)
continue;
if (string(*J,Space2,SSpace2-Space2) != Word1)
continue;
*J += string(*I,SSpace);
*I = string();
}
}
// Wipe erased entries
for (unsigned int I = 0; I < List.size();)
{
if (List[I].empty() == false)
I++;
else
List.erase(List.begin()+I);
}
}
/*}}}*/
// WriteDatabase - Write the CDROM Database file /*{{{*/
// ---------------------------------------------------------------------
/* We rewrite the configuration class associated with the cdrom database. */
bool pkgCdrom::WriteDatabase(Configuration &Cnf)
{
string DFile = _config->FindFile("Dir::State::cdroms");
string NewFile = DFile + ".new";
unlink(NewFile.c_str());
ofstream Out(NewFile.c_str());
if (!Out)
return _error->Errno("ofstream::ofstream",
"Failed to open %s.new",DFile.c_str());
/* Write out all of the configuration directives by walking the
configuration tree */
const Configuration::Item *Top = Cnf.Tree(0);
for (; Top != 0;)
{
// Print the config entry
if (Top->Value.empty() == false)
Out << Top->FullTag() + " \"" << Top->Value << "\";" << endl;
if (Top->Child != 0)
{
Top = Top->Child;
continue;
}
while (Top != 0 && Top->Next == 0)
Top = Top->Parent;
if (Top != 0)
Top = Top->Next;
}
Out.close();
rename(DFile.c_str(),string(DFile + '~').c_str());
if (rename(NewFile.c_str(),DFile.c_str()) != 0)
return _error->Errno("rename","Failed to rename %s.new to %s",
DFile.c_str(),DFile.c_str());
return true;
}
/*}}}*/
// WriteSourceList - Write an updated sourcelist /*{{{*/
// ---------------------------------------------------------------------
/* This reads the old source list and copies it into the new one. It
appends the new CDROM entires just after the first block of comments.
This places them first in the file. It also removes any old entries
that were the same. */
bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
{
if (List.size() == 0)
return true;
string File = _config->FindFile("Dir::Etc::sourcelist");
// Open the stream for reading
ifstream F((FileExists(File)?File.c_str():"/dev/null"),
ios::in );
if (!F != 0)
return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
string NewFile = File + ".new";
unlink(NewFile.c_str());
ofstream Out(NewFile.c_str());
if (!Out)
return _error->Errno("ofstream::ofstream",
"Failed to open %s.new",File.c_str());
// Create a short uri without the path
string ShortURI = "cdrom:[" + Name + "]/";
string ShortURI2 = "cdrom:" + Name + "/"; // For Compatibility
string Type;
if (Source == true)
Type = "deb-src";
else
Type = "deb";
char Buffer[300];
int CurLine = 0;
bool First = true;
while (F.eof() == false)
{
F.getline(Buffer,sizeof(Buffer));
CurLine++;
_strtabexpand(Buffer,sizeof(Buffer));
_strstrip(Buffer);
// Comment or blank
if (Buffer[0] == '#' || Buffer[0] == 0)
{
Out << Buffer << endl;
continue;
}
if (First == true)
{
for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
{
string::size_type Space = (*I).find(' ');
if (Space == string::npos)
return _error->Error("Internal error");
Out << Type << " cdrom:[" << Name << "]/" << string(*I,0,Space) <<
" " << string(*I,Space+1) << endl;
}
}
First = false;
// Grok it
string cType;
string URI;
const char *C = Buffer;
if (ParseQuoteWord(C,cType) == false ||
ParseQuoteWord(C,URI) == false)
{
Out << Buffer << endl;
continue;
}
// Emit lines like this one
if (cType != Type || (string(URI,0,ShortURI.length()) != ShortURI &&
string(URI,0,ShortURI.length()) != ShortURI2))
{
Out << Buffer << endl;
continue;
}
}
// Just in case the file was empty
if (First == true)
{
for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
{
string::size_type Space = (*I).find(' ');
if (Space == string::npos)
return _error->Error("Internal error");
Out << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) <<
" " << string(*I,Space+1) << endl;
}
}
Out.close();
rename(File.c_str(),string(File + '~').c_str());
if (rename(NewFile.c_str(),File.c_str()) != 0)
return _error->Errno("rename","Failed to rename %s.new to %s",
File.c_str(),File.c_str());
return true;
}
bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
{
stringstream msg;
// Startup
string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
if (CDROM[0] == '.')
CDROM= SafeGetCWD() + '/' + CDROM;
if(log) {
msg.str("");
ioprintf(msg, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
CDROM.c_str());
log->Update(msg.str());
}
if (MountCdrom(CDROM) == false)
return _error->Error("Failed to mount the cdrom.");
// Hash the CD to get an ID
if(log)
log->Update(_("Identifying.. "));
if (IdentCdrom(CDROM,ident) == false)
{
ident = "";
return false;
}
msg.str("");
ioprintf(msg, "[%s]\n",ident.c_str());
log->Update(msg.str());
// Read the database
Configuration Database;
string DFile = _config->FindFile("Dir::State::cdroms");
if (FileExists(DFile) == true)
{
if (ReadConfigFile(Database,DFile) == false)
return _error->Error("Unable to read the cdrom database %s",
DFile.c_str());
}
if(log) {
msg.str("");
ioprintf(msg, _("Stored Label: %s \n"),
Database.Find("CD::"+ident).c_str());
log->Update(msg.str());
}
return true;
}
bool pkgCdrom::Add(pkgCdromStatus *log)
{
stringstream msg;
// Startup
string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/");
if (CDROM[0] == '.')
CDROM= SafeGetCWD() + '/' + CDROM;
if(log) {
log->SetTotal(STEP_LAST);
msg.str("");
ioprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str());
log->Update(msg.str(), STEP_PREPARE);
}
// Read the database
Configuration Database;
string DFile = _config->FindFile("Dir::State::cdroms");
if (FileExists(DFile) == true)
{
if (ReadConfigFile(Database,DFile) == false)
return _error->Error("Unable to read the cdrom database %s",
DFile.c_str());
}
// Unmount the CD and get the user to put in the one they want
if (_config->FindB("APT::CDROM::NoMount",false) == false)
{
if(log)
log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT);
UnmountCdrom(CDROM);
if(log) {
log->Update(_("Waiting for disc...\n"), STEP_WAIT);
if(!log->ChangeCdrom()) {
// user aborted
return false;
}
}
// Mount the new CDROM
log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT);
if (MountCdrom(CDROM) == false)
return _error->Error("Failed to mount the cdrom.");
}
// Hash the CD to get an ID
if(log)
log->Update(_("Identifying.. "), STEP_IDENT);
string ID;
if (IdentCdrom(CDROM,ID) == false)
{
log->Update("\n");
return false;
}
if(log)
log->Update("["+ID+"]\n");
if(log)
log->Update(_("Scanning Disc for index files..\n"),STEP_SCAN);
// Get the CD structure
vector<string> List;
vector<string> SourceList;
vector<string> SigList;
string StartDir = SafeGetCWD();
string InfoDir;
if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false)
{
log->Update("\n");
return false;
}
chdir(StartDir.c_str());
if (_config->FindB("Debug::aptcdrom",false) == true)
{
cout << "I found (binary):" << endl;
for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
cout << *I << endl;
cout << "I found (source):" << endl;
for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
cout << *I << endl;
cout << "I found (Signatures):" << endl;
for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); I++)
cout << *I << endl;
}
//log->Update(_("Cleaning package lists..."), STEP_CLEAN);
// Fix up the list
DropBinaryArch(List);
DropRepeats(List,"Packages");
DropRepeats(SourceList,"Sources");
DropRepeats(SigList,"Release.gpg");
if(log) {
msg.str("");
ioprintf(msg, _("Found %i package indexes, %i source indexes and "
"%i signatures\n"),
List.size(), SourceList.size(), SigList.size());
log->Update(msg.str(), STEP_SCAN);
}
if (List.size() == 0 && SourceList.size() == 0)
return _error->Error("Unable to locate any package files, perhaps this is not a Debian Disc");
// Check if the CD is in the database
string Name;
if (Database.Exists("CD::" + ID) == false ||
_config->FindB("APT::CDROM::Rename",false) == true)
{
// Try to use the CDs label if at all possible
if (InfoDir.empty() == false &&
FileExists(InfoDir + "/info") == true)
{
ifstream F(string(InfoDir + "/info").c_str());
if (!F == 0)
getline(F,Name);
if (Name.empty() == false)
{
// Escape special characters
string::iterator J = Name.begin();
for (; J != Name.end(); J++)
if (*J == '"' || *J == ']' || *J == '[')
*J = '_';
if(log) {
msg.str("");
ioprintf(msg, "Found label '%s'\n", Name.c_str());
log->Update(msg.str());
}
Database.Set("CD::" + ID + "::Label",Name);
}
}
if (_config->FindB("APT::CDROM::Rename",false) == true ||
Name.empty() == true)
{
if(!log)
return _error->Error("No disc name found and no way to ask for it");
while(true) {
if(!log->AskCdromName(Name)) {
// user canceld
return false;
}
cout << "Name: '" << Name << "'" << endl;
if (Name.empty() == false &&
Name.find('"') == string::npos &&
Name.find('[') == string::npos &&
Name.find(']') == string::npos)
break;
log->Update(_("That is not a valid name, try again.\n"));
}
}
}
else
Name = Database.Find("CD::" + ID);
// Escape special characters
string::iterator J = Name.begin();
for (; J != Name.end(); J++)
if (*J == '"' || *J == ']' || *J == '[')
*J = '_';
Database.Set("CD::" + ID,Name);
if(log) {
msg.str("");
ioprintf(msg, _("This Disc is called: \n'%s'\n"), Name.c_str());
log->Update(msg.str());
}
log->Update(_("Copying package lists..."), STEP_COPY);
// take care of the signatures and copy them if they are ok
// (we do this before PackageCopy as it modifies "List" and "SourceList")
SigVerify SignVerify;
SignVerify.CopyAndVerify(CDROM, Name, SigList, List, SourceList);
// Copy the package files to the state directory
PackageCopy Copy;
SourceCopy SrcCopy;
if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false)
return false;
// reduce the List so that it takes less space in sources.list
ReduceSourcelist(CDROM,List);
ReduceSourcelist(CDROM,SourceList);
// Write the database and sourcelist
if (_config->FindB("APT::cdrom::NoAct",false) == false)
{
if (WriteDatabase(Database) == false)
return false;
if(log) {
log->Update(_("Writing new source list\n"), STEP_WRITE);
}
if (WriteSourceList(Name,List,false) == false ||
WriteSourceList(Name,SourceList,true) == false)
return false;
}
// Print the sourcelist entries
if(log)
log->Update(_("Source List entries for this Disc are:\n"));
for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
{
string::size_type Space = (*I).find(' ');
if (Space == string::npos)
return _error->Error("Internal error");
if(log) {
msg.str("");
msg << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) <<
" " << string(*I,Space+1) << endl;
log->Update(msg.str());
}
}
for (vector<string>::iterator I = SourceList.begin(); I != SourceList.end(); I++)
{
string::size_type Space = (*I).find(' ');
if (Space == string::npos)
return _error->Error("Internal error");
if(log) {
msg.str("");
msg << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) <<
" " << string(*I,Space+1) << endl;
log->Update(msg.str());
}
}
// Unmount and finish
if (_config->FindB("APT::CDROM::NoMount",false) == false) {
log->Update(_("Unmounting CD-ROM..."), STEP_LAST);
UnmountCdrom(CDROM);
}
return true;
}

71
apt-pkg/cdrom.h

@ -0,0 +1,71 @@
#ifndef PKGLIB_CDROM_H
#define PKGLIB_CDROM_H
#include<apt-pkg/init.h>
#include<string>
#include<vector>
#ifdef __GNUG__
#pragma interface "apt-pkg/cdrom.h"
#endif
using namespace std;
class pkgCdromStatus
{
protected:
int totalSteps;
public:
pkgCdromStatus() {};
virtual ~pkgCdromStatus() {};
// total steps
virtual void SetTotal(int total) { totalSteps = total; };
// update steps, will be called regularly as a "pulse"
virtual void Update(string text="", int current=0) = 0;
// ask for cdrom insert
virtual bool ChangeCdrom() = 0;
// ask for cdrom name
virtual bool AskCdromName(string &Name) = 0;
// Progress indicator for the Index rewriter
virtual OpProgress* GetOpProgress() {return NULL; };
};
class pkgCdrom
{
protected:
enum {
STEP_PREPARE = 1,
STEP_UNMOUNT,
STEP_WAIT,
STEP_MOUNT,
STEP_IDENT,
STEP_SCAN,
STEP_COPY,
STEP_WRITE,
STEP_UNMOUNT3,
STEP_LAST
};
bool FindPackages(string CD,vector<string> &List,
vector<string> &SList, vector<string> &SigList,
string &InfoDir, pkgCdromStatus *log,
unsigned int Depth = 0);
bool DropBinaryArch(vector<string> &List);
bool DropRepeats(vector<string> &List,const char *Name);
void ReduceSourcelist(string CD,vector<string> &List);
bool WriteDatabase(Configuration &Cnf);
bool WriteSourceList(string Name,vector<string> &List,bool Source);
int Score(string Path);
public:
bool Ident(string &ident, pkgCdromStatus *log);
bool Add(pkgCdromStatus *log);
};
#endif

5
apt-pkg/contrib/fileutl.cc

@ -306,7 +306,7 @@ bool WaitFd(int Fd,bool write,unsigned long timeout)
/* This is used if you want to cleanse the environment for the forked
child, it fixes up the important signals and nukes all of the fds,
otherwise acts like normal fork. */
pid_t ExecFork()
pid_t ExecFork(int dontCloseThisFd)
{
// Fork off the process
pid_t Process = fork();
@ -329,7 +329,8 @@ pid_t ExecFork()
// Close all of our FDs - just in case
for (int K = 3; K != 40; K++)
fcntl(K,F_SETFD,FD_CLOEXEC);
if(K != dontCloseThisFd)
fcntl(K,F_SETFD,FD_CLOEXEC);
}
return Process;

2
apt-pkg/contrib/fileutl.h

@ -87,7 +87,7 @@ string SafeGetCWD();
void SetCloseExec(int Fd,bool Close);
void SetNonBlock(int Fd,bool Block);
bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0);
pid_t ExecFork();
pid_t ExecFork(int dontCloseThisFd=-1);
bool ExecWait(pid_t Pid,const char *Name,bool Reap = false);
// File string manipulators

11
apt-pkg/contrib/sha1.cc

@ -343,11 +343,16 @@ bool SHA1Summation::AddFD(int Fd,unsigned long Size)
{
unsigned char Buf[64 * 64];
int Res = 0;
while (Size != 0)
int ToEOF = (Size == 0);
while (Size != 0 || ToEOF)
{
Res = read(Fd,Buf,MIN(Size,sizeof(Buf)));
if (Res < 0 || (unsigned) Res != MIN(Size,sizeof(Buf)))
unsigned n = sizeof(Buf);
if (!ToEOF) n = MIN(Size,n);
Res = read(Fd,Buf,n);
if (Res < 0 || (!ToEOF && (unsigned) Res != n)) // error, or short read
return false;
if (ToEOF && Res == 0) // EOF
break;
Size -= Res;
Add(Buf,Res);
}

19
apt-pkg/deb/dpkgpm.cc

@ -326,7 +326,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
// DPkgPM::Go - Run the sequence /*{{{*/
// ---------------------------------------------------------------------
/* This globs the operations and calls dpkg */
bool pkgDPkgPM::Go()
bool pkgDPkgPM::Go(int status_fd)
{
unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
@ -367,6 +367,17 @@ bool pkgDPkgPM::Go()
}
}
// if we got a status_fd argument, we pass it to apt
char status_fd_buf[20];
if(status_fd > 0)
{
Args[n++] = "--status-fd";
Size += strlen(Args[n-1]);
snprintf(status_fd_buf,20,"%i",status_fd);
Args[n++] = status_fd_buf;
Size += strlen(Args[n-1]);
}
switch (I->Op)
{
case Item::Remove:
@ -440,7 +451,11 @@ bool pkgDPkgPM::Go()
sighandler_t old_SIGINT = signal(SIGINT,SIG_IGN);
// Fork dpkg
pid_t Child = ExecFork();
pid_t Child;
if(status_fd > 0)
Child = ExecFork(status_fd);
else
Child = ExecFork();
// This is the child
if (Child == 0)

2
apt-pkg/deb/dpkgpm.h

@ -45,7 +45,7 @@ class pkgDPkgPM : public pkgPackageManager
virtual bool Install(PkgIterator Pkg,string File);
virtual bool Configure(PkgIterator Pkg);
virtual bool Remove(PkgIterator Pkg,bool Purge = false);
virtual bool Go();
virtual bool Go(int status_fd=-1);
virtual void Reset();
public:

208
cmdline/indexcopy.cc → apt-pkg/indexcopy.cc

@ -18,8 +18,13 @@
#include <apt-pkg/fileutl.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/tagfile.h>
#include <apt-pkg/indexrecords.h>
#include <apt-pkg/md5.h>
#include <apt-pkg/cdrom.h>
#include <apti18n.h>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
@ -30,12 +35,15 @@ using namespace std;
// IndexCopy::CopyPackages - Copy the package files from the CD /*{{{*/
// ---------------------------------------------------------------------
/* */
bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List)
bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
pkgCdromStatus *log)
{
OpProgress *Progress = NULL;
if (List.size() == 0)
return true;
OpTextProgress Progress;
if(log)
Progress = log->GetOpProgress();
bool NoStat = _config->FindB("APT::CDROM::Fast",false);
bool Debug = _config->FindB("Debug::aptcdrom",false);
@ -130,11 +138,13 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List)
return _error->Errno("fdopen","Failed to reopen fd");
// Setup the progress meter
Progress.OverallProgress(CurrentSize,TotalSize,FileSize,
string("Reading ") + Type() + " Indexes");
if(Progress)
Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
string("Reading ") + Type() + " Indexes");
// Parse
Progress.SubProgress(Pkg.Size());
if(Progress)
Progress->SubProgress(Pkg.Size());
pkgTagSection Section;
this->Section = &Section;
string Prefix;
@ -142,7 +152,8 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List)
unsigned long Chop = 0;
while (Parser.Step(Section) == true)
{
Progress.Progress(Parser.Offset());
if(Progress)
Progress->Progress(Parser.Offset());
string File;
unsigned long Size;
if (GetFile(File,Size) == false)
@ -230,35 +241,8 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List)
FinalF += URItoFileName(S);
if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
return _error->Errno("rename","Failed to rename");
// Copy the release file
snprintf(S,sizeof(S),"cdrom:[%s]/%sRelease",Name.c_str(),
(*I).c_str() + CDROM.length());
string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
TargetF += URItoFileName(S);
if (FileExists(*I + "Release") == true)
{
FileFd Target(TargetF,FileFd::WriteEmpty);
FileFd Rel(*I + "Release",FileFd::ReadOnly);
if (_error->PendingError() == true)
return false;
if (CopyFile(Rel,Target) == false)
return false;
}
else
{
// Empty release file
FileFd Target(TargetF,FileFd::WriteEmpty);
}
// Rename the release file
FinalF = _config->FindDir("Dir::State::lists");
FinalF += URItoFileName(S);
if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
return _error->Errno("rename","Failed to rename");
}
/* Mangle the source to be in the proper notation with
prefix dist [component] */
*I = string(*I,Prefix.length());
@ -267,23 +251,30 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List)
CurrentSize += FileSize;
}
Progress.Done();
if(Progress)
Progress->Done();
// Some stats
cout << "Wrote " << Packages << " records" ;
if (NotFound != 0)
cout << " with " << NotFound << " missing files";
if (NotFound != 0 && WrongSize != 0)
cout << " and";
if (WrongSize != 0)
cout << " with " << WrongSize << " mismatched files";
cout << '.' << endl;
if(log) {
stringstream msg;
if(NotFound == 0 && WrongSize == 0)
ioprintf(msg, _("Wrote %i records.\n"), Packages);
else if (NotFound != 0 && WrongSize == 0)
ioprintf(msg, _("Wrote %i records with %i missing files.\n"),
Packages, NotFound);
else if (NotFound == 0 && WrongSize != 0)
ioprintf(msg, _("Wrote %i records with %i mismachted files\n"),
Packages, WrongSize);
if (NotFound != 0 && WrongSize != 0)
ioprintf(msg, _("Wrote %i records with %i missing files and %i mismachted files\n"), Packages, NotFound, WrongSize);
}
if (Packages == 0)
_error->Warning("No valid records were found.");
if (NotFound + WrongSize > 10)
cout << "Alot of entries were discarded, something may be wrong." << endl;
_error->Warning("Alot of entries were discarded, something may be wrong.\n");
return true;
}
@ -521,4 +512,133 @@ bool SourceCopy::RewriteEntry(FILE *Target,string File)
fputc('\n',Target);
return true;
}
/*}}}*/
bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
{
const indexRecords::checkSum *Record = MetaIndex->Lookup(file);
if (!Record)
{
_error->Warning("Can't find authentication record for: %s",file.c_str());
return false;
}
MD5Summation sum;
FileFd Fd(prefix+file, FileFd::ReadOnly);
sum.AddFD(Fd.Fd(), Fd.Size());
Fd.Close();
string MD5 = (string)sum.Result();
if (Record->MD5Hash != MD5)
{
_error->Warning("MD5 mismatch for: %s",file.c_str());
return false;
}
if(_config->FindB("Debug::aptcdrom",false))
{
cout << "File: " << prefix+file << endl;
cout << "Expected MD5sum: " << Record->MD5Hash << endl;
cout << "got: " << MD5 << endl << endl;
}
return true;
}
bool SigVerify::CopyMetaIndex(string CDROM, string CDName,
string prefix, string file)
{
char S[400];
snprintf(S,sizeof(S),"cdrom:[%s]/%s%s",CDName.c_str(),
(prefix).c_str() + CDROM.length(),file.c_str());
string TargetF = _config->FindDir("Dir::State::lists");
TargetF += URItoFileName(S);
FileFd Target;
FileFd Rel;
Target.Open(TargetF,FileFd::WriteEmpty);
Rel.Open(prefix + file,FileFd::ReadOnly);
if (_error->PendingError() == true)
return false;
if (CopyFile(Rel,Target) == false)
return false;
return true;
}
bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
vector<string> PkgList,vector<string> SrcList)
{
if (SigList.size() == 0)
return true;
bool Debug = _config->FindB("Debug::aptcdrom",false);
// Read all Release files
for (vector<string>::iterator I = SigList.begin(); I != SigList.end(); I++)
{
if(Debug)
cout << "Signature verify for: " << *I << endl;
indexRecords *MetaIndex = new indexRecords;
string prefix = *I;
// a Release.gpg without a Release should never happen
if(!FileExists(*I+"Release"))
continue;
// verify the gpg signature of "Release"
// gpg --verify "*I+Release.gpg", "*I+Release"
string gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv");
string pubringpath = _config->Find("Apt::GPGV::TrustedKeyring", "/etc/apt/trusted.gpg");
pid_t pid = ExecFork();
if(pid < 0) {
_error->Error("Fork failed");
return false;
}
if(pid == 0) {
execlp(gpgvpath.c_str(), gpgvpath.c_str(), "--keyring",
pubringpath.c_str(), string(*I+"Release.gpg").c_str(),
string(*I+"Release").c_str(), NULL);
}
if(!ExecWait(pid, "gpgv")) {
_error->Warning("Signature verification failed for: %s",
string(*I+"Release.gpg").c_str());
// something went wrong, don't copy the Release.gpg
// FIXME: delete any existing gpg file?
continue;
}
// Open the Release file and add it to the MetaIndex
if(!MetaIndex->Load(*I+"Release"))
{
_error->Error(MetaIndex->ErrorText.c_str());
return false;
}
// go over the Indexfiles and see if they verify
// if so, remove them from our copy of the lists
vector<string> keys = MetaIndex->MetaKeys();
for (vector<string>::iterator I = keys.begin(); I != keys.end(); I++)
{
if(!Verify(prefix,*I, MetaIndex)) {
// something went wrong, don't copy the Release.gpg
// FIXME: delete any existing gpg file?
continue;
}
}
// we need a fresh one for the Release.gpg
delete MetaIndex;
// everything was fine, copy the Release and Release.gpg file
CopyMetaIndex(CDROM, Name, prefix, "Release");
CopyMetaIndex(CDROM, Name, prefix, "Release.gpg");
}
return true;
}

16
cmdline/indexcopy.h → apt-pkg/indexcopy.h

@ -19,6 +19,8 @@ using std::vector;
class pkgTagSection;
class FileFd;
class indexRecords;
class pkgCdromStatus;
class IndexCopy
{
@ -39,7 +41,8 @@ class IndexCopy
public:
bool CopyPackages(string CDROM,string Name,vector<string> &List);
bool CopyPackages(string CDROM,string Name,vector<string> &List,
pkgCdromStatus *log);
};
class PackageCopy : public IndexCopy
@ -66,4 +69,15 @@ class SourceCopy : public IndexCopy
public:
};
class SigVerify
{
bool Verify(string prefix,string file, indexRecords *records);
bool CopyMetaIndex(string CDROM, string CDName,
string prefix, string file);
public:
bool CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
vector<string> PkgList,vector<string> SrcList);
};
#endif

11
apt-pkg/indexrecords.cc

@ -83,6 +83,17 @@ bool indexRecords::Load(const string Filename)
return true;
}
vector<string> indexRecords::MetaKeys()
{
std::vector<std::string> keys;
std::map<string,checkSum *>::iterator I = Entries.begin();
while(I != Entries.end()) {
keys.push_back((*I).first);
++I;
}
return keys;
}
bool indexRecords::parseSumData(const char *&Start, const char *End,
string &Name, string &Hash, size_t &Size)
{

4
apt-pkg/indexrecords.h

@ -12,6 +12,7 @@
#include <apt-pkg/fileutl.h>
#include <map>
#include <vector>
class indexRecords
{
@ -34,7 +35,8 @@ class indexRecords
// Lookup function
virtual const checkSum *Lookup(const string MetaKey);
std::vector<std::string> MetaKeys();
virtual bool Load(string Filename);
string GetDist() const;
virtual bool CheckDist(const string MaybeDist) const;

6
apt-pkg/makefile

@ -13,7 +13,7 @@ include ../buildlib/defaults.mak
# methods/makefile - FIXME
LIBRARY=apt-pkg
LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
MAJOR=3.7
MAJOR=3.9
MINOR=0
SLIBS=$(PTHREADLIB) $(INTLLIBS)
APT_DOMAIN:=libapt-pkg$(MAJOR)
@ -34,14 +34,14 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
acquire-worker.cc acquire-method.cc init.cc clean.cc \
srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
indexrecords.cc vendor.cc vendorlist.cc
indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc
HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
orderlist.h sourcelist.h packagemanager.h tagfile.h \
init.h pkgcache.h version.h progress.h pkgrecords.h \
acquire.h acquire-worker.h acquire-item.h acquire-method.h \
clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
vendorlist.h
vendorlist.h cdrom.h indexcopy.h
# Source code for the debian specific components
# In theory the deb headers do not need to be exported..

2
apt-pkg/packagemanager.h

@ -68,7 +68,7 @@ class pkgPackageManager : protected pkgCache::Namespace
virtual bool Install(PkgIterator /*Pkg*/,string /*File*/) {return false;};
virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
virtual bool Go() {return true;};
virtual bool Go(int statusFd=-1) {return true;};
virtual void Reset() {};
public:

705
cmdline/apt-cdrom.cc

@ -18,10 +18,13 @@
#include <apt-pkg/progress.h>
#include <apt-pkg/cdromutl.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/acquire.h>
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/cdrom.h>
#include <config.h>
#include <apti18n.h>
#include "indexcopy.h"
//#include "indexcopy.h"
#include <locale.h>
#include <iostream>
@ -37,460 +40,65 @@
using namespace std;
// FindPackages - Find the package files on the CDROM /*{{{*/
// ---------------------------------------------------------------------
/* We look over the cdrom for package files. This is a recursive
search that short circuits when it his a package file in the dir.
This speeds it up greatly as the majority of the size is in the
binary-* sub dirs. */
bool FindPackages(string CD,vector<string> &List,vector<string> &SList,
string &InfoDir,unsigned int Depth = 0)
/*{{{*/
class pkgCdromTextStatus : public pkgCdromStatus
{
static ino_t Inodes[9];
if (Depth >= 7)
return true;
if (CD[CD.length()-1] != '/')
CD += '/';
if (chdir(CD.c_str()) != 0)
return _error->Errno("chdir","Unable to change to %s",CD.c_str());
// Look for a .disk subdirectory
struct stat Buf;
if (stat(".disk",&Buf) == 0)
{
if (InfoDir.empty() == true)
InfoDir = CD + ".disk/";
}
// Don't look into directories that have been marked to ingore.
if (stat(".aptignr",&Buf) == 0)
return true;
/* 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)
{
List.push_back(CD);
// Continue down if thorough is given
if (_config->FindB("APT::CDROM::Thorough",false) == false)
return true;
}
if (stat("Sources.gz",&Buf) == 0 || stat("Sources",&Buf) == 0)
{
SList.push_back(CD);
// Continue down if thorough is given
if (_config->FindB("APT::CDROM::Thorough",false) == false)
return true;
}
DIR *D = opendir(".");
if (D == 0)
return _error->Errno("opendir","Unable to read %s",CD.c_str());
// Run over the directory
for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
{
// Skip some files..
if (strcmp(Dir->d_name,".") == 0 ||
strcmp(Dir->d_name,"..") == 0 ||
//strcmp(Dir->d_name,"source") == 0 ||
strcmp(Dir->d_name,".disk") == 0 ||
strcmp(Dir->d_name,"experimental") == 0 ||
strcmp(Dir->d_name,"binary-all") == 0 ||