summaryrefslogtreecommitdiff
path: root/apt-inst/deb
diff options
context:
space:
mode:
authorMichael Vogt <egon@debian-devbox>2012-04-16 19:24:07 +0200
committerMichael Vogt <egon@debian-devbox>2012-04-16 19:24:07 +0200
commit443f5e8a3205162ec6933529c5ca0c95ad3f6941 (patch)
tree3e2da22dcecc8eeaabc1ac5ceac0407a8e3cc25f /apt-inst/deb
parent96273866174c54bdb25813633891f29668d43848 (diff)
parentf352743312edeebf666e1c8304cdc4baf457469f (diff)
merge from the expermental2 branch
Diffstat (limited to 'apt-inst/deb')
-rw-r--r--apt-inst/deb/debfile.cc64
-rw-r--r--apt-inst/deb/debfile.h13
-rw-r--r--apt-inst/deb/dpkgdb.cc490
-rw-r--r--apt-inst/deb/dpkgdb.h50
4 files changed, 8 insertions, 609 deletions
diff --git a/apt-inst/deb/debfile.cc b/apt-inst/deb/debfile.cc
index a40cd1ae8..ab4037915 100644
--- a/apt-inst/deb/debfile.cc
+++ b/apt-inst/deb/debfile.cc
@@ -16,6 +16,8 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
+#include<config.h>
+
#include <apt-pkg/debfile.h>
#include <apt-pkg/extracttar.h>
#include <apt-pkg/error.h>
@@ -87,42 +89,6 @@ const ARArchive::Member *debDebFile::GotoMember(const char *Name)
return Member;
}
/*}}}*/
-// DebFile::ExtractControl - Extract Control information /*{{{*/
-// ---------------------------------------------------------------------
-/* Extract the control information into the Database's temporary
- directory. */
-bool debDebFile::ExtractControl(pkgDataBase &DB)
-{
- // Get the archive member and positition the file
- const ARArchive::Member *Member = GotoMember("control.tar.gz");
- if (Member == 0)
- return false;
-
- // Prepare Tar
- ControlExtract Extract;
- ExtractTar Tar(File,Member->Size,"gzip");
- if (_error->PendingError() == true)
- return false;
-
- // Get into the temporary directory
- string Cwd = SafeGetCWD();
- string Tmp;
- if (DB.GetMetaTmp(Tmp) == false)
- return false;
- if (chdir(Tmp.c_str()) != 0)
- return _error->Errno("chdir",_("Couldn't change to %s"),Tmp.c_str());
-
- // Do extraction
- if (Tar.Go(Extract) == false)
- return false;
-
- // Switch out of the tmp directory.
- if (chdir(Cwd.c_str()) != 0)
- chdir("/");
-
- return true;
-}
- /*}}}*/
// DebFile::ExtractArchive - Extract the archive data itself /*{{{*/
// ---------------------------------------------------------------------
/* Simple wrapper around tar.. */
@@ -164,32 +130,6 @@ bool debDebFile::ExtractArchive(pkgDirStream &Stream)
return Tar.Go(Stream);
}
/*}}}*/
-// DebFile::MergeControl - Merge the control information /*{{{*/
-// ---------------------------------------------------------------------
-/* This reads the extracted control file into the cache and returns the
- version that was parsed. All this really does is select the correct
- parser and correct file to parse. */
-pkgCache::VerIterator debDebFile::MergeControl(pkgDataBase &DB)
-{
- // Open the control file
- string Tmp;
- if (DB.GetMetaTmp(Tmp) == false)
- return pkgCache::VerIterator(DB.GetCache());
- FileFd Fd(Tmp + "control",FileFd::ReadOnly);
- if (_error->PendingError() == true)
- return pkgCache::VerIterator(DB.GetCache());
-
- // Parse it
- debListParser Parse(&Fd);
- pkgCache::VerIterator Ver(DB.GetCache());
- if (DB.GetGenerator().MergeList(Parse,&Ver) == false)
- return pkgCache::VerIterator(DB.GetCache());
-
- if (Ver.end() == true)
- _error->Error(_("Failed to locate a valid control file"));
- return Ver;
-}
- /*}}}*/
// DebFile::ControlExtract::DoItem - Control Tar Extraction /*{{{*/
// ---------------------------------------------------------------------
diff --git a/apt-inst/deb/debfile.h b/apt-inst/deb/debfile.h
index 6b9f8ffc8..d94b74446 100644
--- a/apt-inst/deb/debfile.h
+++ b/apt-inst/deb/debfile.h
@@ -25,9 +25,11 @@
#include <apt-pkg/arfile.h>
-#include <apt-pkg/database.h>
#include <apt-pkg/dirstream.h>
#include <apt-pkg/tagfile.h>
+#include <apt-pkg/pkgcache.h>
+
+class FileFd;
class debDebFile
{
@@ -39,13 +41,10 @@ class debDebFile
bool CheckMember(const char *Name);
public:
-
class ControlExtract;
class MemControlExtract;
-
- bool ExtractControl(pkgDataBase &DB);
+
bool ExtractArchive(pkgDirStream &Stream);
- pkgCache::VerIterator MergeControl(pkgDataBase &DB);
const ARArchive::Member *GotoMember(const char *Name);
inline FileFd &GetFile() {return File;};
@@ -68,7 +67,7 @@ class debDebFile::MemControlExtract : public pkgDirStream
char *Control;
pkgTagSection Section;
unsigned long Length;
- string Member;
+ std::string Member;
// Members from DirStream
virtual bool DoItem(Item &Itm,int &Fd);
@@ -81,7 +80,7 @@ class debDebFile::MemControlExtract : public pkgDirStream
bool TakeControl(const void *Data,unsigned long Size);
MemControlExtract() : IsControl(false), Control(0), Length(0), Member("control") {};
- MemControlExtract(string Member) : IsControl(false), Control(0), Length(0), Member(Member) {};
+ MemControlExtract(std::string Member) : IsControl(false), Control(0), Length(0), Member(Member) {};
~MemControlExtract() {delete [] Control;};
};
/*}}}*/
diff --git a/apt-inst/deb/dpkgdb.cc b/apt-inst/deb/dpkgdb.cc
deleted file mode 100644
index a75cf59ca..000000000
--- a/apt-inst/deb/dpkgdb.cc
+++ /dev/null
@@ -1,490 +0,0 @@
-// -*- mode: cpp; mode: fold -*-
-// Description /*{{{*/
-// $Id: dpkgdb.cc,v 1.7.2.1 2004/01/16 18:58:50 mdz Exp $
-/* ######################################################################
-
- DPKGv1 Database Implemenation
-
- This class provides parsers and other implementations for the DPKGv1
- database. It reads the diversion file, the list files and the status
- file to build both the list of currently installed files and the
- currently installed package list.
-
- ##################################################################### */
- /*}}}*/
-// Include Files /*{{{*/
-#include <apt-pkg/dpkgdb.h>
-#include <apt-pkg/configuration.h>
-#include <apt-pkg/error.h>
-#include <apt-pkg/progress.h>
-#include <apt-pkg/tagfile.h>
-#include <apt-pkg/strutl.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <iostream>
-#include <apti18n.h>
- /*}}}*/
-using namespace std;
-
-// EraseDir - Erase A Directory /*{{{*/
-// ---------------------------------------------------------------------
-/* This is necessary to create a new empty sub directory. The caller should
- invoke mkdir after this with the proper permissions and check for
- error. Maybe stick this in fileutils */
-static bool EraseDir(const char *Dir)
-{
- // First we try a simple RM
- if (rmdir(Dir) == 0 ||
- errno == ENOENT)
- return true;
-
- // A file? Easy enough..
- if (errno == ENOTDIR)
- {
- if (unlink(Dir) != 0)
- return _error->Errno("unlink",_("Failed to remove %s"),Dir);
- return true;
- }
-
- // Should not happen
- if (errno != ENOTEMPTY)
- return _error->Errno("rmdir",_("Failed to remove %s"),Dir);
-
- // Purge it using rm
- pid_t Pid = ExecFork();
-
- // Spawn the subprocess
- if (Pid == 0)
- {
- execlp(_config->Find("Dir::Bin::rm","/bin/rm").c_str(),
- "rm","-rf","--",Dir,(char *)NULL);
- _exit(100);
- }
- return ExecWait(Pid,_config->Find("dir::bin::rm","/bin/rm").c_str());
-}
- /*}}}*/
-// DpkgDB::debDpkgDB - Constructor /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-debDpkgDB::debDpkgDB() : CacheMap(0), FileMap(0)
-{
- AdminDir = flNotFile(_config->Find("Dir::State::status"));
- DiverInode = 0;
- DiverTime = 0;
-}
- /*}}}*/
-// DpkgDB::~debDpkgDB - Destructor /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-debDpkgDB::~debDpkgDB()
-{
- delete Cache;
- Cache = 0;
- delete CacheMap;
- CacheMap = 0;
-
- delete FList;
- FList = 0;
- delete FileMap;
- FileMap = 0;
-}
- /*}}}*/
-// DpkgDB::InitMetaTmp - Get the temp dir for meta information /*{{{*/
-// ---------------------------------------------------------------------
-/* This creats+empties the meta temporary directory /var/lib/dpkg/tmp.ci
- Only one package at a time can be using the returned meta directory. */
-bool debDpkgDB::InitMetaTmp(string &Dir)
-{
- string Tmp = AdminDir + "tmp.ci/";
- if (EraseDir(Tmp.c_str()) == false)
- return _error->Error(_("Unable to create %s"),Tmp.c_str());
- if (mkdir(Tmp.c_str(),0755) != 0)
- return _error->Errno("mkdir",_("Unable to create %s"),Tmp.c_str());
-
- // Verify it is on the same filesystem as the main info directory
- dev_t Dev;
- struct stat St;
- if (stat((AdminDir + "info").c_str(),&St) != 0)
- return _error->Errno("stat",_("Failed to stat %sinfo"),AdminDir.c_str());
- Dev = St.st_dev;
- if (stat(Tmp.c_str(),&St) != 0)
- return _error->Errno("stat",_("Failed to stat %s"),Tmp.c_str());
- if (Dev != St.st_dev)
- return _error->Error(_("The info and temp directories need to be on the same filesystem"));
-
- // Done
- Dir = Tmp;
- return true;
-}
- /*}}}*/
-// DpkgDB::ReadyPkgCache - Prepare the cache with the current status /*{{{*/
-// ---------------------------------------------------------------------
-/* This reads in the status file into an empty cache. This really needs
- to be somehow unified with the high level APT notion of the Database
- directory, but there is no clear way on how to do that yet. */
-bool debDpkgDB::ReadyPkgCache(OpProgress &Progress)
-{
- if (Cache != 0)
- {
- Progress.OverallProgress(1,1,1,_("Reading package lists"));
- return true;
- }
-
- if (CacheMap != 0)
- {
- delete CacheMap;
- CacheMap = 0;
- }
-
- if (pkgCacheGenerator::MakeOnlyStatusCache(&Progress,&CacheMap) == false)
- return false;
- Cache->DropProgress();
-
- return true;
-}
- /*}}}*/
-// DpkgDB::ReadFList - Read the File Listings in /*{{{*/
-// ---------------------------------------------------------------------
-/* This reads the file listing in from the state directory. This is a
- performance critical routine, as it needs to parse about 50k lines of
- text spread over a hundred or more files. For an initial cold start
- most of the time is spent in reading file inodes and so on, not
- actually parsing. */
-bool debDpkgDB::ReadFList(OpProgress &Progress)
-{
- // Count the number of packages we need to read information for
- unsigned long Total = 0;
- pkgCache &Cache = this->Cache->GetCache();
- for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
- {
- // Only not installed packages have no files.
- if (I->CurrentState == pkgCache::State::NotInstalled)
- continue;
- Total++;
- }
-
- /* Switch into the admin dir, this prevents useless lookups for the
- path components */
- string Cwd = SafeGetCWD();
- if (chdir((AdminDir + "info/").c_str()) != 0)
- return _error->Errno("chdir",_("Failed to change to the admin dir %sinfo"),AdminDir.c_str());
-
- // Allocate a buffer. Anything larger than this buffer will be mmaped
- unsigned long BufSize = 32*1024;
- char *Buffer = new char[BufSize];
-
- // Begin Loading them
- unsigned long Count = 0;
- char Name[300];
- for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
- {
- /* Only not installed packages have no files. ConfFile packages have
- file lists but we don't want to read them in */
- if (I->CurrentState == pkgCache::State::NotInstalled ||
- I->CurrentState == pkgCache::State::ConfigFiles)
- continue;
-
- // Fetch a package handle to associate with the file
- pkgFLCache::PkgIterator FlPkg = FList->GetPkg(I.Name(),0,true);
- if (FlPkg.end() == true)
- {
- _error->Error(_("Internal error getting a package name"));
- break;
- }
-
- Progress.OverallProgress(Count,Total,1,_("Reading file listing"));
-
- // Open the list file
- snprintf(Name,sizeof(Name),"%s.list",I.Name());
- int Fd = open(Name,O_RDONLY);
-
- /* Okay this is very strange and bad.. Best thing is to bail and
- instruct the user to look into it. */
- struct stat Stat;
- if (Fd == -1 || fstat(Fd,&Stat) != 0)
- {
- _error->Errno("open",_("Failed to open the list file '%sinfo/%s'. If you "
- "cannot restore this file then make it empty "
- "and immediately re-install the same version of the package!"),
- AdminDir.c_str(),Name);
- break;
- }
-
- // Set File to be a memory buffer containing the whole file
- char *File;
- if ((unsigned)Stat.st_size < BufSize)
- {
- if (read(Fd,Buffer,Stat.st_size) != Stat.st_size)
- {
- _error->Errno("read",_("Failed reading the list file %sinfo/%s"),
- AdminDir.c_str(),Name);
- close(Fd);
- break;
- }
- File = Buffer;
- }
- else
- {
- // Use mmap
- File = (char *)mmap(0,Stat.st_size,PROT_READ,MAP_PRIVATE,Fd,0);
- if (File == (char *)(-1))
- {
- _error->Errno("mmap",_("Failed reading the list file %sinfo/%s"),
- AdminDir.c_str(),Name);
- close(Fd);
- break;
- }
- }
-
- // Parse it
- const char *Start = File;
- const char *End = File;
- const char *Finish = File + Stat.st_size;
- for (; End < Finish; End++)
- {
- // Not an end of line
- if (*End != '\n' && End + 1 < Finish)
- continue;
-
- // Skip blank lines
- if (End - Start > 1)
- {
- pkgFLCache::NodeIterator Node = FList->GetNode(Start,End,
- FlPkg.Offset(),true,false);
- if (Node.end() == true)
- {
- _error->Error(_("Internal error getting a node"));
- break;
- }
- }
-
- // Skip past the end of line
- for (; *End == '\n' && End < Finish; End++);
- Start = End;
- }
-
- close(Fd);
- if ((unsigned)Stat.st_size >= BufSize)
- munmap((caddr_t)File,Stat.st_size);
-
- // Failed
- if (End < Finish)
- break;
-
- Count++;
- }
-
- delete [] Buffer;
- if (chdir(Cwd.c_str()) != 0)
- chdir("/");
-
- return !_error->PendingError();
-}
- /*}}}*/
-// DpkgDB::ReadDiversions - Load the diversions file /*{{{*/
-// ---------------------------------------------------------------------
-/* Read the diversion file in from disk. This is usually invoked by
- LoadChanges before performing an operation that uses the FLCache. */
-bool debDpkgDB::ReadDiversions()
-{
- struct stat Stat;
- if (stat((AdminDir + "diversions").c_str(),&Stat) != 0)
- return true;
-
- if (_error->PendingError() == true)
- return false;
-
- FILE *Fd = fopen((AdminDir + "diversions").c_str(),"r");
- if (Fd == 0)
- return _error->Errno("fopen",_("Failed to open the diversions file %sdiversions"),AdminDir.c_str());
-
- FList->BeginDiverLoad();
- while (1)
- {
- char From[300];
- char To[300];
- char Package[100];
-
- // Read the three lines in
- if (fgets(From,sizeof(From),Fd) == 0)
- break;
- if (fgets(To,sizeof(To),Fd) == 0 ||
- fgets(Package,sizeof(Package),Fd) == 0)
- {
- _error->Error(_("The diversion file is corrupted"));
- break;
- }
-
- // Strip the \ns
- unsigned long Len = strlen(From);
- if (Len < 2 || From[Len-1] != '\n')
- _error->Error(_("Invalid line in the diversion file: %s"),From);
- else
- From[Len-1] = 0;
- Len = strlen(To);
- if (Len < 2 || To[Len-1] != '\n')
- _error->Error(_("Invalid line in the diversion file: %s"),To);
- else
- To[Len-1] = 0;
- Len = strlen(Package);
- if (Len < 2 || Package[Len-1] != '\n')
- _error->Error(_("Invalid line in the diversion file: %s"),Package);
- else
- Package[Len-1] = 0;
-
- // Make sure the lines were parsed OK
- if (_error->PendingError() == true)
- break;
-
- // Fetch a package
- if (strcmp(Package,":") == 0)
- Package[0] = 0;
- pkgFLCache::PkgIterator FlPkg = FList->GetPkg(Package,0,true);
- if (FlPkg.end() == true)
- {
- _error->Error(_("Internal error getting a package name"));
- break;
- }
-
- // Install the diversion
- if (FList->AddDiversion(FlPkg,From,To) == false)
- {
- _error->Error(_("Internal error adding a diversion"));
- break;
- }
- }
- if (_error->PendingError() == false)
- FList->FinishDiverLoad();
-
- DiverInode = Stat.st_ino;
- DiverTime = Stat.st_mtime;
-
- fclose(Fd);
- return !_error->PendingError();
-}
- /*}}}*/
-// DpkgDB::ReadFileList - Read the file listing /*{{{*/
-// ---------------------------------------------------------------------
-/* Read in the file listing. The file listing is created from three
- sources, *.list, Conffile sections and the Diversion table. */
-bool debDpkgDB::ReadyFileList(OpProgress &Progress)
-{
- if (Cache == 0)
- return _error->Error(_("The pkg cache must be initialized first"));
- if (FList != 0)
- {
- Progress.OverallProgress(1,1,1,_("Reading file listing"));
- return true;
- }
-
- // Create the cache and read in the file listing
- FileMap = new DynamicMMap(MMap::Public);
- FList = new pkgFLCache(*FileMap);
- if (_error->PendingError() == true ||
- ReadFList(Progress) == false ||
- ReadConfFiles() == false ||
- ReadDiversions() == false)
- {
- delete FList;
- delete FileMap;
- FileMap = 0;
- FList = 0;
- return false;
- }
-
- cout << "Node: " << FList->HeaderP->NodeCount << ',' << FList->HeaderP->UniqNodes << endl;
- cout << "Dir: " << FList->HeaderP->DirCount << endl;
- cout << "Package: " << FList->HeaderP->PackageCount << endl;
- cout << "HashSize: " << FList->HeaderP->HashSize << endl;
- cout << "Size: " << FileMap->Size() << endl;
- cout << endl;
-
- return true;
-}
- /*}}}*/
-// DpkgDB::ReadConfFiles - Read the conf file sections from the s-file /*{{{*/
-// ---------------------------------------------------------------------
-/* Reading the conf files is done by reparsing the status file. This is
- actually rather fast so it is no big deal. */
-bool debDpkgDB::ReadConfFiles()
-{
- FileFd File(_config->FindFile("Dir::State::status"),FileFd::ReadOnly);
- pkgTagFile Tags(&File);
- if (_error->PendingError() == true)
- return false;
-
- pkgTagSection Section;
- while (1)
- {
- // Skip to the next section
- unsigned long Offset = Tags.Offset();
- if (Tags.Step(Section) == false)
- break;
-
- // Parse the line
- const char *Start;
- const char *Stop;
- if (Section.Find("Conffiles",Start,Stop) == false)
- continue;
-
- const char *PkgStart;
- const char *PkgEnd;
- if (Section.Find("Package",PkgStart,PkgEnd) == false)
- return _error->Error(_("Failed to find a Package: header, offset %lu"),Offset);
-
- // Snag a package record for it
- pkgFLCache::PkgIterator FlPkg = FList->GetPkg(PkgStart,PkgEnd,true);
- if (FlPkg.end() == true)
- return _error->Error(_("Internal error getting a package name"));
-
- // Parse the conf file lines
- while (1)
- {
- for (; isspace(*Start) != 0 && Start < Stop; Start++);
- if (Start == Stop)
- break;
-
- // Split it into words
- const char *End = Start;
- for (; isspace(*End) == 0 && End < Stop; End++);
- const char *StartMd5 = End;
- for (; isspace(*StartMd5) != 0 && StartMd5 < Stop; StartMd5++);
- const char *EndMd5 = StartMd5;
- for (; isspace(*EndMd5) == 0 && EndMd5 < Stop; EndMd5++);
- if (StartMd5 == EndMd5 || Start == End)
- return _error->Error(_("Bad ConfFile section in the status file. Offset %lu"),Offset);
-
- // Insert a new entry
- unsigned char MD5[16];
- if (Hex2Num(string(StartMd5,EndMd5-StartMd5),MD5,16) == false)
- return _error->Error(_("Error parsing MD5. Offset %lu"),Offset);
-
- if (FList->AddConfFile(Start,End,FlPkg,MD5) == false)
- return false;
- Start = EndMd5;
- }
- }
-
- return true;
-}
- /*}}}*/
-// DpkgDB::LoadChanges - Read in any changed state files /*{{{*/
-// ---------------------------------------------------------------------
-/* The only file in the dpkg system that can change while packages are
- unpacking is the diversions file. */
-bool debDpkgDB::LoadChanges()
-{
- struct stat Stat;
- if (stat((AdminDir + "diversions").c_str(),&Stat) != 0)
- return true;
- if (DiverInode == Stat.st_ino && DiverTime == Stat.st_mtime)
- return true;
- return ReadDiversions();
-}
- /*}}}*/
diff --git a/apt-inst/deb/dpkgdb.h b/apt-inst/deb/dpkgdb.h
deleted file mode 100644
index 125845f96..000000000
--- a/apt-inst/deb/dpkgdb.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// -*- mode: cpp; mode: fold -*-
-// Description /*{{{*/
-// $Id: dpkgdb.h,v 1.2 2001/02/20 07:03:17 jgg Exp $
-/* ######################################################################
-
- DPKGv1 Data Base Implemenation
-
- The DPKGv1 database is typically stored in /var/lib/dpkg/. For
- DPKGv1 the 'meta' information is the contents of the .deb control.tar.gz
- member prepended by the package name. The meta information is unpacked
- in its temporary directory and then migrated into the main list dir
- at a checkpoint.
-
- Journaling is providing by syncronized file writes to the updates sub
- directory.
-
- ##################################################################### */
- /*}}}*/
-#ifndef PKGLIB_DPKGDB_H
-#define PKGLIB_DPKGDB_H
-
-
-#include <apt-pkg/database.h>
-
-class debDpkgDB : public pkgDataBase
-{
- protected:
-
- string AdminDir;
- DynamicMMap *CacheMap;
- DynamicMMap *FileMap;
- unsigned long DiverInode;
- signed long DiverTime;
-
- virtual bool InitMetaTmp(string &Dir);
- bool ReadFList(OpProgress &Progress);
- bool ReadDiversions();
- bool ReadConfFiles();
-
- public:
-
- virtual bool ReadyFileList(OpProgress &Progress);
- virtual bool ReadyPkgCache(OpProgress &Progress);
- virtual bool LoadChanges();
-
- debDpkgDB();
- virtual ~debDpkgDB();
-};
-
-#endif