diff options
-rw-r--r-- | apt-pkg/cacheiterators.h | 281 | ||||
-rw-r--r-- | apt-pkg/contrib/error.cc | 139 | ||||
-rw-r--r-- | apt-pkg/contrib/error.h | 84 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 214 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.h | 63 | ||||
-rw-r--r-- | apt-pkg/contrib/mmap.cc | 227 | ||||
-rw-r--r-- | apt-pkg/contrib/mmap.h | 92 | ||||
-rw-r--r-- | apt-pkg/contrib/system.h | 57 | ||||
-rw-r--r-- | apt-pkg/pkgcache.cc | 360 | ||||
-rw-r--r-- | apt-pkg/pkgcache.h | 280 | ||||
-rw-r--r-- | apt-pkg/pkgcachegen.cc | 184 | ||||
-rw-r--r-- | apt-pkg/pkgcachegen.h | 69 | ||||
-rw-r--r-- | apt-pkg/tagfile.cc | 195 | ||||
-rw-r--r-- | apt-pkg/tagfile.h | 64 | ||||
-rw-r--r-- | apt-pkg/version.cc | 249 | ||||
-rw-r--r-- | apt-pkg/version.h | 45 | ||||
-rw-r--r-- | doc/apt-cache.8 | 199 | ||||
-rw-r--r-- | doc/apt-get.8 | 250 | ||||
-rw-r--r-- | doc/apt.8 | 50 | ||||
-rw-r--r-- | doc/cache.sgml | 761 | ||||
-rw-r--r-- | doc/design.sgml | 411 | ||||
-rw-r--r-- | doc/dpkg-tech.sgml | 509 | ||||
-rw-r--r-- | doc/files.sgml | 491 | ||||
-rw-r--r-- | doc/ftp.conf.5 | 93 | ||||
-rw-r--r-- | doc/guide.sgml | 548 | ||||
-rw-r--r-- | doc/sources.list.5 | 177 |
26 files changed, 6092 insertions, 0 deletions
diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h new file mode 100644 index 000000000..539444c33 --- /dev/null +++ b/apt-pkg/cacheiterators.h @@ -0,0 +1,281 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: cacheiterators.h,v 1.1 1998/07/02 02:58:12 jgg Exp $ +/* ###################################################################### + + Cache Iterators - Iterators for navigating the cache structure + + The iterators all provides ++,==,!=,->,* and end for their type. + The end function can be used to tell if the list has been fully + traversed. + + Unlike STL iterators these contain helper functions to access the data + that is being iterated over. This is because the data structures can't + be formed in a manner that is intuitive to use and also mmapable. + + For each variable in the target structure that would need a translation + to be accessed correctly a translating function of the same name is + present in the iterator. If applicable the translating function will + return an iterator. + + The DepIterator can iterate over two lists, a list of 'version depends' + or a list of 'package reverse depends'. The type is determined by the + structure passed to the constructor, which should be the structure + that has the depends pointer as a member. + + This header is not user includable, please use pkglib/pkgcache.h + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_CACHEITERATORS_H +#define PKGLIB_CACHEITERATORS_H + +// Package Iterator +class pkgCache::PkgIterator +{ + Package *Pkg; + pkgCache *Owner; + long HashIndex; + + public: + + enum OkState {NeedsNothing,NeedsUnpack,NeedsConfigure}; + + // Iteration + void operator ++(int); + inline void operator ++() {operator ++(0);}; + inline bool end() const {return Owner == 0 || Pkg == Owner->PkgP?true:false;}; + + // Comparison + inline bool operator ==(const PkgIterator &B) const {return Pkg == B.Pkg;}; + inline bool operator !=(const PkgIterator &B) const {return Pkg != B.Pkg;}; + + // Accessors + inline Package *operator ->() {return Pkg;}; + inline Package const *operator ->() const {return Pkg;}; + inline Package const &operator *() const {return *Pkg;}; + inline operator Package *() {return Pkg == Owner->PkgP?0:Pkg;}; + inline operator Package const *() const {return Pkg == Owner->PkgP?0:Pkg;}; + inline const char *Name() const {return Pkg->Name == 0?0:Owner->StrP + Pkg->Name;}; + inline const char *Section() const {return Pkg->Section == 0?0:Owner->StrP + Pkg->Section;}; + inline const char *TargetDist() const {return Pkg->TargetDist == 0?0:Owner->StrP + Pkg->TargetDist;}; + inline VerIterator VersionList() const; + inline VerIterator TargetVer() const; + inline VerIterator CurrentVer() const; + inline DepIterator RevDependsList() const; + inline PrvIterator ProvidesList() const; + OkState State() const; + + // Constructors + inline PkgIterator(pkgCache &Owner) : Owner(&Owner), HashIndex(-1) + { + Pkg = Owner.PkgP; + operator ++(0); + }; + inline PkgIterator(pkgCache &Owner,Package *Trg) : Pkg(Trg), Owner(&Owner), + HashIndex(0) + { + if (Pkg == 0) + Pkg = Owner.PkgP; + }; + inline PkgIterator() : Pkg(0), Owner(0), HashIndex(0) {}; +}; + +// Version Iterator +class pkgCache::VerIterator +{ + Version *Ver; + pkgCache &Owner; + + void _dummy(); + + public: + + // Iteration + void operator ++(int) {if (Ver != Owner.VerP) Ver = Owner.VerP + Ver->NextVer;}; + inline void operator ++() {operator ++(0);}; + inline bool end() const {return Ver == Owner.VerP?true:false;}; + inline void operator =(const VerIterator &B) {Ver = B.Ver;}; + + // Comparison + inline bool operator ==(const VerIterator &B) const {return Ver == B.Ver;}; + inline bool operator !=(const VerIterator &B) const {return Ver != B.Ver;}; + int CompareVer(const VerIterator &B) const; + + // Accessors + inline Version *operator ->() {return Ver;}; + inline Version const *operator ->() const {return Ver;}; + inline Version &operator *() {return *Ver;}; + inline Version const &operator *() const {return *Ver;}; + inline operator Version *() {return Ver == Owner.VerP?0:Ver;}; + inline operator Version const *() const {return Ver == Owner.VerP?0:Ver;}; + inline const char *VerStr() const {return Ver->VerStr == 0?0:Owner.StrP + Ver->VerStr;}; + inline const char *Section() const {return Ver->Section == 0?0:Owner.StrP + Ver->Section;}; + inline PkgFileIterator File() const; + inline PkgIterator ParentPkg() const {return PkgIterator(Owner,Owner.PkgP + Ver->ParentPkg);}; + inline DepIterator DependsList() const; + inline PrvIterator ProvidesList() const; + + inline VerIterator(pkgCache &Owner,Version *Trg) : Ver(Trg), Owner(Owner) + { + if (Ver == 0) + Ver = Owner.VerP; + }; +}; + +// Dependency iterator +class pkgCache::DepIterator +{ + Dependency *Dep; + enum {DepVer, DepRev} Type; + pkgCache *Owner; + + void _dummy(); + + public: + + // Iteration + void operator ++(int) {if (Dep != Owner->DepP) Dep = Owner->DepP + + (Type == DepVer?Dep->NextDepends:Dep->NextRevDepends);}; + inline void operator ++() {operator ++(0);}; + inline bool end() const {return Owner == 0 || Dep == Owner->DepP?true:false;}; + + // Comparison + inline bool operator ==(const DepIterator &B) const {return Dep == B.Dep;}; + inline bool operator !=(const DepIterator &B) const {return Dep != B.Dep;}; + + // Accessors + inline Dependency *operator ->() {return Dep;}; + inline Dependency const *operator ->() const {return Dep;}; + inline Dependency &operator *() {return *Dep;}; + inline Dependency const &operator *() const {return *Dep;}; + inline operator Dependency *() {return Dep == Owner->DepP?0:Dep;}; + inline operator Dependency const *() const {return Dep == Owner->DepP?0:Dep;}; + inline const char *TargetVer() const {return Dep->Version == 0?0:Owner->StrP + Dep->Version;}; + inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + Dep->Package);}; + Version **AllTargets(); + bool SmartTargetPkg(PkgIterator &Result); + inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner);SmartTargetPkg(R);return R;}; + inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + Dep->ParentVer);}; + inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Dep->ParentVer].ParentPkg);}; + bool IsCritical(); + inline bool Reverse() {return Type == DepRev;}; + + inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) : + Dep(Trg), Type(DepVer), Owner(&Owner) + { + if (Dep == 0) + Dep = Owner.DepP; + }; + inline DepIterator(pkgCache &Owner,Dependency *Trg,Package *) : + Dep(Trg), Type(DepRev), Owner(&Owner) + { + if (Dep == 0) + Dep = Owner.DepP; + }; + inline DepIterator() : Dep(0), Type(DepVer), Owner(0) {}; +}; + +// Provides iterator +class pkgCache::PrvIterator +{ + Provides *Prv; + enum {PrvVer, PrvPkg} Type; + pkgCache *Owner; + + void _dummy(); + + public: + + // Iteration + void operator ++(int) {if (Prv != Owner->ProvideP) Prv = Owner->ProvideP + + (Type == PrvVer?Prv->NextPkgProv:Prv->NextProvides);}; + inline void operator ++() {operator ++(0);}; + inline bool end() const {return Prv == Owner->ProvideP?true:false;}; + + // Comparison + inline bool operator ==(const PrvIterator &B) const {return Prv == B.Prv;}; + inline bool operator !=(const PrvIterator &B) const {return Prv != B.Prv;}; + + // Accessors + inline Provides *operator ->() {return Prv;}; + inline Provides const *operator ->() const {return Prv;}; + inline Provides &operator *() {return *Prv;}; + inline Provides const &operator *() const {return *Prv;}; + inline operator Provides *() {return Prv == Owner->ProvideP?0:Prv;}; + inline operator Provides const *() const {return Prv == Owner->ProvideP?0:Prv;}; + inline const char *Name() const {return Owner->StrP + Owner->PkgP[Prv->ParentPkg].Name;}; + inline const char *ProvideVersion() const {return Prv->ProvideVersion == 0?0:Owner->StrP + Prv->ProvideVersion;}; + inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Prv->ParentPkg);}; + inline VerIterator OwnerVer() {return VerIterator(*Owner,Owner->VerP + Prv->Version);}; + inline PkgIterator OwnerPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Prv->Version].ParentPkg);}; + + inline PrvIterator(pkgCache &Owner,Provides *Trg,Version *) : + Prv(Trg), Type(PrvVer), Owner(&Owner) + { + if (Prv == 0) + Prv = Owner.ProvideP; + }; + inline PrvIterator(pkgCache &Owner,Provides *Trg,Package *) : + Prv(Trg), Type(PrvPkg), Owner(&Owner) + { + if (Prv == 0) + Prv = Owner.ProvideP; + }; +}; + +// Package file +class pkgCache::PkgFileIterator +{ + pkgCache *Owner; + PackageFile *File; + + public: + + // Iteration + void operator ++(int) {if (File!= Owner->PkgFileP) File = Owner->PkgFileP + File->NextFile;}; + inline void operator ++() {operator ++(0);}; + inline bool end() const {return File == Owner->PkgFileP?true:false;}; + + // Comparison + inline bool operator ==(const PkgFileIterator &B) const {return File == B.File;}; + inline bool operator !=(const PkgFileIterator &B) const {return File != B.File;}; + + // Accessors + inline PackageFile *operator ->() {return File;}; + inline PackageFile const *operator ->() const {return File;}; + inline PackageFile const &operator *() const {return *File;}; + inline operator PackageFile *() {return File == Owner->PkgFileP?0:File;}; + inline operator PackageFile const *() const {return File == Owner->PkgFileP?0:File;}; + + inline const char *FileName() const {return File->FileName == 0?0:Owner->StrP + File->FileName;}; + inline const char *Version() const {return File->Version == 0?0:Owner->StrP + File->Version;}; + inline const char *Distribution() const {return File->Distribution == 0?0:Owner->StrP + File->Distribution;}; + + bool IsOk(); + + // Constructors + inline PkgFileIterator(pkgCache &Owner) : Owner(&Owner), File(Owner.PkgFileP + Owner.Head().FileList) {}; + inline PkgFileIterator(pkgCache &Owner,PackageFile *Trg) : Owner(&Owner), File(Trg) {}; +}; + +// Inlined Begin functions cant be in the class because of order problems +inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const + {return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);}; +inline pkgCache::VerIterator pkgCache::PkgIterator::CurrentVer() const + {return VerIterator(*Owner,Owner->VerP + Pkg->CurrentVer);}; +inline pkgCache::VerIterator pkgCache::PkgIterator::TargetVer() const + {return VerIterator(*Owner,Owner->VerP + Pkg->TargetVer);}; +inline pkgCache::DepIterator pkgCache::PkgIterator::RevDependsList() const + {return DepIterator(*Owner,Owner->DepP + Pkg->RevDepends,Pkg);}; +inline pkgCache::PrvIterator pkgCache::PkgIterator::ProvidesList() const + {return PrvIterator(*Owner,Owner->ProvideP + Pkg->ProvidesList,Pkg);}; +inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const + {return PrvIterator(Owner,Owner.ProvideP + Ver->ProvidesList,Ver);}; +inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const + {return DepIterator(Owner,Owner.DepP + Ver->DependsList,Ver);}; +inline pkgCache::PkgFileIterator pkgCache::VerIterator::File() const + {return PkgFileIterator(Owner,Owner.PkgFileP + Ver->File);}; + +#endif diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc new file mode 100644 index 000000000..59d2b8c8b --- /dev/null +++ b/apt-pkg/contrib/error.cc @@ -0,0 +1,139 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: error.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + Global Erorr Class - Global error mechanism + + We use a simple STL vector to store each error record. A PendingFlag + is kept which indicates when the vector contains a Sever error. + + This source is placed in the Public Domain, do with it what you will + It was originally written by Jason Gunthorpe. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#include <pkglib/error.h> + /*}}}*/ + +GlobalError *_error = new GlobalError; + +// GlobalError::GlobalError - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +GlobalError::GlobalError() : PendingFlag(false) +{ +} + /*}}}*/ +// GlobalError::Errno - Get part of the error string from errno /*{{{*/ +// --------------------------------------------------------------------- +/* Function indicates the stdlib function that failed and Description is + a user string that leads the text. Form is: + Description - Function (errno: strerror) + Carefull of the buffer overrun, sprintf. + */ +bool GlobalError::Errno(const char *Function,const char *Description,...) +{ + va_list args; + va_start(args,Description); + + // sprintf the description + char S[400]; + vsprintf(S,Description,args); + sprintf(S + strlen(S)," - %s (%i %s)",Function,errno,strerror(errno)); + + // Put it on the list + Item Itm; + Itm.Text = S; + Itm.Error = true; + List.push_back(Itm); + + PendingFlag = true; + + return false; +} + /*}}}*/ +// GlobalError::Error - Add an error to the list /*{{{*/ +// --------------------------------------------------------------------- +/* Just vsprintfs and pushes */ +bool GlobalError::Error(const char *Description,...) +{ + va_list args; + va_start(args,Description); + + // sprintf the description + char S[400]; + vsprintf(S,Description,args); + + // Put it on the list + Item Itm; + Itm.Text = S; + Itm.Error = true; + List.push_back(Itm); + + PendingFlag = true; + + return false; +} + /*}}}*/ +// GlobalError::Warning - Add a warning to the list /*{{{*/ +// --------------------------------------------------------------------- +/* This doesn't set the pending error flag */ +bool GlobalError::Warning(const char *Description,...) +{ + va_list args; + va_start(args,Description); + + // sprintf the description + char S[400]; + vsprintf(S,Description,args); + + // Put it on the list + Item Itm; + Itm.Text = S; + Itm.Error = false; + List.push_back(Itm); + + return false; +} + /*}}}*/ +// GlobalError::PopMessage - Pulls a single message out /*{{{*/ +// --------------------------------------------------------------------- +/* This should be used in a loop checking empty() each cycle. It returns + true if the message is an error. */ +bool GlobalError::PopMessage(string &Text) +{ + bool Ret = List.front().Error; + Text = List.front().Text; + List.erase(List.begin()); + + // This really should check the list to see if only warnings are left.. + if (empty()) + PendingFlag = false; + + return Ret; +} + /*}}}*/ +// GlobalError::DumpErrors - Dump all of the errors/warns to cerr /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void GlobalError::DumpErrors() +{ + // Print any errors or warnings found + string Err; + while (empty() == false) + { + bool Type = PopMessage(Err); + if (Type == true) + cerr << "E: " << Err << endl; + else + cerr << "W: " << Err << endl; + } +} + /*}}}*/ diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h new file mode 100644 index 000000000..06b998e5e --- /dev/null +++ b/apt-pkg/contrib/error.h @@ -0,0 +1,84 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: error.h,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + Global Erorr Class - Global error mechanism + + This class has a single global instance. When a function needs to + generate an error condition, such as a read error, it calls a member + in this class to add the error to a stack of errors. + + By using a stack the problem with a scheme like errno is removed and + it allows a very detailed account of what went wrong to be transmitted + to the UI for display. (Errno has problems because each function sets + errno to 0 if it didn't have an error thus eraseing erno in the process + of cleanup) + + Several predefined error generators are provided to handle common + things like errno. The general idea is that all methods return a bool. + If the bool is true then things are OK, if it is false then things + should start being undone and the stack should unwind under program + control. + + A Warning should not force the return of false. Things did not fail, but + they might have had unexpected problems. Errors are stored in a FIFO + so Pop will return the first item.. + + I have some thoughts about extending this into a more general UI<-> + Engine interface, ie allowing the Engine to say 'The disk is full' in + a dialog that says 'Panic' and 'Retry'.. The error generator functions + like errno, Warning and Error return false always so this is normal: + if (open(..)) + return _error->Errno(..); + + This source is placed in the Public Domain, do with it what you will + It was originally written by Jason Gunthorpe. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_ERROR_H +#define PKGLIB_ERROR_H + +#include <string> +#include <vector.h> + +class GlobalError +{ + struct Item + { + string Text; + bool Error; + }; + + vector<Item> List; + bool PendingFlag; + + public: + + // Call to generate an error from a library call. + bool Errno(const char *Function,const char *Description,...); + + /* A warning should be considered less severe than an error, and may be + ignored by the client. */ + bool Error(const char *Description,...); + bool Warning(const char *Description,...); + + // Simple accessors + inline bool PendingError() {return PendingFlag;}; + inline bool empty() {return List.empty();}; + bool PopMessage(string &Text); + void Discard() {List.erase(List.begin(),List.end()); PendingFlag = false;}; + + // Usefull routine to dump to cerr + void DumpErrors(); + + GlobalError(); +}; + +/* The 'extra-ansi' syntax is used to help with collisions. This is the + single global instance of this class. */ +extern GlobalError *_error; + +#endif diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc new file mode 100644 index 000000000..6048ff0bb --- /dev/null +++ b/apt-pkg/contrib/fileutl.cc @@ -0,0 +1,214 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: fileutl.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + File Utilities + + CopyFile - Buffered copy of a single file + GetLock - dpkg compatible lock file manipulation (fcntl) + + This source is placed in the Public Domain, do with it what you will + It was originally written by Jason Gunthorpe. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <fileutl.h> +#include <pkglib/error.h> + +#include <unistd.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <sys/types.h> + /*}}}*/ + +// CopyFile - Buffered copy of a file /*{{{*/ +// --------------------------------------------------------------------- +/* The caller is expected to set things so that failure causes erasure */ +bool CopyFile(File From,File To) +{ + if (From.IsOpen() == false || To.IsOpen() == false) + return false; + + // Buffered copy between fds + unsigned char *Buf = new unsigned char[64000]; + long Size; + while ((Size = read(From.Fd(),Buf,64000)) > 0) + { + if (To.Write(Buf,Size) == false) + { + delete [] Buf; + return false; + } + } + + delete [] Buf; + return true; +} + /*}}}*/ +// GetLock - Gets a lock file /*{{{*/ +// --------------------------------------------------------------------- +/* This will create an empty file of the given name and lock it. Once this + is done all other calls to GetLock in any other process will fail with + -1. The return result is the fd of the file, the call should call + close at some time. */ +int GetLock(string File,bool Errors) +{ + int FD = open(File.c_str(),O_RDWR | O_CREAT | O_TRUNC,0640); + if (FD < 0) + { + if (Errors == true) + _error->Errno("open","Could not open lock file %s",File.c_str()); + return -1; + } + + // Aquire a write lock + struct flock fl; + fl.l_type= F_WRLCK; + fl.l_whence= SEEK_SET; + fl.l_start= 0; + fl.l_len= 1; + if (fcntl(FD,F_SETLK,&fl) == -1) + { + if (Errors == true) + _error->Errno("open","Could not get lock %s",File.c_str()); + close(FD); + return -1; + } + + return FD; +} + /*}}}*/ +// FileExists - Check if a file exists /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool FileExists(string File) +{ + struct stat Buf; + if (stat(File.c_str(),&Buf) != 0) + return false; + return true; +} + /*}}}*/ +// SafeGetCWD - This is a safer getcwd that returns a dynamic string /*{{{*/ +// --------------------------------------------------------------------- +/* We return / on failure. */ +string SafeGetCWD() +{ + // Stash the current dir. + char S[300]; + S[0] = 0; + if (getcwd(S,sizeof(S)) == 0) + return "/"; + return S; +} + /*}}}*/ + +// File::File - Open a file /*{{{*/ +// --------------------------------------------------------------------- +/* The most commonly used open mode combinations are given with Mode */ +File::File(string FileName,OpenMode Mode, unsigned long Perms) +{ + Flags = 0; + switch (Mode) + { + case ReadOnly: + iFd = open(FileName.c_str(),O_RDONLY); + break; + + case WriteEmpty: + unlink(FileName.c_str()); + iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms); + break; + + case WriteExists: + iFd = open(FileName.c_str(),O_RDWR); + break; + } + + if (iFd < 0) + _error->Errno("open","Could not open file %s",FileName.c_str()); + else + this->FileName = FileName; +} + /*}}}*/ +// File::~File - Closes the file /*{{{*/ +// --------------------------------------------------------------------- +/* If the proper modes are selected then we close the Fd and possibly + unlink the file on error. */ +File::~File() +{ + Close(); +} + /*}}}*/ +// File::Read - Read a bit of the file /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool File::Read(void *To,unsigned long Size) +{ + if (read(iFd,To,Size) != (signed)Size) + { + Flags |= Fail; + return _error->Errno("read","Read error"); + } + + return true; +} + /*}}}*/ +// File::Write - Write to the file /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool File::Write(void *From,unsigned long Size) +{ + if (write(iFd,From,Size) != (signed)Size) + { + Flags |= Fail; + return _error->Errno("write","Write error"); + } + + return true; +} + /*}}}*/ +// File::Seek - Seek in the file /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool File::Seek(unsigned long To) +{ + if (lseek(iFd,To,SEEK_SET) != (signed)To) + { + Flags |= Fail; + return _error->Error("Unable to seek to %u",To); + } + + return true; +} + /*}}}*/ +// File::Size - Return the size of the file /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned long File::Size() +{ + struct stat Buf; + if (fstat(iFd,&Buf) != 0) + return _error->Errno("fstat","Unable to determine the file size"); + return Buf.st_size; +} + /*}}}*/ +// File::Close - Close the file if the close flag is set /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool File::Close() +{ + bool Res = true; + if ((Flags & AutoClose) == AutoClose) + if (close(iFd) != 0) + Res &= _error->Errno("close","Problem closing the file"); + + if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail && + FileName.empty() == false) + if (unlink(FileName.c_str()) != 0) + Res &= _error->Warning("unlnk","Problem unlinking the file"); + return Res; +} + /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h new file mode 100644 index 000000000..1b6666843 --- /dev/null +++ b/apt-pkg/contrib/fileutl.h @@ -0,0 +1,63 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: fileutl.h,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + File Utilities + + CopyFile - Buffered copy of a single file + GetLock - dpkg compatible lock file manipulation (fcntl) + FileExists - Returns true if the file exists + SafeGetCWD - Returns the CWD in a string with overrun protection + + The file class is a handy abstraction for various functions+classes + that need to accept filenames. + + This source is placed in the Public Domain, do with it what you will + It was originally written by Jason Gunthorpe. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_FILEUTL_H +#define PKGLIB_FILEUTL_H + +#include <string> + +class File +{ + protected: + int iFd; + + enum LocalFlags {AutoClose = (1<<0),Fail = (1<<1),DelOnFail = (1<<2)}; + unsigned long Flags; + string FileName; + + public: + enum OpenMode {ReadOnly,WriteEmpty,WriteExists}; + + bool Read(void *To,unsigned long Size); + bool Write(void *From,unsigned long Size); + bool Seek(unsigned long To); + unsigned long Size(); + bool Close(); + + // Simple manipulators + inline int Fd() {return iFd;}; + inline bool IsOpen() {return iFd >= 0;}; + inline bool Failed() {return (Flags & Fail) == Fail;}; + inline void EraseOnFailure() {Flags |= DelOnFail;}; + inline void OpFail() {Flags |= Fail;}; + + File(string FileName,OpenMode Mode,unsigned long Perms = 0666); + File(int Fd) : iFd(Fd), Flags(AutoClose) {}; + File(int Fd,bool) : iFd(Fd), Flags(0) {}; + virtual ~File(); +}; + +bool CopyFile(string From,string To); +int GetLock(string File,bool Errors = true); +bool FileExists(string File); +string SafeGetCWD(); + +#endif diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc new file mode 100644 index 000000000..85cac1cca --- /dev/null +++ b/apt-pkg/contrib/mmap.cc @@ -0,0 +1,227 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: mmap.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + MMap Class - Provides 'real' mmap or a faked mmap using read(). + + MMap cover class. + + Some broken versions of glibc2 (libc6) have a broken definition + of mmap that accepts a char * -- all other systems (and libc5) use + void *. We can't safely do anything here that would be portable, so + libc6 generates warnings -- which should be errors, g++ isn't properly + strict. + + The configure test notes that some OS's have broken private mmap's + so on those OS's we can't use mmap. This means we have to use + configure to test mmap and can't rely on the POSIX + _POSIX_MAPPED_FILES test. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#define _BSD_SOURCE +#include <pkglib/mmap.h> +#include <pkglib/error.h> + +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/user.h> +#include <unistd.h> +#include <fcntl.h> + /*}}}*/ + +// MMap::MMap - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +MMap::MMap(File &F,unsigned long Flags) : Fd(F), Flags(Flags), iSize(0), + Base(0) +{ + if ((Flags & NoImmMap) != NoImmMap) + Map(); +} + /*}}}*/ +// MMap::~MMap - Destructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +MMap::~MMap() +{ + Close(true); +} + /*}}}*/ +// MMap::Map - Perform the mapping /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool MMap::Map() +{ + iSize = Fd.Size(); + + // Set the permissions. + int Prot = PROT_READ; + int Map = MAP_SHARED; + if ((Flags & ReadOnly) != ReadOnly) + Prot |= PROT_WRITE; + if ((Flags & Public) != Public) + Map = MAP_PRIVATE; + + // Map it. + Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0); + if (Base == (void *)-1) + return _error->Errno("mmap","Couldn't make mmap of %u bytes",iSize); + + return true; +} + /*}}}*/ +// MMap::Close - Close the map /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool MMap::Close(bool DoClose) +{ + if (Fd.IsOpen() == false) + return true; + + Sync(); + + if (munmap((char *)Base,iSize) != 0) + _error->Warning("Unable to munmap"); + + iSize = 0; + if (DoClose == true) + Fd.Close(); + return true; +} + /*}}}*/ +// MMap::Sync - Syncronize the map with the disk /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool MMap::Sync() +{ + if ((Flags & ReadOnly) == ReadOnly) + if (msync((char *)Base,iSize,MS_SYNC) != 0) + return _error->Error("msync","Unable to write mmap"); + return true; +} + /*}}}*/ +// MMap::Sync - Syncronize a section of the file to disk /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool MMap::Sync(unsigned long Start,unsigned long Stop) +{ + if ((Flags & ReadOnly) == ReadOnly) + if (msync((char *)Base+(int)(Start/PAGE_SIZE)*PAGE_SIZE,Stop - Start,MS_SYNC) != 0) + return _error->Error("msync","Unable to write mmap"); + return true; +} + /*}}}*/ + +// DynamicMMap::DynamicMMap - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +DynamicMMap::DynamicMMap(File &F,unsigned long Flags,unsigned long WorkSpace) : + MMap(F,Flags | NoImmMap), WorkSpace(WorkSpace) +{ + unsigned long EndOfFile = Fd.Size(); + Fd.Seek(WorkSpace); + char C = 0; + Fd.Write(&C,sizeof(C)); + Map(); + iSize = EndOfFile; +} + /*}}}*/ +// DynamicMMap::~DynamicMMap - Destructor /*{{{*/ +// --------------------------------------------------------------------- +/* We truncate the file to the size of the memory data set */ +DynamicMMap::~DynamicMMap() +{ + unsigned long EndOfFile = iSize; + Close(false); + ftruncate(Fd.Fd(),EndOfFile); + Fd.Close(); +} + /*}}}*/ +// DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned long DynamicMMap::RawAllocate(unsigned long Size) +{ + unsigned long Result = iSize; + iSize += Size; + + // Just in case error check + if (Result > WorkSpace) + { + _error->Error("Dynamic MMap ran out of room"); + return 0; + } + + return Result; +} + /*}}}*/ +// DynamicMMap::Allocate - Pooled aligned allocation /*{{{*/ +// --------------------------------------------------------------------- +/* This allocates an Item of size ItemSize so that it is aligned to its + size in the file. */ +unsigned long DynamicMMap::Allocate(unsigned long ItemSize) +{ + // Look for a matching pool entry + Pool *I; + Pool *Empty = 0; + for (I = Pools; I != Pools + PoolCount; I++) + { + if (I->ItemSize == 0) + Empty = I; + if (I->ItemSize == ItemSize) + break; + } + + // No pool is allocated, use an unallocated one + if (I == Pools + PoolCount) + { + // Woops, we ran out, the calling code should allocate more. + if (Empty == 0) + { + _error->Error("Ran out of allocation pools"); + return 0; + } + + I = Empty; + I->ItemSize = ItemSize; + I->Count = 0; + } + + // Out of space, allocate some more + if (I->Count == 0) + { + I->Count = 20*1024/ItemSize; + I->Start = RawAllocate(I->Count*ItemSize); + } + + I->Count--; + unsigned long Result = I->Start; + I->Start += ItemSize; + return Result/ItemSize; +} + /*}}}*/ +// DynamicMMap::WriteString - Write a string to the file /*{{{*/ +// --------------------------------------------------------------------- +/* Strings are not aligned to anything */ +unsigned long DynamicMMap::WriteString(const char *String, + unsigned long Len) +{ + unsigned long Result = iSize; + // Just in case error check + if (Result > WorkSpace) + { + _error->Error("Dynamic MMap ran out of room"); + return 0; + } + + if (Len == 0) + Len = strlen(String); + iSize += Len + 1; + memcpy((char *)Base + Result,String,Len); + ((char *)Base)[Result + Len] = 0; + return Result; +} + /*}}}*/ diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h new file mode 100644 index 000000000..096304177 --- /dev/null +++ b/apt-pkg/contrib/mmap.h @@ -0,0 +1,92 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: mmap.h,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + MMap Class - Provides 'real' mmap or a faked mmap using read(). + + The purpose of this code is to provide a generic way for clients to + access the mmap function. In enviroments that do not support mmap + from file fd's this function will use read and normal allocated + memory. + + Writing to a public mmap will always fully comit all changes when the + class is deleted. Ie it will rewrite the file, unless it is readonly + + The DynamicMMap class is used to help the on-disk data structure + generators. It provides a large allocated workspace and members + to allocate space from the workspace in an effecient fashion. + + This source is placed in the Public Domain, do with it what you will + It was originally written by Jason Gunthorpe. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_MMAP_H +#define PKGLIB_MMAP_H + +#include <string> +#include <pkglib/fileutl.h> + +class MMap +{ + protected: + + File &Fd; + unsigned long Flags; + unsigned long iSize; + void *Base; + + bool Map(); + bool Close(bool DoClose = true); + + public: + + enum OpenFlags {NoImmMap = (1<<0),Public = (1<<1),ReadOnly = (1<<2)}; + + // Simple accessors + inline operator void *() {return Base;}; + inline void *Data() {return Base;}; + inline unsigned long Size() {return iSize;}; + + // File manipulators + bool Sync(); + bool Sync(unsigned long Start,unsigned long Stop); + + MMap(File &F,unsigned long Flags); + virtual ~MMap(); +}; + +class DynamicMMap : public MMap +{ + public: + + // This is the allocation pool structure + struct Pool + { + unsigned long ItemSize; + unsigned long Start; + unsigned long Count; + }; + + protected: + + unsigned long WorkSpace; + Pool *Pools; + unsigned int PoolCount; + + public: + + // Allocation + unsigned long RawAllocate(unsigned long Size); + unsigned long Allocate(unsigned long ItemSize); + unsigned long WriteString(const char *String,unsigned long Len = 0); + inline unsigned long WriteString(string S) {return WriteString(S.begin(),S.size());}; + void UsePools(Pool &P,unsigned int Count) {Pools = &P; PoolCount = Count;}; + + DynamicMMap(File &F,unsigned long Flags,unsigned long WorkSpace = 1024*1024); + virtual ~DynamicMMap(); +}; + +#endif diff --git a/apt-pkg/contrib/system.h b/apt-pkg/contrib/system.h new file mode 100644 index 000000000..e652348b0 --- /dev/null +++ b/apt-pkg/contrib/system.h @@ -0,0 +1,57 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: system.h,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + System Header - Usefull private definitions + + This source is placed in the Public Domain, do with it what you will + It was originally written by Brian C. White. + + ##################################################################### */ + /*}}}*/ +// Private header +// Header section: / +#ifndef SYSTEM_H +#define SYSTEM_H + +// MIN_VAL(SINT16) will return -0x8000 and MAX_VAL(SINT16) = 0x7FFF +#define MIN_VAL(t) (((t)(-1) > 0) ? (t)( 0) : (t)(((1L<<(sizeof(t)*8-1)) ))) +#define MAX_VAL(t) (((t)(-1) > 0) ? (t)(-1) : (t)(((1L<<(sizeof(t)*8-1))-1))) + +// Min/Max functions +#if defined(__HIGHC__) +#define MIN(x,y) _min(x,y) +#define MAX(x,y) _max(x,y) +#endif + +// GNU C++ has a min/max operator <coolio> +#if defined(__GNUG__) +#define MIN(A,B) ((A) <? (B)) +#define MAX(A,B) ((A) >? (B)) +#endif + +/* Templates tend to mess up existing code that uses min/max because of the + strict matching requirements */ +#if !defined(MIN) +#define MIN(A,B) ((A) < (B)?(A):(B)) +#define MAX(A,B) ((A) > (B)?(A):(B)) +#endif + +/* Bound functions, bound will return the value b within the limits a-c + bounv will change b so that it is within the limits of a-c. */ +#define _bound(a,b,c) MIN(c,MAX(b,a)) +#define _boundv(a,b,c) b = _bound(a,b,c) +#define ABS(a) (((a) < (0)) ?-(a) : (a)) + +/* Usefull count macro, use on an array of things and it will return the + number of items in the array */ +#define _count(a) (sizeof(a)/sizeof(a[0])) + +// Flag Macros +#define FLAG(f) (1L << (f)) +#define SETFLAG(v,f) ((v) |= FLAG(f)) +#define CLRFLAG(v,f) ((v) &=~FLAG(f)) +#define CHKFLAG(v,f) ((v) & FLAG(f) ? true : false) + +#endif diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc new file mode 100644 index 000000000..b75fe6d94 --- /dev/null +++ b/apt-pkg/pkgcache.cc @@ -0,0 +1,360 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: pkgcache.cc,v 1.1 1998/07/02 02:58:12 jgg Exp $ +/* ###################################################################### + + Package Cache - Accessor code for the cache + + Please see doc/pkglib/cache.sgml for a more detailed description of + this format. Also be sure to keep that file up-to-date!! + + This is the general utility functions for cache managment. They provide + a complete set of accessor functions for the cache. The cacheiterators + header contains the STL-like iterators that can be used to easially + navigate the cache as well as seemlessly dereference the mmap'd + indexes. Use these always. + + The main class provides for ways to get package indexes and some + general lookup functions to start the iterators. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <pkglib/pkgcache.h> +#include <pkglib/version.h> +#include <pkglib/error.h> +#include <system.h> + +#include <string> +#include <sys/stat.h> +#include <unistd.h> + /*}}}*/ + +// Cache::Header::Header - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* Simply initialize the header */ +pkgCache::Header::Header() +{ + Signature = 0x98FE76DC; + + /* Whenever the structures change the major version should be bumped, + whenever the generator changes the minor version should be bumped. */ + MajorVersion = 2; + MinorVersion = 0; + Dirty = true; + + HeaderSz = sizeof(pkgCache::Header); + PackageSz = sizeof(pkgCache::Package); + PackageFileSz = sizeof(pkgCache::PackageFile); + VersionSz = sizeof(pkgCache::Version); + DependencySz = sizeof(pkgCache::Dependency); + ProvidesSz = sizeof(pkgCache::Provides); + + PackageCount = 0; + VersionCount = 0; + DependsCount = 0; + PackageFileCount = 0; + + FileList = 0; + StringList = 0; + memset(HashTable,0,sizeof(HashTable)); + memset(Pools,0,sizeof(Pools)); +} + /*}}}*/ +// Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgCache::Header::CheckSizes(Header &Against) const +{ + if (HeaderSz == Against.HeaderSz && + PackageSz == Against.PackageSz && + PackageFileSz == Against.PackageFileSz && + VersionSz == Against.VersionSz && + DependencySz == Against.DependencySz && + ProvidesSz == Against.ProvidesSz) + return true; + return false; +} + /*}}}*/ + +// Cache::pkgCache - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgCache::pkgCache(MMap &Map) : Map(Map) +{ + ReMap(); +} + /*}}}*/ +// Cache::ReMap - Reopen the cache file /*{{{*/ +// --------------------------------------------------------------------- +/* If the file is already closed then this will open it open it. */ +bool pkgCache::ReMap() +{ + // Apply the typecasts. + HeaderP = (Header *)Map.Data(); + PkgP = (Package *)Map.Data(); + PkgFileP = (PackageFile *)Map.Data(); + VerP = (Version *)Map.Data(); + ProvideP = (Provides *)Map.Data(); + DepP = (Dependency *)Map.Data(); + StringItemP = (StringItem *)Map.Data(); + StrP = (char *)Map.Data(); + + cout << "Size is " << Map.Size() << endl; + if (Map.Size() == 0) + return false; + + // Check the header + Header DefHeader; + if (HeaderP->Signature != DefHeader.Signature || + HeaderP->Dirty == true) + return _error->Error("The package cache file is corrupted"); + + if (HeaderP->MajorVersion != DefHeader.MajorVersion || + HeaderP->MinorVersion != DefHeader.MinorVersion || + HeaderP->CheckSizes(DefHeader) == false) + return _error->Error("The package cache file is an incompatible version"); + + return true; +} + /*}}}*/ +// Cache::Hash - Hash a string /*{{{*/ +// --------------------------------------------------------------------- +/* This is used to generate the hash entries for the HashTable. With my + package list from bo this function gets 94% table usage on a 512 item + table (480 used items) */ +unsigned long pkgCache::sHash(string Str) +{ + unsigned long Hash = 0; + for (const char *I = Str.begin(); I != Str.end(); I++) + Hash += *I * ((Str.end() - I + 1)); + Header H; + return Hash % _count(H.HashTable); +} + +unsigned long pkgCache::sHash(const char *Str) +{ + unsigned long Hash = 0; + const char *End = Str + strlen(Str); + for (const char *I = Str; I != End; I++) + Hash += *I * ((End - I + 1)); + Header H; + return Hash % _count(H.HashTable); +} + + /*}}}*/ +// Cache::FindPkg - Locate a package by name /*{{{*/ +// --------------------------------------------------------------------- +/* Returns 0 on error, pointer to the package otherwise */ +pkgCache::PkgIterator pkgCache::FindPkg(string Name) +{ + // Look at the hash bucket + Package *Pkg = PkgP + HeaderP->HashTable[Hash(Name)]; + for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage) + { + if (Pkg->Name != 0 && StrP + Pkg->Name == Name) + return PkgIterator(*this,Pkg); + } + return PkgIterator(*this,0); +} + /*}}}*/ + +// Cache::PkgIterator - operator ++ - Postfix incr /*{{{*/ +// --------------------------------------------------------------------- +/* This will advance to the next logical package in the hash table. */ +void pkgCache::PkgIterator::operator ++(int) +{ + // Follow the current links + if (Pkg != Owner->PkgP) + Pkg = Owner->PkgP + Pkg->NextPackage; + + // Follow the hash table + while (Pkg == Owner->PkgP && HashIndex < (signed)_count(Owner->HeaderP->HashTable)) + { + HashIndex++; + Pkg = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex]; + } +}; + /*}}}*/ +// Bases for iterator classes /*{{{*/ +void pkgCache::VerIterator::_dummy() {} +void pkgCache::DepIterator::_dummy() {} +void pkgCache::PrvIterator::_dummy() {} + /*}}}*/ +// PkgIterator::State - Check the State of the package /*{{{*/ +// --------------------------------------------------------------------- +/* By this we mean if it is either cleanly installed or cleanly removed. */ +pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const +{ + if (Pkg->CurrentState == pkgSTATE_UnPacked || + Pkg->CurrentState == pkgSTATE_HalfConfigured) + return NeedsConfigure; + + if (Pkg->CurrentState == pkgSTATE_UnInstalled || + Pkg->CurrentState == pkgSTATE_HalfInstalled || + Pkg->InstState != pkgSTATE_Ok) + return NeedsUnpack; + + return NeedsNothing; +} + /*}}}*/ +// DepIterator::IsCritical - Returns true if the dep is important /*{{{*/ +// --------------------------------------------------------------------- +/* Currently critical deps are defined as depends, predepends and + conflicts. */ +bool pkgCache::DepIterator::IsCritical() +{ + if (Dep->Type == pkgDEP_Conflicts || Dep->Type == pkgDEP_Depends || + Dep->Type == pkgDEP_PreDepends) + return true; + return false; +} + /*}}}*/ +// DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/ +// --------------------------------------------------------------------- +/* This intellegently looks at dep target packages and tries to figure + out which package should be used. This is needed to nicely handle + provide mapping. If the target package has no other providing packages + then it returned. Otherwise the providing list is looked at to + see if there is one one unique providing package if so it is returned. + Otherwise true is returned and the target package is set. The return + result indicates whether the node should be expandable */ +bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) +{ + Result = TargetPkg(); + + // No provides at all + if (Result->ProvidesList == 0) + return false; + + // There is the Base package and the providing ones which is at least 2 + if (Result->VersionList != 0) + return true; + + /* We have to skip over indirect provisions of the package that + owns the dependency. For instance, if libc5-dev depends on the + virtual package libc-dev which is provided by libc5-dev and libc6-dev + we must ignore libc5-dev when considering the provides list. */ + PrvIterator PStart = Result.ProvidesList(); + for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); PStart++); + + // Nothing but indirect self provides + if (PStart.end() == true) + return false; + + // Check for single packages in the provides list + PrvIterator P = PStart; + for (; P.end() != true; P++) + { + // Skip over self provides + if (P.OwnerPkg() == ParentPkg()) + continue; + if (PStart.OwnerPkg() != P.OwnerPkg()) + break; + } + + // Check for non dups + if (P.end() != true) + return true; + Result = PStart.OwnerPkg(); + return false; +} + /*}}}*/ +// DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/ +// --------------------------------------------------------------------- +/* This is a more usefull version of TargetPkg() that follows versioned + provides. It includes every possible package-version that could satisfy + the dependency. The last item in the list has a 0. */ +pkgCache::Version **pkgCache::DepIterator::AllTargets() +{ + Version **Res = 0; + unsigned long Size =0; + while (1) + { + Version **End = Res; + PkgIterator DPkg = TargetPkg(); + + // Walk along the actual package providing versions + for (VerIterator I = DPkg.VersionList(); I.end() == false; I++) + { + if (pkgCheckDep(TargetVer(),I.VerStr(),Dep->CompareOp) == false) + continue; + + if (Dep->Type == pkgDEP_Conflicts && ParentPkg() == I.ParentPkg()) + continue; + + Size++; + if (Res != 0) + *End++ = I; + } + + // Follow all provides + for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++) + { + if (pkgCheckDep(TargetVer(),I.ProvideVersion(),Dep->CompareOp) == false) + continue; + + if (Dep->Type == pkgDEP_Conflicts && ParentPkg() == I.OwnerPkg()) + continue; + + Size++; + if (Res != 0) + *End++ = I.OwnerVer(); + } + + // Do it again and write it into the array + if (Res == 0) + { + Res = new Version *[Size+1]; + Size = 0; + } + else + { + *End = 0; + break; + } + } + + return Res; +} + /*}}}*/ +// VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/ +// --------------------------------------------------------------------- +/* This just looks over the version list to see if B is listed before A. In + most cases this will return in under 4 checks, ver lists are short. */ +int pkgCache::VerIterator::CompareVer(const VerIterator &B) const +{ + // Check if they are equal + if (*this == B) + return 0; + if (end() == true) + return -1; + if (B.end() == true) + return 1; + + /* Start at A and look for B. If B is found then A > B otherwise + B was before A so A < B */ + VerIterator I = *this; + for (;I.end() == false; I++) + if (I == B) + return 1; + return -1; +} + /*}}}*/ +// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/ +// --------------------------------------------------------------------- +/* This stats the file and compares its stats with the ones that were + stored during generation. Date checks should probably also be + included here. */ +bool pkgCache::PkgFileIterator::IsOk() +{ + struct stat Buf; + if (stat(FileName(),&Buf) != 0) + return false; + + if (Buf.st_size != (signed)File->Size || Buf.st_mtime != File->mtime) + return false; + + return true; +} + /*}}}*/ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h new file mode 100644 index 000000000..0dc939a51 --- /dev/null +++ b/apt-pkg/pkgcache.h @@ -0,0 +1,280 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: pkgcache.h,v 1.1 1998/07/02 02:58:12 jgg Exp $ +/* ###################################################################### + + Cache - Structure definitions for the cache file + + Please see doc/pkglib/cache.sgml for a more detailed description of + this format. Also be sure to keep that file up-to-date!! + + Clients should always use the CacheIterators classes for access to the + cache. They provide a simple STL-like method for traversing the links + of the datastructure. + + See pkgcachegen.h for information about generating cache structures. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_PKGCACHE_H +#define PKGLIB_PKGCACHE_H + +#include <string> +#include <time.h> +#include <pkglib/mmap.h> + +// Definitions for Depends::Type +#define pkgDEP_Depends 1 +#define pkgDEP_PreDepends 2 +#define pkgDEP_Suggests 3 +#define pkgDEP_Recommends 4 +#define pkgDEP_Conflicts 5 +#define pkgDEP_Replaces 6 + +// Definitions for Version::Priority +#define pkgPRIO_Important 1 +#define pkgPRIO_Required 2 +#define pkgPRIO_Standard 3 +#define pkgPRIO_Optional 4 +#define pkgPRIO_Extra 5 + +// Definitions for Package::SelectedState +#define pkgSTATE_Unkown 0 +#define pkgSTATE_Install 1 +#define pkgSTATE_Hold 2 +#define pkgSTATE_DeInstall 3 +#define pkgSTATE_Purge 4 + +// Definitions for Package::Flags +#define pkgFLAG_Auto (1 << 0) +#define pkgFLAG_New (1 << 1) +#define pkgFLAG_Obsolete (1 << 2) +#define pkgFLAG_Essential (1 << 3) +#define pkgFLAG_ImmediateConf (1 << 4) + +// Definitions for Package::InstState +#define pkgSTATE_Ok 0 +#define pkgSTATE_ReInstReq 1 +#define pkgSTATE_Hold 2 +#define pkgSTATE_HoldReInstReq 3 + +// Definitions for Package::CurrentState +#define pkgSTATE_NotInstalled 0 +#define pkgSTATE_UnPacked 1 +#define pkgSTATE_HalfConfigured 2 +#define pkgSTATE_UnInstalled 3 +#define pkgSTATE_HalfInstalled 4 +#define pkgSTATE_ConfigFiles 5 +#define pkgSTATE_Installed 6 + +// Definitions for PackageFile::Flags +#define pkgFLAG_NotSource (1 << 0) + +// Definitions for Dependency::CompareOp +#define pkgOP_OR 0x10 +#define pkgOP_LESSEQ 0x1 +#define pkgOP_GREATEREQ 0x2 +#define pkgOP_LESS 0x3 +#define pkgOP_GREATER 0x4 +#define pkgOP_EQUALS 0x5 +#define pkgOP_NOTEQUALS 0x6 + +class pkgCache +{ + public: + // Cache element predeclarations + struct Header; + struct Package; + struct PackageFile; + struct Version; + struct Provides; + struct Dependency; + struct StringItem; + + // Iterators + class PkgIterator; + class VerIterator; + class DepIterator; + class PrvIterator; + class PkgFileIterator; + friend PkgIterator; + friend VerIterator; + friend DepIterator; + friend PrvIterator; + friend PkgFileIterator; + + protected: + + // Memory mapped cache file + string CacheFile; + MMap ⤅ + + bool Public; + bool ReadOnly; + + static unsigned long sHash(string S); + static unsigned long sHash(const char *S); + + public: + + // Pointers to the arrays of items + Header *HeaderP; + Package *PkgP; + PackageFile *PkgFileP; + Version *VerP; + Provides *ProvideP; + Dependency *DepP; + StringItem *StringItemP; + char *StrP; + + virtual bool ReMap(); + inline bool Sync() {return Map.Sync();}; + + // String hashing function (512 range) + inline unsigned long Hash(string S) const {return sHash(S);}; + inline unsigned long Hash(const char *S) const {return sHash(S);}; + + // Accessors + PkgIterator FindPkg(string Name); + Header &Head() {return *HeaderP;}; + inline PkgIterator PkgBegin(); + inline PkgIterator PkgEnd(); + + pkgCache(MMap &Map); + virtual ~pkgCache() {}; +}; + +// Header structure +struct pkgCache::Header +{ + // Signature information + unsigned long Signature; + short MajorVersion; + short MinorVersion; + bool Dirty; + + // Size of structure values + unsigned short HeaderSz; + unsigned short PackageSz; + unsigned short PackageFileSz; + unsigned short VersionSz; + unsigned short DependencySz; + unsigned short ProvidesSz; + + // Structure counts + unsigned long PackageCount; + unsigned long VersionCount; + unsigned long DependsCount; + unsigned long PackageFileCount; + + // Offsets + unsigned long FileList; // struct PackageFile + unsigned long StringList; // struct StringItem + + /* Allocation pools, there should be one of these for each structure + excluding the header */ + DynamicMMap::Pool Pools[6]; + + // Rapid package name lookup + unsigned long HashTable[512]; + + bool CheckSizes(Header &Against) const; + Header(); +}; + +struct pkgCache::Package +{ + // Pointers + unsigned long Name; // Stringtable + unsigned long VersionList; // Version + unsigned long TargetVer; // Version + unsigned long CurrentVer; // Version + unsigned long TargetDist; // StringTable (StringItem) + unsigned long Section; // StringTable (StringItem) + + // Linked list + unsigned long NextPackage; // Package + unsigned long RevDepends; // Dependency + unsigned long ProvidesList; // Provides + + // Install/Remove/Purge etc + unsigned char SelectedState; // What + unsigned char InstState; // Flags + unsigned char CurrentState; // State + + unsigned short ID; + unsigned short Flags; +}; + +struct pkgCache::PackageFile +{ + // Names + unsigned long FileName; // Stringtable + unsigned long Version; // Stringtable + unsigned long Distribution; // Stringtable + unsigned long Size; + + // Linked list + unsigned long NextFile; // PackageFile + unsigned short ID; + unsigned short Flags; + time_t mtime; // Modification time for the file +}; + +struct pkgCache::Version +{ + unsigned long VerStr; // Stringtable + unsigned long File; // PackageFile + unsigned long Section; // StringTable (StringItem) + + // Lists + unsigned long NextVer; // Version + unsigned long DependsList; // Dependency + unsigned long ParentPkg; // Package + unsigned long ProvidesList; // Provides + + unsigned long Offset; + unsigned long Size; + unsigned long InstalledSize; + unsigned short ID; + unsigned char Priority; +}; + +struct pkgCache::Dependency +{ + unsigned long Version; // Stringtable + unsigned long Package; // Package + unsigned long NextDepends; // Dependency + unsigned long NextRevDepends; // Dependency + unsigned long ParentVer; // Version + + // Specific types of depends + unsigned char Type; + unsigned char CompareOp; + unsigned short ID; +}; + +struct pkgCache::Provides +{ + unsigned long ParentPkg; // Pacakge + unsigned long Version; // Version + unsigned long ProvideVersion; // Stringtable + unsigned long NextProvides; // Provides + unsigned long NextPkgProv; // Provides +}; + +struct pkgCache::StringItem +{ + unsigned long String; // Stringtable + unsigned long NextItem; // StringItem +}; + +#include <pkglib/cacheiterators.h> + +inline pkgCache::PkgIterator pkgCache::PkgBegin() + {return PkgIterator(*this);}; +inline pkgCache::PkgIterator pkgCache::PkgEnd() + {return PkgIterator(*this,PkgP);}; + +#endif diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc new file mode 100644 index 000000000..cb0fd3f74 --- /dev/null +++ b/apt-pkg/pkgcachegen.cc @@ -0,0 +1,184 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: pkgcachegen.cc,v 1.1 1998/07/02 02:58:12 jgg Exp $ +/* ###################################################################### + + Package Cache Generator - Generator for the cache structure. + + This builds the cache structure from the abstract package list parser. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <pkglib/pkgcachegen.h> +#include <pkglib/error.h> +#include <pkglib/version.h> + +#include <sys/stat.h> +#include <unistd.h> + /*}}}*/ + +// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* We set the diry flag and make sure that is written to the disk */ +pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map) : Map(Map), Cache(Map) +{ + if (_error->PendingError() == true) + return; + + if (Map.Size() == 0) + { + Map.RawAllocate(sizeof(pkgCache::Header)); + *Cache.HeaderP = pkgCache::Header(); + } + Cache.HeaderP->Dirty = true; + Map.Sync(0,sizeof(pkgCache::Header)); + Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0])); +} + /*}}}*/ +// CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/ +// --------------------------------------------------------------------- +/* We sync the data then unset the dirty flag in two steps so as to + advoid a problem during a crash */ +pkgCacheGenerator::~pkgCacheGenerator() +{ + if (_error->PendingError() == true) + return; + if (Map.Sync() == false) + return; + + Cache.HeaderP->Dirty = false; + Map.Sync(0,sizeof(pkgCache::Header)); +} + /*}}}*/ +// CacheGenerator::MergeList - Merge the package list /*{{{*/ +// --------------------------------------------------------------------- +/* This provides the generation of the entries in the cache. Each loop + goes through a single package record from the underlying parse engine. */ +bool pkgCacheGenerator::MergeList(ListParser &List) +{ + List.Owner = this; + + do + { + // Get a pointer to the package structure + string Package = List.Package(); + pkgCache::PkgIterator Pkg = Cache.FindPkg(Package); + if (Pkg.end() == false) + { + if (NewPackage(Pkg,Package) == false) + return false; + + if (List.NewPackage(Pkg) == false) + return false; + } + if (List.UsePackage(Pkg) == false) + return false; + + /* Get a pointer to the version structure. We know the list is sorted + so we use that fact in the search. Insertion of new versions is + done with correct sorting */ + string Version = List.Version(); + pkgCache::VerIterator Ver = Pkg.VersionList(); + unsigned long *Last = &Pkg->VersionList; + int Res; + for (; Ver.end() == false; Ver++, Last = &Ver->NextVer) + { + Res = pkgVersionCompare(Version.begin(),Version.end(),Ver.VerStr(), + Ver.VerStr() + strlen(Ver.VerStr())); + if (Res >= 0) + break; + } + + /* We already have a version for this item, record that we + saw it */ + if (Res == 0) + { + if (NewFileVer(Ver,List) == false) + return false; + + continue; + } + + // Add a new version + *Last = NewVersion(Ver,*Last); + if (List.NewVersion(Ver) == false) + return false; + + if (NewFileVer(Ver,List) == false) + return false; + } + while (List.Step() == true); + + return true; +} + /*}}}*/ +// CacheGenerator::NewPackage - Add a new package /*{{{*/ +// --------------------------------------------------------------------- +/* This creates a new package structure and adds it to the hash table */ +bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator Pkg,string Name) +{ + // Get a structure + unsigned long Package = Map.Allocate(sizeof(pkgCache::Package)); + if (Package == 0) + return false; + + Pkg = pkgCache::PkgIterator(Cache,Cache.PackageP + Package); + + // Insert it into the hash table + unsigned long Hash = Map.Hash(Name); + Pkg->NextPackage = Cache.HeaderP->HashTable[Hash]; + Cache.HeaderP->HashTable[Hash] = Package; + + // Set the name and the ID + Pkg->Name = Map.WriteString(Name); + if (Pkg->Name == 0) + return false; + Pkg->ID = Cache.HeaderP->PackageCount++; + + return true; +} + /*}}}*/ +// CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator Ver, + ListParser &List) +{ +} + /*}}}*/ +// CacheGenerator::NewVersion - Create a new Version /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, + unsigned long Next) +{ +} + /*}}}*/ +// CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/ +// --------------------------------------------------------------------- +/* This is used to select which file is to be associated with all newly + added versions. */ +bool pkgCacheGenerator::SelectFile(string File,unsigned long Flags) +{ + struct stat Buf; + if (stat(File.c_str(),&Buf) == -1) + return _error->Errno("stat","Couldn't stat ",File.c_str()); + + // Get some space for the structure + CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile)); + if (CurrentFile == Cache.PkgFileP) + return false; + + // Fill it in + CurrentFile->FileName = Map.WriteString(File); + CurrentFile->Size = Buf.st_size; + CurrentFile->mtime = Buf.st_mtime; + CurrentFile->NextFile = Cache.HeaderP->FileList; + CurrentFile->Flags = Flags; + PkgFileName = File; + + if (CurrentFile->FileName == 0) + return false; +} + /*}}}*/ diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h new file mode 100644 index 000000000..1385ab964 --- /dev/null +++ b/apt-pkg/pkgcachegen.h @@ -0,0 +1,69 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: pkgcachegen.h,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + Package Cache Generator - Generator for the cache structure. + + This builds the cache structure from the abstract package list parser. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_PKGCACHEGEN_H +#define PKGLIB_PKGCACHEGEN_H + +#include <pkglib/pkgcache.h> + +class pkgCacheGenerator +{ + public: + + class ListParser; + + protected: + + DynamicMMap ⤅ + pkgCache Cache; + + string PkgFileName; + pkgCache::PackageFile *CurrentFile; + + bool NewPackage(pkgCache::PkgIterator Pkg,string Pkg); + bool NewFileVer(pkgCache::VerIterator Ver,ListParser &List); + unsigned long NewVersion(pkgCache::VerIterator &Ver,unsigned long Next); + + public: + + // This is the abstract package list parser class. + class ListParser + { + pkgCacheGenerator *Owner; + friend pkgCacheGenerator; + + protected: + + inline unsigned long WriteString(string S) {return Owner->Map.WriteString(S);}; + inline unsigned long WriteString(const char *S,unsigned int Size) {return Owner->Map.WriteString(S,Size);}; + + public: + + // These all operate against the current section + virtual string Package() = 0; + virtual string Version() = 0; + virtual bool NewVersion(pkgCache::VerIterator Ver) = 0; + virtual bool NewPackage(pkgCache::PkgIterator Pkg) = 0; + virtual bool UsePackage(pkgCache::PkgIterator Pkg) = 0; + + virtual bool Step() = 0; + }; + friend ListParser; + + bool SelectFile(string File,unsigned long Flags = 0); + bool MergeList(ListParser &List); + + pkgCacheGenerator(DynamicMMap &Map); + ~pkgCacheGenerator(); +}; + +#endif diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc new file mode 100644 index 000000000..106b0febe --- /dev/null +++ b/apt-pkg/tagfile.cc @@ -0,0 +1,195 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: tagfile.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + Fast scanner for RFC-822 type header information + + This uses a rotating 64K buffer to load the package information into. + The scanner runs over it and isolates and indexes a single section. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <pkglib/tagfile.h> +#include <pkglib/error.h> + +#include <string> +#include <stdio.h> + /*}}}*/ + +// TagFile::pkgTagFile - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgTagFile::pkgTagFile(File &Fd) : Fd(Fd) +{ + Buffer = new char[64*1024]; + Start = End = Buffer + 64*1024; + Left = Fd.Size(); + Fill(); +} + /*}}}*/ +// TagFile::Step - Advance to the next section /*{{{*/ +// --------------------------------------------------------------------- +/* If the Section Scanner fails we refill the buffer and try again. */ +bool pkgTagFile::Step(pkgTagSection &Tag) +{ + if (Tag.Scan(Start,End - Start) == false) + { + if (Fill() == false) + return false; + + if (Tag.Scan(Start,End - Start) == false) + return _error->Error("Unable to parse package file"); + } + Start += Tag.Length(); + return true; +} + /*}}}*/ +// TagFile::Fill - Top up the buffer /*{{{*/ +// --------------------------------------------------------------------- +/* This takes the bit at the end of the buffer and puts it at the start + then fills the rest from the file */ +bool pkgTagFile::Fill() +{ + unsigned long Size = End - Start; + + if (Left == 0) + { + if (Size <= 1) + return false; + return true; + } + + memmove(Buffer,Start,Size); + Start = Buffer; + + // See if only a bit of the file is left or if + if (Left < End - Buffer - Size) + { + if (Fd.Read(Buffer + Size,Left) == false) + return false; + End = Buffer + Size + Left; + Left = 0; + } + else + { + if (Fd.Read(Buffer + Size, End - Buffer - Size) == false) + return false; + Left -= End - Buffer - Size; + } + return true; +} + /*}}}*/ +// TagSection::Scan - Scan for the end of the header information /*{{{*/ +// --------------------------------------------------------------------- +/* This looks for the first double new line in the data stream. It also + indexes the tags in the section. */ +bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength) +{ + const char *End = Start + MaxLength; + Stop = Section = Start; + + TagCount = 0; + Indexes[TagCount++] = Stop - Section; + Stop++; + for (; Stop < End; Stop++) + { + if (Stop[-1] != '\n') + continue; + if (Stop[0] == '\n') + { + // Extra one at the end to simplify find + Indexes[TagCount] = Stop - Section; + for (; Stop[0] == '\n' && Stop < End; Stop++); + return true; + break; + } + + if (isspace(Stop[0]) == 0) + Indexes[TagCount++] = Stop - Section; + + // Just in case. + if (TagCount > sizeof(Indexes)/sizeof(Indexes[0])) + TagCount = sizeof(Indexes)/sizeof(Indexes[0]); + } + return false; +} + /*}}}*/ +// TagSection::Find - Locate a tag /*{{{*/ +// --------------------------------------------------------------------- +/* This searches the section for a tag that matches the given string. */ +bool pkgTagSection::Find(const char *Tag,const char *&Start, + const char *&End) +{ + unsigned int Length = strlen(Tag); + for (unsigned int I = 0; I != TagCount; I++) + { + if (strncasecmp(Tag,Section + Indexes[I],Length) != 0) + continue; + + // Make sure the colon is in the right place + const char *C = Section + Length + Indexes[I]; + for (; isspace(*C) != 0; C++); + if (*C != ':') + continue; + + // Strip off the gunk from the start end + Start = C; + End = Section + Indexes[I+1]; + for (; (isspace(*Start) != 0 || *Start == ':') && Start < End; Start++); + for (; isspace(End[-1]) != 0 && End > Start; End--); + return true; + } + Start = End = 0; + return false; +} + /*}}}*/ + +#include <pkglib/pkgcachegen.h> + +int main(int argc,char *argv[]) +{ + { + File F(argv[1],File::ReadOnly); + pkgTagFile Test(F); + File CacheF("./cache",File::WriteEmpty); + DynamicMMap Map(CacheF,MMap::Public); + pkgCacheGenerator Gen(Map); + Gen.SelectFile("tet"); + } + +#if 0 + pkgTagSection I; + while (Test.Step(I) == true) + { + const char *Start; + const char *End; + if (I.Find("Package",Start,End) == false) + { + cout << "Failed" << endl; + continue; + } + + cout << "Package: " << string(Start,End - Start) << endl; + +/* for (const char *I = Start; I < End; I++) + { + const char *Begin = I; + bool Number = true; + while (isspace(*I) == 0 && ispunct(*I) == 0 && I < End) + { + if (isalpha(*I) != 0) + Number = false; + I++; + } + if (Number == false) + cout << string(Begin,I-Begin) << endl; + while ((isspace(*I) != 0 || ispunct(*I) != 0) && I < End) + I++; + I--; + } */ + } +#endif + _error->DumpErrors(); +} diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h new file mode 100644 index 000000000..a7a82dd1c --- /dev/null +++ b/apt-pkg/tagfile.h @@ -0,0 +1,64 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: tagfile.h,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + Fast scanner for RFC-822 type header information + + This parser handles Debian package files (and others). Their form is + RFC-822 type header fields in groups seperated by a blank line. + + The parser reads the and provides methods to step linearly + over it or to jump to a pre-recorded start point and read that record. + + A second class is used to perform pre-parsing of the record. It works + by indexing the start of each header field and providing lookup + functions for header fields. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_TAGFILE_H +#define PKGLIB_TAGFILE_H + +#include <pkglib/fileutl.h> + +class pkgTagSection +{ + const char *Section; + const char *Stop; + + // We have a limit of 256 tags per section. + unsigned short Indexes[256]; + unsigned int TagCount; + + public: + + inline bool operator ==(const pkgTagSection &rhs) {return Section == rhs.Section;}; + inline bool operator !=(const pkgTagSection &rhs) {return Section != rhs.Section;}; + + bool Find(const char *Tag,const char *&Start, const char *&End); + bool Scan(const char *Start,unsigned long MaxLength); + inline unsigned long Length() {return Stop - Section;}; + + pkgTagSection() : Section(0), Stop(0) {}; +}; + +class pkgTagFile +{ + File Fd; + char *Buffer; + char *Start; + char *End; + unsigned long Left; + + bool Fill(); + + public: + + bool Step(pkgTagSection &Section); + + pkgTagFile(File &F); +}; + +#endif diff --git a/apt-pkg/version.cc b/apt-pkg/version.cc new file mode 100644 index 000000000..c02ee5f87 --- /dev/null +++ b/apt-pkg/version.cc @@ -0,0 +1,249 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: version.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + Version - Version string + + Version comparing is done using the == and < operators. STL's + function.h provides the remaining set of comparitors. A directly + callable non-string class version is provided for functions manipulating + the cache file (esp the sort function). + + A version is defined to be equal if a case sensitive compare returns + that the two strings are the same. For compatibility with the QSort + function this version returns -1,0,1. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <pkglib/version.h> +#include <pkglib/pkgcache.h> + +#include <stdlib.h> + /*}}}*/ + +// Version::pkgVersion - Default Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgVersion::pkgVersion() +{ +} + /*}}}*/ +// Version::operator == - Checks if two versions are equal /*{{{*/ +// --------------------------------------------------------------------- +/* We can't simply perform a string compare because of epochs. */ +bool pkgVersion::operator ==(const pkgVersion &Vrhs) const +{ + if (pkgVersionCompare(Value.begin(),Value.end(), + Vrhs.Value.begin(),Vrhs.Value.end()) == 0) + return true; + return false; +} + /*}}}*/ +// Version::operator < - Checks if this is less than another version /*{{{*/ +// --------------------------------------------------------------------- +/* All other forms of comparision can be built up from this single function. + a > b -> b < a + a <= b -> !(a > b) -> !(b < a) + a >= b -> !(a < b) + */ +bool pkgVersion::operator <(const pkgVersion &Vrhs) const +{ + if (pkgVersionCompare(Value.begin(),Value.end(), + Vrhs.Value.begin(),Vrhs.Value.end()) == -1) + return true; + return false; +} + /*}}}*/ +// StrToLong - Convert the string between two iterators to a long /*{{{*/ +// --------------------------------------------------------------------- +/* */ +static unsigned long StrToLong(const char *begin,const char *end) +{ + char S[40]; + char *I = S; + for (; begin != end && I < S + 40;) + *I++ = *begin++; + *I = 0; + return strtoul(S,0,10); +} + /*}}}*/ +// VersionCompare (op) - Greater than comparison for versions /*{{{*/ +// --------------------------------------------------------------------- +/* */ +int pkgVersionCompare(const char *A, const char *B) +{ + return pkgVersionCompare(A,A + strlen(A),B,B + strlen(B)); +} +int pkgVersionCompare(string A,string B) +{ + return pkgVersionCompare(A.begin(),A.end(),B.begin(),B.end()); +} + + /*}}}*/ +// VersionCompare - Greater than comparison for versions /*{{{*/ +// --------------------------------------------------------------------- +/* */ +int pkgVersionCompare(const char *A, const char *AEnd, const char *B, + const char *BEnd) +{ + // lhs = left hand side, rhs = right hand side + const char *lhs = A; + const char *rhs = B; + + /* Consider epochs. They need special handling because an epoch + must not be compared against the first element of the real version. + This works okay when both sides have an epoch but when only one + does it must compare the missing epoch to 0 */ + for (;lhs != AEnd && *lhs != ':'; lhs++); + for (;rhs != BEnd && *rhs != ':'; rhs++); + + // Parse the epoch out + unsigned long lhsEpoch = 0; + unsigned long rhsEpoch = 0; + if (lhs != AEnd && *lhs == ':') + lhsEpoch = StrToLong(A,lhs); + if (rhs != BEnd && *rhs == ':') + rhsEpoch = StrToLong(B,rhs); + if (lhsEpoch != rhsEpoch) + { + if (lhsEpoch > rhsEpoch) + return 1; + return -1; + } + + /* Iterate over the whole string + What this does is to spilt the whole string into groups of + numeric and non numeric portions. For instance: + a67bhgs89 + Has 4 portions 'a', '67', 'bhgs', '89'. A more normal: + 2.7.2-linux-1 + Has '2', '.', '7', '.' ,'-linux-','1' */ + lhs = A; + rhs = B; + while (lhs != AEnd && rhs != BEnd) + { + // Starting points + const char *Slhs = lhs; + const char *Srhs = rhs; + + // Compute ending points were we have passed over the portion + bool Digit = (isdigit(*lhs) > 0?true:false); + for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++); + for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++); + + if (Digit == true) + { + // If the lhs has a digit and the rhs does not then true + if (rhs - Srhs == 0) + return -1; + + // Generate integers from the strings. + unsigned long Ilhs = StrToLong(Slhs,lhs); + unsigned long Irhs = StrToLong(Srhs,rhs); + if (Ilhs != Irhs) + { + if (Ilhs > Irhs) + return 1; + return -1; + } + } + else + { + // They are equal length so do a straight text compare + for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++) + { + if (*Slhs != *Srhs) + { + /* We need to compare non alpha chars as higher than alpha + chars (a < !) This is so things like 7.6p2-4 and 7.6-0 + compare higher as well as . and -. I am not sure how + the dpkg code manages to achive the != '-' test, but it + is necessary. */ + int lc = *Slhs; + int rc = *Srhs; + if (isalpha(lc) == 0 && lc != '-') lc += 256; + if (isalpha(rc) == 0 && rc != '-') rc += 256; + if (lc > rc) + return 1; + return -1; + } + } + + // If the lhs is shorter than the right it is 'less' + if (lhs - Slhs < rhs - Srhs) + return -1; + + // If the lhs is longer than the right it is 'more' + if (lhs - Slhs > rhs - Srhs) + return 1; + } + } + + // The strings must be equal + if (lhs == AEnd && rhs == BEnd) + return 0; + + // lhs is shorter + if (lhs == AEnd) + return -1; + + // rhs is shorter + if (rhs == BEnd) + return 1; + + // Shouldnt happen + return 1; +} + /*}}}*/ +// CheckDep - Check a single dependency /*{{{*/ +// --------------------------------------------------------------------- +/* This simply preforms the version comparison and switch based on + operator. */ +bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op) +{ + if (DepVer == 0) + return true; + if (PkgVer == 0) + return false; + + // Perform the actuall comparision. + int Res = pkgVersionCompare(PkgVer,DepVer); + switch (Op & 0x0F) + { + case pkgOP_LESSEQ: + if (Res <= 0) + return true; + break; + + case pkgOP_GREATEREQ: + if (Res >= 0) + return true; + break; + + case pkgOP_LESS: + if (Res < 0) + return true; + break; + + case pkgOP_GREATER: + if (Res > 0) + return true; + break; + + case pkgOP_EQUALS: + if (Res == 0) + return true; + break; + + case pkgOP_NOTEQUALS: + if (Res != 0) + return true; + break; + } + + return false; +} + /*}}}*/ + diff --git a/apt-pkg/version.h b/apt-pkg/version.h new file mode 100644 index 000000000..a30246946 --- /dev/null +++ b/apt-pkg/version.h @@ -0,0 +1,45 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: version.h,v 1.1 1998/07/02 02:58:13 jgg Exp $ +/* ###################################################################### + + Version - Version string + + This class implements storage and operators for version strings. + + The client is responsible for stripping epochs should it be desired. + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_VERSION_H +#define PKGLIB_VERSION_H + +#include <string> + +class pkgVersion +{ + string Value; + + public: + + inline operator string () const {return Value;}; + + // Assignmnet + void operator =(string rhs) {Value = rhs;}; + + // Comparitors. STL will provide the rest + bool operator ==(const pkgVersion &rhs) const; + bool operator <(const pkgVersion &rhs) const; + + pkgVersion(); + pkgVersion(string Version) : Value(Version) {}; +}; + +int pkgVersionCompare(const char *A, const char *B); +int pkgVersionCompare(const char *A, const char *AEnd, const char *B, + const char *BEnd); +int pkgVersionCompare(string A,string B); +bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op); + +#endif diff --git a/doc/apt-cache.8 b/doc/apt-cache.8 new file mode 100644 index 000000000..0292973ed --- /dev/null +++ b/doc/apt-cache.8 @@ -0,0 +1,199 @@ +.\" This manpage is copyright (C) 1998 Branden Robinson <branden@debian.org>.
+.\"
+.\" This is free software; you may redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2,
+.\" or (at your option) any later version.
+.\"
+.\" This is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public
+.\" License along with APT; if not, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+.\" 02111-1307 USA
+.TH apt-cache 8 "16 June 1998" "Debian GNU/Linux"
+.SH NAME
+apt-cache \- APT package handling utility \(em cache manipulator
+.SH SYNOPSIS
+.B apt-cache
+.I command cache
+.RI [ argument
+.IR ... ]
+.SH DESCRIPTION
+.B apt-cache
+performs a variety of operations on APT's package cache.
+.I apt-cache
+is seldom called directly; instead it is usually invoked internally by
+.BR apt-get (8)
+or
+.BR apt (8).
+.PP
+.I command
+is one of
+.RS
+.PD 0
+.B add
+.PP
+.B dump
+.PP
+.B dumpavail
+.PP
+.B showpkg
+.PP
+.B stats
+.RE
+.PD 1
+.PP
+.I cache
+must be a package cache file (for instance,
+.IR /var/cache/apt/pkgcache.bin ).
+Some
+.IR command s
+require additional arguments.
+.SS add
+.B add
+adds a new set of package records to
+.IR cache .
+Remaining arguments are of the form
+.IR file : dist : ver ,
+where
+.I file
+is the full path to file in question.
+.I dist
+and
+.I ver
+can be any string and are not yet implemented.
+.SS dump
+.B dump
+displays information about all the packages in the cache. See
+.B showpkg
+below for an explanation of what data is output for each package.
+.SS dumpavail
+.B dumpavail
+generates an
+.I available
+file suitable for use with
+.BR dpkg (8)
+based on the information in the cache.
+.SS showpkg
+.B showpkg
+displays information about the packages listed on the command line.
+Remaining arguments are package names. The available versions and
+reverse dependencies of each package listed are listed, as well as
+forward dependencies for each version. Forward (normal) dependencies
+are those packages upon which the package in question depends; reverse
+dependencies are those packages that depend upon the package in
+question. Thus, forward dependencies must be satisfied for a package,
+but reverse dependencies need not be.
+For instance,
+.B apt-cache showpkg
+.I cache
+.B libreadline2
+would produce output similar to the following:
+.PP
+.RS
+.PD 0
+Package: libreadline2
+.PP
+Versions: 2.1-8,2.1-7,
+.PP
+Reverse Depends:
+.RS
+.PP
+libreadlineg2,libreadline2
+.PP
+libreadlineg2,libreadline2
+.PP
+libreadline2-altdev,libreadline2
+.RE
+.PP
+Dependencies:
+.PP
+2.1-8 - libc5 ncurses3.0 ldso
+.PP
+2.1-7 - ldso libc5 ncurses3.0
+.RE
+.PD 1
+.PP
+Thus it may be seen that libreadline2, version 2.1-8, depends on libc5,
+ncurses3.0, and ldso, which must be installed for libreadline2 to work. In
+turn, libreadlineg2 and libreadline2-altdev depend on libreadline2. If
+libreadline2 is installed, libc5, ncurses3.0, and ldso must also be
+installed; libreadlineg2 and libreadline2-altdev do not have to be
+installed.
+.SS stats
+.B stats
+displays some statistics about
+.IR cache .
+No further arguments are expected. Statistics reported are:
+.RS
+.TP
+.I Total package names
+is the number of package names found in the cache.
+.TP
+.I Normal packages
+is the number of regular, ordinary package names; these
+are packages that bear a one-to-one correspondence between their names and
+the names used by other packages for them in dependencies. The majority of
+packages fall into this category.
+.TP
+.I Pure virtual packages
+is the number of packages that exist only as a virtual package name; that
+is, packages only "provide" the virtual package name, and no package
+actually uses the name. For instance, "mail-transport-agent" in the Debian
+GNU/Linux system is a pure virtual package; several packages provide
+"mail-transport-agent", but there is no package named "mail-transport-agent".
+.TP
+.I Single virtual packages
+is the number of packages with only one package providing a particular
+virtual package. For instance, in the Debian GNU/Linux system,
+"X11-text-viewer" is a virtual package, but only one package, xless,
+provides "X11-text-viewer".
+.TP
+.I Mixed virtual packages
+is the number of packages that either provide a particular virtual package
+or have the virtual package name as the package name. For instance, in the
+Debian GNU/Linux system, e2fsprogs is both an actual package, and
+provided by the e2compr package.
+.TP
+.I Missing
+is the number of package names that were referenced in a dependency but
+were not provided by any package. Missing packages may be in evidence
+if a full distribution is not accesssed, or if a package (real or virtual)
+has been dropped from the distribution.
+.TP
+.I Total distinct versions
+is the number of package versions found in the cache; this value is
+therefore at least equal to the number of total package names. If more than
+one distribution (both "stable" and "unstable", for instance), is being
+accessed, this value can be considerably larger than the number of total
+package names.
+.TP
+.I Total dependencies
+is the number of dependency relationships claimed by all of the packages in
+the cache.
+.RE
+.SH OPTIONS
+None.
+.SH FILES
+None.
+.SH SEE ALSO
+.BR apt (8),
+.BR apt-get (8),
+.I /usr/doc/apt/cache*
+.SH DIAGNOSTICS
+apt-cache returns zero on normal operation, decimal 100 on error.
+.SH BUGS
+See <http://www.debian.org/Bugs/db/pa/lapt.html>. If you wish to report a
+bug in
+.BR apt-cache ,
+please see
+.I /usr/doc/debian/bug-reporting.txt
+or the
+.BR bug (1)
+command.
+.SH AUTHOR
+apt-cache was written by the APT team <apt@packages.debian.org>.
diff --git a/doc/apt-get.8 b/doc/apt-get.8 new file mode 100644 index 000000000..c53dc70d7 --- /dev/null +++ b/doc/apt-get.8 @@ -0,0 +1,250 @@ +.\" $Id: apt-get.8,v 1.1 1998/07/02 02:58:12 jgg Exp $
+.\" This manpage is copyright (C) 1998 Branden Robinson <branden@debian.org>.
+.\"
+.\" This is free software; you may redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2,
+.\" or (at your option) any later version.
+.\"
+.\" This is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public
+.\" License along with APT; if not, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+.\" 02111-1307 USA
+.TH apt-get 8 "16 June 1998" "Debian GNU/Linux"
+.SH NAME
+apt-get \- APT package handling utility \(em command-line interface
+.SH SYNOPSIS
+.B apt-get
+.RI [ options ]
+.RI [ command ]
+.RI [ package
+.IR ... ]
+.SH DESCRIPTION
+.B apt-get
+is the command-line tool for handling packages, and may be considered the
+user's "back-end" to
+.BR apt (8).
+Use
+.BR apt (8)
+if the usage of apt-get does not seem intuitive.
+.PP
+.I command
+is one of
+.RS
+.PD 0
+.B update
+.PP
+.B upgrade
+.PP
+.B dselect-upgrade
+.PP
+.B dist-upgrade
+.PP
+.B install
+.PP
+.B check
+.PP
+.B clean
+.RE
+.PD 1
+.PP
+Unless one of the
+.IR -h ,
+.IR --help ,
+.IR -f ,
+or
+.I --fix-broken
+options is given, one of the above commands must be present. Only the
+.B install
+command requires any further arguments.
+.SS update
+.B update
+is used to resynchronize the package overview files from their
+sources. The overviews of available packages are fetched from the
+location(s) specified in
+.IR /etc/apt/sources.list .
+For example, when using a Debian archive, this command retrieves and
+scans the
+.I Packages.gz
+files, so that information about new and updated packages is available. An
+.B update
+should always be performed before an
+.B upgrade
+or
+.BR dist-upgrade .
+.SS upgrade
+.B upgrade
+is used to install the newest versions of all packages currently installed
+on the system from the sources enumerated in
+.IR /etc/apt/sources.list .
+Packages currently installed with new versions available are retrieved
+and upgraded; under no circumstances are currently installed packages
+removed, or packages not already installed retrieved and installed. New
+versions of currently installed packages that cannot be upgraded without
+changing the install status of another package will be left at their
+current version. An
+.B update
+must be performed first so that
+.B apt-get
+knows that new versions of packages are available.
+.SS dselect-upgrade
+.B dselect-upgrade
+is used in conjunction with the traditional Debian GNU/Linux packaging
+front-end,
+.BR dselect (8). " dselect-upgrade"
+follows the changes made by
+.B dselect
+to the
+.I Status
+field of available packages, and performs the actions necessary to realize
+that state (for instance, the removal of old and the installation of new
+packages).
+.B dselect-upgrade
+does not attempt to intelligently address dependency issues as
+.B dist-upgrade
+or
+.B install
+do. If any dependency problems arise,
+.B apt-get
+aborts without performing any of the actions requested, even those
+without problems.
+.B dselect-upgrade
+is only useful to users of
+.B dselect
+and the
+.I .deb
+package file format. The
+.I /etc/apt/sources.list
+file contains a list of locations from which to retrieve desired package
+files.
+.SS dist-upgrade
+.BR dist-upgrade ,
+in addition to performing the function of
+.BR upgrade ,
+also intelligently handles changing dependencies with new versions of
+packages;
+.B apt-get
+has a "smart" conflict resolution system, and it will attempt to upgrade
+the most important packages at the expense of less important ones if
+necessary. The
+.I /etc/apt/sources.list
+file contains a list of locations from which to retrieve desired package
+files.
+.SS install
+.B install
+is followed by one or more
+.I packages
+desired for installation. Each
+.I package
+is a package name, not a fully qualified filename (for instance, in a
+Debian GNU/Linux system,
+.I lsdo
+would be the argument provided, not
+.IR ldso_1.9.6-2.deb ).
+All packages required by the package(s) specified for installation will
+also be retrieved and installed. The
+.I /etc/apt/sources.list
+file is used to locate the desired packages. If a hyphen is appended to
+the package name (with no intervening space), the identified package will
+be removed if it is installed. This latter feature may be used to override
+decisions made by apt-get's conflict resolution system.
+.SS check
+.B check
+is a diagnostic tool; it updates the package cache and checks for broken
+packages.
+.SS clean
+.B clean
+clears out the local repository of retrieved package files. It removes
+everything but the lock file from
+.I /var/cache/apt/archives/
+and
+.IR /var/cache/apt/archives/partial/ .
+When APT is used as a
+.BR dselect (8)
+method,
+.B
+clean
+is run automatically. Those who do not use dselect will likely want to
+run
+.B
+apt-get clean
+from time to time to free up disk space.
+.SH OPTIONS
+.TP
+.IR \-d , " --download-only"
+Download only; package files are only retrieved, not unpacked or installed.
+.TP
+.IR \-f , " --fix-broken"
+Fix; attempt to correct a system with broken dependencies in
+place. This option may be used alone or in conjunction with any of the
+command actions, and is sometimes necessary when running APT for the
+first time; APT itself does not allow broken package dependencies to
+exist on a system. It is possible that a system's dependency structure
+can be so corrupt as to require manual intervention (which usually
+means using dselect or dpkg --remove to eliminate some of the offending
+packages). Use of this option together with -m is discouraged.
+.TP
+.IR \-h , " --help"
+Help; display a helpful usage message and exit.
+.TP
+.IR \-m , " --ignore-missing"
+Ignore missing packages; If packages cannot be retrieved or fail the
+integrity check after retrieval (corrupted package files), hold back
+those packages and handle the result. Use of this option together with
+-f is discouraged.
+.TP
+.IR \-q , " --silent"
+Quiet; produces output suitable for logging, omitting progress indicators.
+.TP
+.I \-qq
+Very quiet; no output except for errors.
+.TP
+.IR \-s , " --simulate" , " --just-print" , " --dry-run" , " --recon " , " --no-act"
+No action; perform a simulation of events that would occur but do not
+actually change the system.
+.TP
+.IR \-y , " --yes" , " --assume-yes"
+Automatic yes to prompts; assume "yes" as answer to all prompts and run
+non-interactively.
+.SH FILES
+.TP
+.I /etc/apt/sources.list
+see
+.BR sources.list (5)
+.TP
+.I /var/cache/apt/archives/
+storage area for retrieved package files
+.TP
+.I /var/cache/apt/archives/partial/
+storage area for package files in transit
+.TP
+.I /var/state/apt/lists/
+storage area for state information for each package resource specified in
+.I /etc/apt/sources.list
+.TP
+.I /var/state/apt/lists/partial/
+storage area for state information in transit
+.SH SEE ALSO
+.BR apt (8),
+.BR apt-cache (8),
+.BR dpkg (8),
+.BR dselect (8),
+.BR sources.list (5)
+.SH DIAGNOSTICS
+apt-get returns zero on normal operation, decimal 100 on error.
+.SH BUGS
+See <http://www.debian.org/Bugs/db/pa/lapt.html>. If you wish to report a
+bug in
+.BR apt-get ,
+please see
+.I /usr/doc/debian/bug-reporting.txt
+or the
+.BR bug (1)
+command.
+.SH AUTHOR
+apt-get was written by the APT team <apt@packages.debian.org>.
diff --git a/doc/apt.8 b/doc/apt.8 new file mode 100644 index 000000000..08aa2c4fd --- /dev/null +++ b/doc/apt.8 @@ -0,0 +1,50 @@ +.\" This manpage is copyright (C) 1998 Branden Robinson <branden@debian.org>. +.\" +.\" This is free software; you may redistribute it and/or modify +.\" it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2, +.\" or (at your option) any later version. +.\" +.\" This is distributed in the hope that it will be useful, but +.\" WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with APT; if not, write to the Free Software +.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +.\" 02111-1307 USA +.TH apt 8 "16 June 1998" "Debian GNU/Linux" +.SH NAME +apt \- Advanced Package Tool +.SH SYNOPSIS +.B apt +.SH DESCRIPTION +APT is a management system for software packages. It is still +under development; the snazzy front ends are not yet available. In the +meantime, please see +.BR apt-get (8). +.SH OPTIONS +None. +.SH FILES +None. +.SH SEE ALSO +.BR apt-cache (8), +.BR apt-get (8), +.BR ftp.conf (5), +.BR sources.list (5) +.SH DIAGNOSTICS +apt returns zero on normal operation, decimal 100 on error. +.SH BUGS +This manpage isn't even started. +.PP +See <http://www.debian.org/Bugs/db/pa/lapt.html>. If you wish to report a +bug in +.BR apt , +please see +.I /usr/doc/debian/bug-reporting.txt +or the +.BR bug (1) +command. +.SH AUTHOR +apt was written by the APT team <apt@packages.debian.org>. diff --git a/doc/cache.sgml b/doc/cache.sgml new file mode 100644 index 000000000..43f8d4fff --- /dev/null +++ b/doc/cache.sgml @@ -0,0 +1,761 @@ +<!doctype debiandoc system> +<!-- -*- mode: sgml; mode: fold -*- --> +<book> +<title>APT Cache File Format</title> + +<author>Jason Gunthorpe <email>jgg@debian.org</email></author> +<version>$Id: cache.sgml,v 1.1 1998/07/02 02:58:12 jgg Exp $</version> + +<abstract> +This document describes the complete implementation and format of the APT +Cache file. The APT Cache file is a way for APT to parse and store a +large number of package files for display in the UI. It's primary design +goal is to make display of a single package in the tree very fast by +pre-linking important things like dependencies and provides. + +The specification doubles as documentation for one of the in-memory +structures used by the package library and the APT GUI. + +</abstract> + +<copyright> +Copyright © Jason Gunthorpe, 1997. +<p> +APT and this document are free software; you can redistribute them and/or +modify them under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +<p> +For more details, on Debian GNU/Linux systems, see the file +/usr/doc/copyright/GPL for the full license. +</copyright> + +<toc sect> + +<chapt>Introduction +<!-- Purpose {{{ --> +<!-- ===================================================================== --> +<sect>Purpose + +<p> +This document describes the implementation of an architecture +dependent binary cache file. The goal of this cache file is two fold, +firstly to speed loading and processing of the package file array and +secondly to reduce memory consumption of the package file array. + +<p> +The implementation is aimed at an environment with many primary package +files, for instance someone that has a Package file for their CD-ROM, a +Package file for the latest version of the distribution on the CD-ROM and a +package file for the development version. Always present is the information +contained in the status file which might be considered a separate package +file. + +<p> +Please understand, this is designed as a -CACHE FILE- it is not ment to be +used on any system other than the one it was created for. It is not ment to +be authoritative either, ie if a system crash or software failure occures it +must be perfectly acceptable for the cache file to be in an inconsistant +state. Furthermore at any time the cache file may be erased without losing +any information. + +<p> +Also the structures and storage layout is optimized for use by the APT +GUI and may not be suitable for all purposes. However it should be possible +to extend it with associate cache files that contain other information. + +<p> +To keep memory use down the cache file only contains often used fields and +fields that are inexepensive to store, the Package file has a full list of +fields. Also the client may assume that all items are perfectly valid and +need not perform checks against their correctness. Removal of information +from the cache is possible, but blanks will be left in the file, and +unused strings will also be present. The recommended implementation is to +simply rebuild the cache each time any of the data files change. It is +possible to add a new package file to the cache without any negative side +effects. + +<sect1>Note on Pointer access +<p> +Every item in every structure is stored as the index to that structure. +What this means is that once the files is mmaped every data access has to +go through a fixup stage to get a real memory pointer. This is done +by taking the tndex, multiplying it by the type size and then adding +it to the start address of the memory block. This sounds complex, but +in C it is a single array dereference. Because all items are aligned to +their size and indexs are stored as multiples of the size of the structure +the format is immediately portable to all possible architectures - BUT the +generated files are -NOT-. + +<p> +This scheme allows code like this to be written: +<example> + void *Map = mmap(...); + Package *PkgList = (Package *)Map; + Header *Head = (Header *)Map; + char *Strings = (char *)Map; + cout << (Strings + PkgList[Head->HashTable[0]]->Name) << endl; +</example> +<p> +Notice the lack of casting or multiplication. The net result is to return +the name of the first package in the first hash bucket, without error +checks. + +<p> +The generator uses allocation pools to group similarly sized structures in +large blocks to eliminate any alignment overhead. The generator also +assures that no structures overlap and all indexes are unique. Although +at first glance it may seem like there is the potential for two structures +to exist at the same point the generator never allows this to happen. +(See the discussion of free space pools) + <!-- }}} --> + +<chapt>Structures +<!-- Header {{{ --> +<!-- ===================================================================== --> +<sect>Header +<p> +This is the first item in the file. +<example> + struct Header + { + // Signature information + unsigned long Signature; + short MajorVersion; + short MinorVersion; + bool Dirty; + + // Size of structure values + unsigned short HeaderSz; + unsigned short PackageSz; + unsigned short PackageFileSz; + unsigned short VersionSz; + unsigned short DependencySz; + unsigned short ProvidesSz; + + // Structure counts + unsigned long PackageCount; + unsigned long VersionCount; + unsigned long DependsCount; + unsigned long PackageFileCount; + + // Offsets + unsigned long FileList; // PackageFile + unsigned long StringList; // StringItem + + // Pool structures + unsigned long PoolStart[6]; + unsigned long PoolSize[6]; + unsigned long PoolAln[6]; + + // Package name lookup + unsigned long HashTable[512]; // Package + }; +</example> +<taglist> +<tag>Signature<item> +This must contain the hex value 0x98FE76DC which is designed to verify +that the system loading the image has the same byte order and byte size as +the system saving the image + +<tag>MajorVersion +<tag>MinorVersion<item> +These contain the version of the cache file, currently 0.2. + +<tag>Dirty<item> +Dirty is true if the cache file was opened for reading, the client expects +to have written things to it and have not fully synced it. The file should +be erased and rebuilt if it is true. + +<tag>HeaderSz +<tag>PackageSz +<tag>PackageFileSz +<tag>VersionSz +<tag>DependencySz +<tag>ProvidesSz<item> +*Sz contains the sizeof() that particular structure. It is used as an +extra consistancy check on the structure of the file. + +If any of the size values do not exactly match what the client expects then +the client should refuse the load the file. + +<tag>PackageCount +<tag>VersionCount +<tag>DependsCount +<tag>PackageFileCount<item> +These indicate the number of each structure contianed in the cache. +PackageCount is especially usefull for generating user state structures. +See Package::Id for more info. + +<tag>FileList<item> +This contains the index of the first PackageFile structure. The PackageFile +structures are singely linked lists that represent all package files that +have been merged into the cache. + +<tag>StringList<item> +This contains a list of all the unique strings (string item type strings) in +the cache. The parser reads this list into memory so it can match strings +against it. + +<tag>PoolStart +<tag>PoolSize +<tag>PoolAln<item> +The Pool structures manage the allocation pools that the generator uses. +Start indicates the first byte of the pool, Size is the number of bytes +remaining in the pool and Aln (alignment) is the structure size of the pool. +An Aln of 0 indicates the slot is empty. There should be the same number of +slots as there are structure types. The generator stores this information +so future additions can make use of any unused pool blocks. + +<tag>HashTable<item> +HashTable is a hash table that provides indexing for all of the packages. +Each package name is inserted into the hash table using the following has +function: +<example> + unsigned long Hash(string Str) + { + unsigned long Hash = 0; + for (const char *I = Str.begin(); I != Str.end(); I++) + Hash += *I * ((Str.end() - I + 1)); + return Hash % _count(Head.HashTable); + } +</example> +<p> +By iterating over each entry in the hash table it is possible to iterate over +the entire list of packages. Hash Collisions are handled with a singely linked +list of packages based at the hash item. The linked list contains only +packages that macth the hashing function. + +</taglist> + <!-- }}} --> +<!-- Package {{{ --> +<!-- ===================================================================== --> +<sect>Package +<p> +This contians information for a single unique package. There can be any +number of versions of a given package. Package exists in a singly +linked list of package records starting at the hash index of the name in +the Header->HashTable. +<example> + struct Pacakge + { + // Pointers + unsigned long Name; // Stringtable + unsigned long VersionList; // Version + unsigned long TargetVer; // Version + unsigned long CurrentVer; // Version + unsigned long TargetDist; // StringTable (StringItem) + unsigned long Section; // StringTable (StringItem) + + // Linked lists + unsigned long NextPackage; // Package + unsigned long RevDepends; // Dependency + unsigned long ProvidesList; // Provides + + // Install/Remove/Purge etc + unsigned char SelectedState; // What + unsigned char InstState; // Flags + unsigned char CurrentState; // State + + // Unique ID for this pkg + unsigned short ID; + unsigned short Flags; + }; +</example> + +<taglist> +<tag>Name<item> +Name of the package. + +<tag>VersionList<item> +Base of a singely linked list of version structures. Each structure +represents a unique version of the package. The version structures +contain links into PackageFile and the original text file as well as +detailed infromation about the size and dependencies of the specific +package. In this way multiple versions of a package can be cleanly handled +by the system. Furthermore, this linked list is guarenteed to be sorted +from Highest version to lowest version with no duplicate entries. + +<tag>TargetVer +<tag>CurrentVer<item> +This is an index (pointer) to the sub version that is being targeted for +upgrading. CurrentVer is an index to the installed version, either can be +0. + +<tag>TargetDist<item> +This indicates the target distribution. Automatic upgrades should not go +outside of the specified dist. If it is 0 then the global target dist should +be used. The string should be contained in the StringItem list. + +<tag>Section<item> +This indicates the deduced section. It should be "Unknown" or the section +of the last parsed item. + +<tag>NextPackage<item> +Next link in this hash item. This linked list is based at Header.HashTable +and contains only packages with the same hash value. + +<tag>RevDepends<item> +Reverse Depends is a linked list of all dependencies linked to this package. + +<tag>ProvidesList<item> +This is a linked list of all provides for this package name. + +<tag>SelectedState +<tag>InstState +<tag>CurrentState<item> +These corrispond to the 3 items in the Status field found in the status +file. See the section on defines for the possible values. +<p> +SelectedState is the state that the user wishes the package to be +in. +<p> +InstState is the installation state of the package. This normally +should be Ok, but if the installation had an accident it may be otherwise. +<p> +CurrentState indicates if the package is installed, partially installed or +not installed. + +<tag>ID<item> +ID is a value from 0 to Header->PackageCount. It is a unique value assigned +by the generator. This allows clients to create an array of size PackageCount +and use it to store state information for the package map. For instance the +status file emitter uses this to track which packages have been emitted +already. + +<tag>Flags<item> +Flags are some usefull indicators of the package's state. + +</taglist> + + <!-- }}} --> +<!-- PackageFile {{{ --> +<!-- ===================================================================== --> +<sect>PackageFile +<p> +This contians information for a single package file. Package files are +referenced by Version structures. This is a singly linked list based from +Header.FileList +<example> + struct PackageFile + { + // Names + unsigned long FileName; // Stringtable + unsigned long Version; // Stringtable + unsigned long Distribution; // Stringtable + unsigned long Size; + + // Linked list + unsigned long NextFile; // PackageFile + unsigned short ID; + unsigned short Flags; + time_t mtime; // Modification time + }; +</example> +<taglist> + +<tag>FileName<item> +Refers the the physical disk file that this PacakgeFile represents. + +<tag>Version<item> +Version is the given version, ie 1.3.1, 2.4_revision_1 etc. + +<tag>Distribution<item> +Distribution is the symbolic name for this PackageFile, hamm,bo,rexx etc + +<tag>Size<item> +Size is provided as a simple check to ensure that the package file has not +been altered. + +<tag>ID<item> +See Package::ID. + +<tag>Flags<item> +Provides some flags for the PackageFile, see the section on defines. + +<tag>mtime<item> +Modification time for the file at time of cache generation. + +</taglist> + + <!-- }}} --> +<!-- Version {{{ --> +<!-- ===================================================================== --> +<sect>Version +<p> +This contians the information for a single version of a package. This is a +singley linked list based from Package.Versionlist. + +<p> +The version list is always sorted from highest version to lowest version by +the generator. Also there may not be any duplicate entries in the list (same +VerStr). + +<example> + struct Version + { + unsigned long VerStr; // Stringtable + unsigned long File; // PackageFile + unsigned long Section; // StringTable (StringItem) + + // Lists + unsigned long NextVer; // Version + unsigned long DependsList; // Dependency + unsigned long ParentPkg; // Package + unsigned long ProvidesList; // Provides + + unsigned long Offset; + unsigned long Size; + unsigned long InstalledSize; + unsigned short ID; + unsigned char Priority; + }; +</example> +<taglist> + +<tag>VerStr<item> +This is the complete version string. + +<tag>File<item> +References the PackageFile that this version came out of. File can be used +to determine what distribution the Version applies to. If File is 0 then +this is a blank version. The structure should also have a 0 in all other +fields excluding VerStr and Possibly NextVer. + +<tag>Section<item> +This string indicates which section it is part of. The string should be +contained in the StringItem list. + +<tag>NextVer<item> +Next step in the linked list. + +<tag>DependsList<item> +This is the base of the dependency list. + +<tag>ParentPkg<item> +This links the version to the owning package, allowing reverse dependencies +to determine the package. + +<tag>ProvidesList<item> +Head of the linked list of Provides::NextPkgProv, forward provides. + +<tag>Offset<item> +The byte offset of the first line of this item in the specified +PackageFile + +<tag>Size +<tag>InstalledSize<item> +The archive size for this version. For debian this is the size of the .deb +file. Installed size is the uncompressed size for this version + +<tag>ID<item> +See Package::ID. + +<tag>Priority<item> +This is the parsed priority value of the package. +</taglist> + + <!-- }}} --> +<!-- Dependency {{{ --> +<!-- ===================================================================== --> +<sect>Dependency +<p> +Dependency contains the information for a single dependency record. The records +are split up like this to ease processing by the client. The base of list +linked list is Version.DependsList. All forms of dependencies are recorded +here including Conflicts, Suggests and Recommends. + +<p> +Multiple depends on the same package must be grouped together in +the Dependency lists. Clients should assume this is always true. + +<example> + struct Dependency + { + unsigned long Version; // Stringtable + unsigned long Package; // Package + unsigned long NextDepends; // Dependency + unsigned long NextRevDepends; // Reverse dependency linking + unsigned long ParentVer; // Upwards parent version link + + // Specific types of depends + unsigned char Type; + unsigned char CompareOp; + unsigned short ID; + }; +</example> +<taglist> +<tag>Version<item> +The string form of the version that the dependency is applied against. + +<tag>Package<item> +The index of the package file this depends applies to. If the package file +does not already exist when the dependency is inserted a blank one (no +version records) should be created. + +<tag>NextDepends<item> +Linked list based off a Version structure of all the dependencies in that +version. + +<tag>NextRevDepends<item> +Reverse dependency linking, based off a Package structure. This linked list +is a list of all packages that have a depends line for a given package. + +<tag>ParentVer<item> +Parent version linking, allows the reverse dependency list to link +back to the version and package that the dependency are for. + +<tag>Type<item> +Describes weather it is depends, predepends, recommends, suggests, etc. + +<tag>CompareOp<item> +Describes the comparison operator specified on the depends line. If the high +bit is set then it is a logical or with the previous record. + +<tag>ID<item> +See Package::ID. + +</taglist> + + <!-- }}} --> +<!-- Provides {{{ --> +<!-- ===================================================================== --> +<sect>Provides +<p> +Provides handles virtual packages. When a Provides: line is encountered +a new provides record is added associating the package with a virtual +package name. The provides structures are linked off the package structures. +This simplifies the analysis of dependencies and other aspects A provides +refers to a specific version of a specific package, not all versions need to +provide that provides. + +<p> +There is a linked list of provided package names started from each +version that provides packages. This is the forwards provides mechanism. +<example> + struct Provides + { + unsigned long ParentPkg; // Package + unsigned long Version; // Version + unsigned long ProvideVersion; // Stringtable + unsigned long NextProvides; // Provides + unsigned long NextPkgProv; // Provides + }; +</example> +<taglist> +<tag>ParentPkg<item> +The index of the package that head of this linked list is in. ParentPkg->Name +is the name of the provides. + +<tag>Version<item> +The index of the version this provide line applies to. + +<tag>ProvideVersion<item> +Each provides can specify a version in the provides line. This version allows +dependencies to depend on specific versions of a Provides, as well as allowing +Provides to override existing packages. This is experimental. + +<tag>NextProvides<item> +Next link in the singly linked list of provides (based off package) + +<tag>NextPkgProv<item> +Next link in the singly linked list of provides for 'Version'. + +</taglist> + + <!-- }}} --> +<!-- StringItem {{{ --> +<!-- ===================================================================== --> +<sect>StringItem +<p> +StringItem is used for generating single instances of strings. Some things +like Section Name are are usefull to have as unique tags. It is part of +a linked list based at Header::StringList. +<example> + struct StringItem + { + unsigned long String; // Stringtable + unsigned long NextItem; // StringItem + }; +</example> +<taglist> +<tag>String<item> +The string this refers to. + +<tag>NextItem<item> +Next link in the chain. +</taglist> + <!-- }}} --> +<!-- StringTable {{{ --> +<!-- ===================================================================== --> +<sect>StringTable +<p> +All strings are simply inlined any place in the file that is natural for the +writer. The client should make no assumptions about the positioning of +strings. All stringtable values point to a byte offset from the start of the +file that a null terminated string will begin. + <!-- }}} --> +<!-- Defines {{{ --> +<!-- ===================================================================== --> +<sect>Defines +<p> +Several structures use variables to indicate things. Here is a list of all +of them. + +<sect1>Definitions for Dependency::Type +<p> +<example> +#define pkgDEP_Depends 1 +#define pkgDEP_PreDepends 2 +#define pkgDEP_Suggests 3 +#define pkgDEP_Recommends 4 +#define pkgDEP_Conflicts 5 +#define pkgDEP_Replaces 6 +</example> +</sect1> + +<sect1>Definitions for Dependency::CompareOp +<p> +<example> +#define pkgOP_OR 0x10 +#define pkgOP_LESSEQ 0x1 +#define pkgOP_GREATEREQ 0x2 +#define pkgOP_LESS 0x3 +#define pkgOP_GREATER 0x4 +#define pkgOP_EQUALS 0x5 +</example> +The lower 4 bits are used to indicate what operator is being specified and +the upper 4 bits are flags. pkgOP_OR indicates that the next package is +or'd with the current package. +</sect1> + +<sect1>Definitions for Package::SelectedState +<p> +<example> +#define pkgSTATE_Unkown 0 +#define pkgSTATE_Install 1 +#define pkgSTATE_Hold 2 +#define pkgSTATE_DeInstall 3 +#define pkgSTATE_Purge 4 +</example> +</sect1> + +<sect1>Definitions for Package::InstState +<p> +<example> +#define pkgSTATE_Ok 0 +#define pkgSTATE_ReInstReq 1 +#define pkgSTATE_Hold 2 +#define pkgSTATE_HoldReInstReq 3 +</example> +</sect1> + +<sect1>Definitions for Package::CurrentState +<p> +<example> +#define pkgSTATE_NotInstalled 0 +#define pkgSTATE_UnPacked 1 +#define pkgSTATE_HalfConfigured 2 +#define pkgSTATE_UnInstalled 3 +#define pkgSTATE_HalfInstalled 4 +#define pkgSTATE_ConfigFiles 5 +#define pkgSTATE_Installed 6 +</example> +</sect1> + +<sect1>Definitions for Package::Flags +<p> +<example> +#define pkgFLAG_Auto (1 << 0) +#define pkgFLAG_New (1 << 1) +#define pkgFLAG_Obsolete (1 << 2) +#define pkgFLAG_Essential (1 << 3) +#define pkgFLAG_ImmediateConf (1 << 4) +</example> +</sect1> + +<sect1>Definitions for Version::Priority +<p> +Zero is used for unparsable or absent Priority fields. +<example> +#define pkgPRIO_Important 1 +#define pkgPRIO_Required 2 +#define pkgPRIO_Standard 3 +#define pkgPRIO_Optional 4 +#define pkgPRIO_Extra 5 +</example> +</sect1> + +<sect1>Definitions for PackageFile::Flags +<p> +<example> +#define pkgFLAG_NotSource (1 << 0) +</example> +</sect1> + + <!-- }}} --> + +<chapt>Notes on the Generator +<!-- Notes on the Generator {{{ --> +<!-- ===================================================================== --> +<p> +The pkgCache::MergePackageFile function is currently the only generator of +the cache file. It implements a conversion from the normal textual package +file into the cache file. + +<p> +The generator assumes any package declaration with a +Status: line is a 'Status of the package' type of package declaration. +A Package with a Target-Version field should also really have a status field. +The processing of a Target-Version field can create a place-holder Version +structure that is empty to refer to the specified version (See Version +for info on what a empty Version looks like). The Target-Version syntax +allows the specification of a specific version and a target distribution. + +<p> +Different section names on different versions is supported, but I +do not expect to use it. To simplify the GUI it will mearly use the section +in the Package structure. This should be okay as I hope sections do not change +much. + +<p> +The generator goes through a number of post processing steps after producing +a disk file. It sorts all of the version lists to be in descending order +and then generates the reverse dependency lists for all of the packages. +ID numbers and count values are also generated in the post processing step. + +<p> +It is possible to extend many of the structures in the cache with extra data. +This is done by using the ID member. ID will be a unique number from 0 to +Header->??Count. For example +<example> +struct MyPkgData; +MyPkgData *Data = new MyPkgData[Header->PackageCount]; +Data[Package->ID]->Item = 0; +</example> +This provides a one way reference between package structures and user data. To +get a two way reference would require a member inside the MyPkgData structure. + +<p> +The generators use of free space pools tend to make the package file quite +large, and quite full of blank space. This could be fixed with sparse files. + + <!-- }}} --> + +<chapt>Future Directions +<!-- Future Directions {{{ --> +<!-- ===================================================================== --> +<p> +Some good directions to take the cache file is into a cache directory that +contains many associated caches that cache other important bits of +information. (/var/cache/apt, FHS2) + +<p> +Caching of the info/*.list is an excellent place to start, by generating all +the list files into a tree structure and reverse linking them to the package +structures in the main cache file major speed gains in dpkg might be achived. + + <!-- }}} --> + +</book> diff --git a/doc/design.sgml b/doc/design.sgml new file mode 100644 index 000000000..55fd7e551 --- /dev/null +++ b/doc/design.sgml @@ -0,0 +1,411 @@ +<!doctype debiandoc system> +<debiandoc> + <book> + <titlepag> + <title> The APT project design document</title> + <author> + <name>Manoj Srivastava</name> + <email>srivasta@debian.org</email> + </author> + <version>$Id: design.sgml,v 1.1 1998/07/02 02:58:12 jgg Exp $</version> + <abstract> + This document is an overview of the specifications and design + goals of the APT project. It also attempts to give a broad + description of the implementation as well. + </abstract> + <copyright> + <copyrightsummary>Copyright ©1997 Manoj Srivastava + </copyrightsummary> + <p> + APT, including this document, is free software; you may + redistribute it and/or modify it under the terms of the GNU + General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later + version.</p> + <p> + This is distributed in the hope that it will be useful, but + <em>without any warranty</em>; without even the implied + warranty of merchantability or fitness for a particular + purpose. See the GNU General Public License for more + details.</p> + + <p> + You should have received a copy of the GNU General Public + License with your Debian GNU/Linux system, in + <tt>/usr/doc/copyright/GPL</tt>, or with the + <prgn/debiandoc-sgml/ source package as the file + <tt>COPYING</tt>. If not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, + USA.</p> + </copyright> + </titlepag> + <chapt id="introduction"> + <heading>Introduction</heading> + <p>APT is supposed to be a replacement for dselect, and not a + replacement for dpkg. However, since addition functionality + has been required for APT, and given the fact that this is + very closely related to dpkg, it is not unreasonable to expect + that additional functionality in the underlying dpkg would + also be requested.</p> + + <p> Diety/dselect are the first introduction that people have to + Debian, and unfortunately this first impression contributes + greatly to the public perception of the distribution. It is + imperative that this be a showcase for Debian, rather than + frighten novices away (which has been an accusation often + levelled at the current system)</p> + </chapt> + <chapt> + <heading>Requirements</heading> + <p> + <enumlist compact="compact"> + <item> + <p> + APT should be a replacement for dselect. Therefore it + should have all the functionality that dselect has + currently. This is the primary means of interaction + between the user and the package management system, and + it should be able to handle all tasks involved in + installing, upgrading, and routine management without + having the users take recourse to the underlying + management system.</p> + </item> + <item> + <p> + It should be easier to use and less confusing for novice + users. The primary stimulus for the creation of APT + was the perceived intractability, complexity, and + non-intuitive behavior of the existing user interface, + and as such, human factors must be a primary mandate of + APT.</p> + </item> + <item> + <p> + It should be able to group packages more flexibly, and + possibly allow operations based on a group. One should + be able to select, or deselect, a coherent group of + related packages simultaneously, allowing one to add, + remove, or upgrade functionality to a machine as one + step. + </p> + </item> + <item> + <p> + This would allow APT to handle <em>standard + installations</em>, namely, one could then install a + set of packages to enable a machine to fulfill specific + tasks. Define a few standard installations, and which + packages are included therein. The packages should be + internally consistent.</p> + </item> + <item> + <p> + Make use of a keywords field in package headers; provide + a standard list of keywords for people to use. This + could be the underpinning to allow the previous two + requirements to work (though the developers are not + constrained to implement the previous requirements using + keywords) + </p> + </item> + <item> + <p> + Use dependencies, conflicts, and reverse dependencies to + properly order packages for installation and + removal. This has been a complaint in the past that the + installation methods do not really understand + dependencies, causing the upgrade process to break, or + allowing the removal of packages that left the system in + an untenable state by breaking the dependencies on + packages that were dependent on the package being + removed. A special emhasis is placed on handling + pre-dependencies correctly; the target of a + predependency has to be fully configured before + attempting to install the pre-dependent package. Also, + <em>configure immediately</em> requests mentioned below + should be handled.</p> + </item> + <item> + <p> + Handle replacement of a package providing a virtual + package with another (for example, it has been very + difficult replacing <prgn>sendmail</prgn> with + <prgn>smail</prgn>, or vice versa), making sure that the + dependencies are still satisfied. </p> + </item> + <item> + <p> + Handle source lists for updates from multiple + sources. APT should also be able to handle diverse + methods of acquiring new packages; local filesystem, + mountable CD-ROM drives, FTP accesible repositories are + some of the methods that come to mind. Also, the source + lists can be separated into categories, such as main, + contrib, non-us, non-local, non-free, my-very-own, + etc. APT should be set up to retrive the Packages + files from these multiple source lists, as well as + retrieving the packages themselves. </p> + </item> + <item> + <p> + Handle base of source and acquire all Packages files + underneath. (possibly select based on architecture), + this should be a simple extension of the previous + requirement.</p> + </item> + <item> + <p> + Handle remote installation (to be implemented maybe in a + future version, it still needs to be designed). This + would ease the burden of maintaining multiple Debian + machines on a site. In the authors opinion this is a + killer difference for the distribution, though it may be + too hard a problem to be implemented with the initial + version of APT. However, some thought must be given to + this to enable APT to retain hooks for future + functionality, or at least to refrain from methods that + may preclude remote activity. It is desirable that + adding remote installation not require a redesign of + APT from the ground up.</p> + </item> + <item> + <p> + Be scalable. Dselect worked a lot better with 400 + packages, but at last count the number of packages was + around twelve hundred and climbing. This also requires + APT to pay attention to the needs of small machines + which are low on memory (though this requirement shall + diminish as we move towards bigger machines, it would + still be nice if Debian worked on all old machines where + Linux itself would work).</p> + </item> + <item> + <p> + Handle install immediately requests. Some packages, like + watchdog, are required to be working for the stability + of the machine itself. There are others which may be + required for the correct functioning of a production + machine, or which are mission critical + applications. APT should, in these cases, upgrade the + packages with minimal downtime; allowing these packages + to be one of potentially hundreds of packages being + upgraded concurrently may not satisfy the requirements + of the package or the site. (Watchdog, for example, if + not restarted quickly, may cause the machine to reboot + in the midst of installation, which may cause havoc on + the machine)</p> + </item> + </enumlist> + </p> + </chapt> + <chapt> + <heading>Procedural description</heading> + <p><taglist> + <tag>Set Options</tag> + <item> + <p> + This process handles setting of user or + site options, and configuration of all aspects of + APT. It allows the user to set the location and order + of package sources, allowing them to set up source list + details, like ftp site locations, passwords, + etc. Display options may also be set.</p> + </item> + <tag>Updates</tag> + <item> + <p> + Build a list of available packages, using + source lists or a base location and trawling for + Packages files (needs to be aware of architecture). This + may involve finding and retrieving Packages files, + storing them locally for efficiency, and parsing the + data for later use. This would entail contacting various + underlying access modules (ftp, cdrom mounts, etc) Use a + backing store for speed. This may also require + downloading the actual package files locally for + speed.</p> + </item> + <tag>Local status</tag> + <item> + <p> + Build up a list of packages already + installed. This requires reading and writing the local?? + status file. For remote installation, this should + probably use similar mechanisms as the Packages file + retrieval does. Use the backing store for speed. One + should consider multiple backing stores, one for each + machine. + </p> + </item> + <tag>Relationship determination</tag> + <item> + <p> + Determine forward and reverse dependencies. All known + dependency fields should be acted upon, since it is + fairly cheap to do so. Update the backing store with + this information.</p> + </item> + <tag>Selection</tag> + <item> + <p> + Present the data to the user. Look at Behan Webster's + documentation for the user interface procedures. (Note: + In the authors opinion deletions and reverse + dependencies should also be presented to the user, in a + strictly symmetric fashion; this may make it easier to + prevent a package being removed that breaks + dependencies) + </p> + </item> + <tag>Ordering of package installations and configuration </tag> + <item> + <p> + Build a list of events. Simple topological sorting gives + order of packages in dependency order. At certain points + in this ordering, predependencies/immediate configure + directives cause an break in normal ordering. We need to + insert the uninstall/purge directive in the stream + (default: as early as possible).</p> + </item> + <tag>Action</tag> + <item> + <p> + Take the order of installations and removals and build + up a stream of events to send to the packaging system + (dpkg). Execute the list of events if succesful. Do not + partially install packages and leave system in broken + state. Go to The Selection step as needed.</p> + </item> + + </taglist> + </p> + </chapt> + <chapt> + <heading>Modules and interfaces</heading> + <p><taglist> + <tag>The user interface module</tag> + <item> + <p> Look at Behan Webster's documentation.</p> + </item> + <tag>Widget set</tag> + <item> + <p> + Related closely to above Could some one present design + decisions of the widget set here?</p> + </item> + <tag>pdate Module</tag> + <item> + <p> + Distinct versions of the same package are recorded + separately, but if multiple Packages files contain the + same version of a package, then only the forst one is + recorded. For this reason, the least expensive update + source should be listed first (local file system is + better than a remote ftp site)</p> + <p> + This module should interact with the user interface + module to set and change configuration parameters for + the modules listed below. It needs to record that + information in an on disk data file, to be read on + future invocations. </p> + <p><enumlist> + <item> + <p>FTP methods</p> + </item> + <item> + <p>mount and file traversal module(s)?</p> + </item> + <item> + <p>Other methods ???</p> + </item> + </enumlist> + </p> + </item> + <tag>Status file parser/generator</tag> + <item> + <p> + The status file records the current state of the system, + listing the packages installed, etc. The status file is + also one method of communicating with dpkg, since it is + perfectly permissible for the user to use APT to + request packages be updated, put others on hold, mark + other for removal, etc, and then run <tt>dpkg + -BORGiE</tt> on a file system.</p> + </item> + <tag>Package file parser/generator</tag> + <item> + <p> + Related to above. Handle multiple Packages files, from + different sources. Each package contains a link back to + the packages file structure that contains details about + the origin of the data. </p> + </item> + <tag>Dependency module</tag> + <item> + <p><list> + <item> + <p>dependency/conflict determination and linking</p> + </item> + <item> + <p>reverse dependency generator. Maybe merged with above</p> + </item> + </list> + </p> + </item> + <tag>Package ordering Module</tag> + <item> + <p>Create an ordering of the actions to be taken.</p> + </item> + <tag>Event genrator</tag> + <item> + <p>module to interact with dpkg</p> + </item> + </taglist> + </chapt> + <chapt> + <heading>Data flow and conversions analysis.</heading> + <p> + <example> + ____________ + __\|ftp modules| + / /|___________| + _ ____________ / ________________ + | update | / |mount/local file| + |==========================>| module |/_____\| traversals | + | |_____________| /|________________| + | ^ ^ + | | | ______________ + ______|_______ _ _____ ______ | _____v________ \| | + |Configuration | |configuration| | |Packages Files| ===|Status file | + | module |<=>| data | | |______________| / /|____________| + |______________| |_____________| | ^ / + ^ | | / + | | _______v_______|/_ + | | | | ________________ + | | | |/_\| Dependency | + | | |backing store |\ /| Module | + | | |______________| _|_______________| + | \ ^ /| ^ + | \ | / | + | _\|____v_______|/__ ____v_______ + |_____________________________\| User interaction| | dpkg | + /|_________________|<==>| Invoker | + |___________| + + </example> + <p> dpkg also interacts with status and available files.</p> + + + <p> + The backing store and the associated data structures are the + core of APT. All modules essentially revolve around the + backing store, feeding it data, adding and manipulating links + and relationships between data in the backing store, allowing + the user to interact with and modify the data in the backing + store, and finally writing it out as the status file and + possibly issuing directives to dpkg.</p> + + <p>The other focal point for APT is the user interface.</p> + </chapt> + </book> +</debiandoc> diff --git a/doc/dpkg-tech.sgml b/doc/dpkg-tech.sgml new file mode 100644 index 000000000..3c01ee8f0 --- /dev/null +++ b/doc/dpkg-tech.sgml @@ -0,0 +1,509 @@ +<!doctype debiandoc system> +<book> +<title>dpkg technical manual</title> + +<author>Tom Lees <email>tom@lpsg.demon.co.uk</email></author> +<version>$Id: dpkg-tech.sgml,v 1.1 1998/07/02 02:58:12 jgg Exp $</version> + +<abstract> +This document describes the minimum necessary workings for the APT dselect +replacement. It gives an overall specification of what its external interface +must look like for compatibility, and also gives details of some internal +quirks. +</abstract> + +<copyright> +Copyright © Tom Lees, 1997. +<p> +APT and this document are free software; you can redistribute them and/or +modify them under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +<p> +For more details, on Debian GNU/Linux systems, see the file +/usr/doc/copyright/GPL for the full license. +</copyright> + +<toc sect> + +<chapt>Quick summary of dpkg's external interface +<sect id="control">Control files + +<p> +The basic dpkg package control file supports the following major features:- + +<list> +<item>5 types of dependencies:- + <list> + <item>Pre-Depends, which must be satisfied before a package may be + unpacked + <item>Depends, which must be satisfied before a package may be + configured + <item>Recommends, to specify a package which if not installed may + severely limit the usefulness of the package + <item>Suggests, to specify a package which may increase the + productivity of the package + <item>Conflicts, to specify a package which must NOT be installed + in order for the package to be configured + </list> +Each of these dependencies can specify a version and a depedency on that +version, for example "<= 0.5-1", "== 2.7.2-1", etc. The comparators available +are:- + <list> + <item>"<<" - less than + <item>"<=" - less than or equal to + <item>">>" - greater than + <item>">=" - greater than or equal to + <item>"==" - equal to + </list> +<item>The concept of "virtual packages", which many other packages may provide, +using the Provides mechanism. An example of this is the "httpd" virtual package, +which all web servers should provide. Virtual package names may be used in +dependency headers. However, current policy is that virtual packages do not +support version numbers, so dependencies on virtual packages with versions +will always fail. +<item>Several other control fields, such as Package, Version, Description, +Section, Priority, etc., which are mainly for classification purposes. The +package name must consist entirely of lowercase characters, plus the characters +'+', '-', and '.'. Fields can extend across multiple lines - on the second +and subsequent lines, there is a space at the beginning instead of a field +name and a ':'. Empty lines must consist of the text " .", which will be +ignored, as will the initial space for other continuation lines. This feature +is usually only used in the Description field. +</list> + +<sect>The dpkg status area + +<p> +The "dpkg status area" is the term used to refer to the directory where dpkg +keeps its various status files (GNU would have you call it the dpkg shared +state directory). This is always, on Debian systems, /var/lib/dpkg. However, +the default directory name should not be hard-coded, but #define'd, so that +alteration is possible (it is available via configure in dpkg 1.4.0.9 and +above). Of course, in a library, code should be allowed to override the +default directory, but the default should be part of the library (so that +the user may change the dpkg admin dir simply by replacing the library). + +<p> +Dpkg keeps a variety of files in its status area. These are discussed later +on in this document, but a quick summary of the files is here:- + +<list> +<item>available - this file contains a concatenation of control information +from all the packages which dpkg knows about. This is updated using the dpkg +commands "--update-avail <file>", "--merge-avail <file>", and +"--clear-avail". +<item>status - this file contains information on the following things for +every package:- + <list> + <item>Whether it is installed, not installed, unpacked, removed, + failed configuration, or half-installed (deconfigured in + favour of another package). + <item>Whether it is selected as install, hold, remove, or purge. + <item>If it is "ok" (no installation problems), or "not-ok". + <item>It usually also contains the section and priority (so that + dselect may classify packages not in available) + <item>For packages which did not initially appear in the "available" + file when they were installed, the other control information + for them. + </list> + <p> + The exact format for the "Status:" field is: + <example> + Status: Want Flag Status + </example> + Where <var>Want</> may be one of <em>unknown</>, <em>install</>, + <em>hold</>, <em>deinstall</>, <em>purge</>. <var>Flag</> + may be one of <em>ok</>, <em>reinstreq</>, <em>hold</>, + <em>hold-reinstreq</>. + <var>Status</> may be one of <em>not-installed</>, <em>unpacked</>, + <em>half-configured</>, <em>installed</>, <em>half-installed</> + <em>config-files</>, <em>post-inst-failed</>, <em>removal-failed</>. + The states are as follows:- + <taglist> + <tag>not-installed + <item>No files are installed from the package, it has no config files + left, it uninstalled cleanly if it ever was installed. + <tag>unpacked + <item>The basic files have been unpacked (and are listed in + /var/lib/dpkg/info/[package].list. There are config files present, + but the postinst script has _NOT_ been run. + <tag>half-configured + <item>The package was installed and unpacked, but the postinst script + failed in some way. + <tag>installed + <item>All files for the package are installed, and the configuration + was also successful. + <tag>half-installed + <item>An attempt was made to remove the packagem but there was a failure + in the prerm script. + <tag>config-files + <item>The package was "removed", not "purged". The config files are left, + but nothing else. + <tag>post-inst-failed + <item>Old name for half-configured. Do not use. + <tag>removal-failed + <item>Old name for half-installed. Do not use. + </taglist> + The two last items are only left in dpkg for compatibility - they are + understood by it, but never written out in this form. + + <p> + Please see the dpkg source code, <tt>lib/parshelp.c</tt>, + <em>statusinfos</>, <em>eflaginfos</> and <em>wantinfos</> for more + details. + +<item>info - this directory contains files from the control archive of every +package currently installed. They are installed with a prefix of "<packagename>.". +In addition to this, it also contains a file called <package>.list for every +package, which contains a list of files. Note also that the control file is +not copied into here; it is instead found as part of status or available. +<item>methods - this directory is reserved for "method"-specific files - each +"method" has a subdirectory underneath this directory (or at least, it can +have). In addition, there is another subdirectory "mnt", where misc. +filesystems (floppies, CDROMs, etc.) are mounted. +<item>alternatives - directory used by the "update-alternatives" program. It +contains one file for each "alternatives" interface, which contains information +about all the needed symlinked files for each alternative. +<item>diversions - file used by the "dpkg-divert" program. Each diversion takes +three lines. The first is the package name (or ":" for user diversion), the +second the original filename, and the third the diverted filename. +<item>updates - directory used internally by dpkg. This is discussed later, +in the section <ref id="updates">. +<item>parts - temporary directory used by dpkg-split +</list> + +<sect>The dpkg library files + +<p> +These files are installed under /usr/lib/dpkg (usually), but +/usr/local/lib/dpkg is also a possibility (as Debian policy dictates). Under +this directory, there is a "methods" subdirectory. The methods subdirectory +in turn contains any number of subdirectories for each general method +processor (note that one set of method scripts can, and is, used for more than +one of the methods listed under dselect). + +<p> +The following files may be found in each of these subdirectories:- + +<list> +<item>names - One line per method, two-digit priority to appear on menu +at beginning, followed by a space, the name, and then another space and the +short description. +<item>desc.<name> - Contains the long description displayed by dselect +when the cursor is put over the <name> method. +<item>setup - Script or program which sets up the initial values to be used +by this method. Called with first argument as the status area directory +(/var/lib/dpkg), second argument as the name of the method (as in the directory +name), and the third argument as the option (as in the names file). +<item>install - Script/program called when the "install" option of dselect is +run with this method. Same arguments as for setup. +<item>update - Script/program called when the "update" option of dselect is +run. Same arguments as for setup/install. +</list> + +<sect>The "dpkg" command-line utility + +<sect1>"Documented" command-line interfaces + +<p> +As yet unwritten. You can refer to the other manuals for now. See +<manref name="dpkg" section="8">. + +<sect1>Environment variables which dpkg responds to + +<p> +<list> +<item>DPKG_NO_TSTP - if set to a non-null value, this variable causes dpkg to +run a child shell process instead of sending itself a SIGTSTP, when the user +selects to background the dpkg process when it asks about conffiles. +<item>SHELL - used to determine which shell to run in the case when +DPKG_NO_TSTP is set. +<item>CC - used as the C compiler to call to determine the target architecture. +The default is "gcc". +<item>PATH - dpkg checks that it can find at least the following files in the +path when it wants to run package installation scripts, and gives an error if +it cannot find all of them:- + <list> + <item>ldconfig + <item>start-stop-daemon + <item>install-info + <item>update-rc.d + </list> +</list> + +<sect1>Assertions + +<p> +The dpkg utility itself is required for quite a number of packages, even if +they have been installed with a tool totally separate from dpkg. The reason for +this is that some packages, in their pre-installation scripts, check that your +version of dpkg supports certain features. This was broken from the start, and +it should have actually been a control file header "Dpkg-requires", or similar. +What happens is that the configuration scripts will abort or continue according +to the exit code of a call to dpkg, which will stop them from being wrongly +configured. + +<p> +These special command-line options, which simply return as true or false are +all prefixed with "--assert-". Here is a list of them (without the prefix):- + +<list> +<item>support-predepends - Returns success or failure according to whether +a version of dpkg which supports predepends properly (1.1.0 or above) is +installed, according to the database. +<item>working-epoch - Return success or failure according to whether a version +of dpkg which supports epochs in version properly (1.4.0.7 or above) is +installed, according to the database. +</list> + +<p> +Both these options check the status database to see what version of the "dpkg" +package is installed, and check it against a known working version. + +<sect1>--predep-package + +<p> +This strange option is described as follows in the source code: + +<example> +/* Print a single package which: + * (a) is the target of one or more relevant predependencies. + * (b) has itself no unsatisfied pre-dependencies. + * If such a package is present output is the Packages file entry, + * which can be massaged as appropriate. + * Exit status: + * 0 = a package printed, OK + * 1 = no suitable package available + * 2 = error + */ +</example> + +<p> +On further inspection of the source code, it appears that what is does is +this:- + +<list> +<item>Looks at the packages in the database which are selected as "install", +and are installed. +<item>It then looks at the Pre-Depends information for each of these packages +from the available file. When it find a package for which any of the +pre-dependencies are not satisfied, it breaks from the loop through the packages. +<item>It then looks through the unsatisfied pre-dependencies, and looks for +packages which would satisfy this pre-dependency, stopping on the first it +finds. If it finds none, it bombs out with an error. +<item>It then continues this for every dependency of the initial package. +</list> + +Eventually, it writes out the record of all the packages to satisfy the +pre-dependencies. This is used by the disk method to make sure that its +dependency ordering is correct. What happens is that all pre-depending +packages are first installed, then it runs dpkg -iGROEB on the directory, +which installs in the order package files are found. Since pre-dependencies +mean that a package may not even be unpacked unless they are satisfied, it is +necessary to do this (usually, since all the package files are unpacked in one +phase, the configured in another, this is not needed). + +<chapt>dpkg-deb and .deb file internals + +<p> +This chapter describes the internals to the "dpkg-deb" tool, which is used +by "dpkg" as a back-end. dpkg-deb has its own tar extraction functions, which +is the source of many problems, as it does not support long filenames, using +extension blocks. + +<sect>The .deb archive format + +<p> +The main principal of the new-format Debian archive (I won't describe the old +format - for that have a look at deb-old.5), is that the archive really is +an archive - as used by "ar" and friends. However, dpkg-deb uses this format +internally, rather than calling "ar". Inside this archive, there are usually +the folowing members:- + +<list> +<item>debian-binary +<item>control.tar.gz +<item>data.tar.gz +</list> + +<p> +The debian-binary member consists simply of the string "2.0", indicating the +format version. control.tar.gz contains the control files (and scripts), and +the data.tar.gz contains the actual files to populate the filesystem with. +Both tarfiles extract straight into the current directory. Information on the +tar formats can be found in the GNU tar info page. Since dpkg-deb calls +"tar -cf" to build packages, the Debian packages use the GNU extensions. + +<sect>The dpkg-deb command-line + +<p> +dpkg-deb documents itself thoroughly with its '--help' command-line option. +However, I am including a reference to these for completeness. dpkg-deb +supports the following options:- + +<list> +<item>--build (-b) <dir> - builds a .deb archive, takes a directory which +contains all the files as an argument. Note that the directory +<dir>/DEBIAN will be packed separately into the control archive. +<item>--contents (-c) <debfile> - Lists the contents of ther "data.tar.gz" +member. +<item>--control (-e) <debfile> - Extracts the control archive into a +directory called DEBIAN. Alternatively, with another argument, it will extract +it into a different directory. +<item>--info (-I) <debfile> - Prints the contents of the "control" file +in the control archive to stdout. Alternatively, giving it other arguments will +cause it to print the contents of those files instead. +<item>--field (-f) <debfile> <field> ... - Prints any number of +fields from the "control" file. Giving it extra arguments limits the fields it +prints to only those specified. With no command-line arguments other than a +filename, it is equivalent to -I and just the .deb filename. +<item>--extract (-x) <debfile> <dir> - Extracts the data archive +of a debian package under the directory <dir>. +<item>--vextract (-X) <debfile> <dir> - Same as --extract, except +it is equivalent of giving tar the '-v' option - it prints the filenames as +it extracts them. +<item>--fsys-tarfile <debfile> - This option outputs a gunzip'd version +of data.tar.gz to stdout. +<item>--new - sets the archive format to be used to the new Debian format +<item>--old - sets the archive format to be used to the old Debian format +<item>--debug - Tells dpkg-deb to produce debugging output +<item>--nocheck - Tells dpkg-deb not to check the sanity of the control file +<item>--help (-h) - Gives a help message +<item>--version - Shows the version number +<item>--licence/--license (UK/US spellings) - Shows a brief outline of the GPL +</list> + +<sect1>Internal checks used by dpkg-deb when building packages + +<p> +Here is a list of the internal checks used by dpkg-deb when building packages. +It is in the order they are done. + +<list> +<item>First, the output Debian archive argument, if it is given, is checked +using stat. If it is a directory, an internal flag is set. This check is only +made if the archive name is specified explicitly on the command-line. If the +argument was not given, the default is the directory name, with ".deb" +appended. +<item>Next, the control file is checked, unless the --nocheck flag was +specified on the command-line. dpkg-deb will bomb out if the second argument +to --build was a directory, and --nocheck was specified. Note that dpkg-deb +will not be able to determine the name of the package in this case. In the +control file, the following things are checked:- + <list> + <item>The package name is checked to see if it contains any invalid + characters (see <ref id="control"> for this). + <item>The priority field is checked to see if it uses standard values, + and user-defined values are warned against. However, note that this + check is now redundant, since the control file no longer contains + the priority - the changes file now does this. + <item>The control file fields are then checked against the standard + list of fields which appear in control files, and any "user-defined" + fields are reported as warnings. + <item>dpkg-deb then checks that the control file contains a valid + version number. + </list> +<item>After this, in the case where a directory was specified to build the +.deb file in, the filename is created as "directory/pkg_ver.deb" or +"directory/pkg_ver_arch.deb", depending on whether the control file contains +an architecture field. +<item>Next, dpkg-deb checks for the <dir>/DEBIAN directory. It complains +if it doesn't exist, or if it has permissions < 0755, or > 0775. +<item>It then checks that all the files in this subdir are either symlinks +or plain files, and have permissions between 0555 and 0775. +<item>The conffiles file is then checked to see if the filenames are too +long. Warnings are produced for each that is. After this, it checks that +the package provides initial copies of each of these conffiles, and that +they are all plain files. +</list> + +<chapt>dpkg internals + +<p> +This chapter describes the internals of dpkg itself. Although the low-level +formats are quite simple, what dpkg does in certain cases often does not +make sense. + +<sect id="updates">Updates + +<p> +This describes the /var/lib/dpkg/updates directory. The function of this +directory is somewhat strange, and seems only to be used internally. A function +called cleanupdates is called whenever the database is scanned. This function +in turn uses <manref name="scandir" section="3">, to sort the files in this +directory. Files who names do not consist entirely of digits are discarded. +dpkg also causes a fatal error if any of the filenames are different lengths. + +<p> +After having scanned the directory, dpkg in turn parses each file the same way +it parses the status file (they are sorted by the scandir to be in numerical +order). After having done this, it then writes the status information back +to the "status" file, and removes all the "updates" files. + +<p> +These files are created internally by dpkg's "checkpoint" function, and are +cleaned up when dpkg exits cleanly. + +<p> +Juding by the use of the updates directory I would call it a Journal. Inorder +to effeciently ensure the complete integrity of the status file dpkg will +"checkpoint" or journal all of it's activities in the updates directory. By +merging the contents of the updates directory (in order!!) against the +original status file it can get the precise current state of the system, +even in the event of a system failure while dpkg is running. + +<p> +The other option would be to sync-rewrite the status file after each +operation, which would kill performance. + +<p> +It is very important that any program that uses the status file abort if +the updates directory is not empty! The user should be informed to run dpkg +manually (what options though??) to correct the situation. + +<sect>What happens when dpkg reads the database + +<p> +First, the status file is read. This gives dpkg an initial idea of the packages +that are there. Next, the updates files are read in, overriding the status +file, and if necessary, the status file is re-written, and updates files are +removed. Finally, the available file is read. The available file is read +with flags which preclude dpkg from updating any status information from it, +though - installed version, etc., and is also told to record that the packages +it reads this time are available, not installed. + +<p> +More information on updates is given above. + +<sect>How dpkg compares version numbers + +<p> +Version numbers consist of three parts: the epoch, the upstream version, and +the Debian revision. Dpkg compares these parts in that order. If the epochs +are different, it returns immediately, and so on. + +<p> +However, the important part is how it compares the versions which are +essentially stored as just strings. These are compared in two distinct parts: +those consisting of numerical characters (which are evaluated, and then +compared), and those consisting of other characters. When comparing +non-numerical parts, they are compared as the character values (ASCII), but +non-alphabetical characters are considered "greater than" alphabetical ones. +Also note that longer strings (after excluding differences where numerical +values are equal) are considered "greater than" shorter ones. + +<p> +Here are a few examples of how these rules apply:- + +<example> +15 > 10 +0010 == 10 + +d.r > dsr +32.d.r == 0032.d.r +d.rnr < d.rnrn +</example> + +</book> diff --git a/doc/files.sgml b/doc/files.sgml new file mode 100644 index 000000000..d98d6f68a --- /dev/null +++ b/doc/files.sgml @@ -0,0 +1,491 @@ +<!doctype debiandoc system> +<!-- -*- mode: sgml; mode: fold -*- --> +<book> +<title>APT Files</title> + +<author>Jason Gunthorpe <email>jgg@debian.org</email></author> +<version>$Id: files.sgml,v 1.1 1998/07/02 02:58:12 jgg Exp $</version> + +<abstract> +This document describes the complete implementation and format of the +installed APT directory structure. It also serves as guide to how APT +views the Debian archive. +</abstract> + +<copyright> +Copyright © Jason Gunthorpe, 1998. +<p> +"APT" and this document are free software; you can redistribute them and/or +modify them under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +<p> +For more details, on Debian GNU/Linux systems, see the file +/usr/doc/copyright/GPL for the full license. +</copyright> + +<toc sect> + +<chapt>Introduction +<!-- General {{{ --> +<!-- ===================================================================== --> +<sect>General + +<p> +This document serves two purposes. The first is to document the installed +directory structure and the format and purpose of each file. The second +purpose is to document how APT views the Debian archive and deals with +multiple package files. + +<p> +The var directory structure is as follows: +<example> + /var/state/apt/ + lists/ + partial/ + xstatus + /var/cache/apt/ + pkgcache.bin + srcpkgcache.bin + archives/ + partial/ + /etc/apt/ + sources.list + cdromdevs.list + /usr/lib/apt/ + methods/ + cdrom + ftp + http +</example> + +<p> +As is specified in the FHS 2.0 /var/state/apt is used for application +data that is not expected to be user modified. /var/cache/apt is used +for regeneratable data and is where the package cache and downloaded .debs +go. +</sect> + <!-- }}} --> + +<chapt>Files +<!-- Distribution Source List {{{ --> +<!-- ===================================================================== --> +<sect>Distribution Source list (sources.list) + +<p> +The distribution source list is used to locate archives of the debian +distribution. It is designed to support any number of active sources and to +support a mix of source media. The file lists one source per line, with the +fastest source listed first. The format of each line is: + +<p> +<var>type ui args</var> + +<p> +The first item, <var>type</var>, indicates the format for the remainder +of the line. It is designed to indicate the structure of the distribution +the line is talking about. Currently the only defined value is <em>deb</em> +which indicates a standard debian archive with a dists dir. + +<sect1>The deb Type + <p> + The <em>deb</em> type is to be a typical two level debian distributions, + dist/<var>distribution</var>/<var>component</var>. Typically distribution + is one of stable, unstable or frozen while component is one of main, + contrib, non-free or non-us. The format for the deb line is as follows: + + <p> + deb <var>uri</var> <var>distribution</var> <var>compontent</var> + [<var>component</var> ...] + + <p> + <var>uri</var> for the <em>deb</em> type must specify the base of the + debian distribution. APT will automatically generate the proper longer + URIs to get the information it needs. <var>distribution</var> can specify + an exact path, in this case the components must be omitted and + <var>distribution</var> must end in a slash. + + <p> + Since only one distribution can be specified per deb line it may be + necessary to list a number of deb lines for the same URI. APT will + sort the URI list after it has generated a complete set to allow + connection reuse. It is important to order things in the sourcelist + from most prefered to least prefered (fastest to slowest). +</sect1> + +<sect1>URI specification +<p> +URIs in the source list support a large number of access schemes. + +<taglist> +<tag>cdrom<item> + The cdrom scheme is special in that If Modifed Since queries are never + performed and that APT knows how to match a cdrom to the name it + was given when first inserted. It does this by examining the date + and size of the package file. APT also knows all of the possible + prefix paths for the cdrom drives and that the user should be prompted + to insert a CD if it cannot be found. The path is relative to an + arbitary mount point (of APT's choosing) and must not start with a + slash. The first pathname component is the given name and is purely + descriptive and of the users choice. However, if a file in the root of + the cdrom is called 'cdname' its contents will be used instead of + prompting. The name serves as a tag for the cdrom and should be unique. + APT will track the CDROM's based on their tag and package file + properties. + <example> + cdrom:Debian 1.3/debian + </example> + +<tag>http<item> + This scheme specifies a HTTP server for the debian archive. HTTP is prefered + over FTP because If Modified Since queries against the Package file are + possible. Newer HTTP protcols may even support reget which would make + http the protocol of choice. + <example> + http://www.debian.org/archive + </example> + +<tag>ftp<item> + This scheme specifies a FTP connection to the server. FTP is limited because + there is no support for IMS and is hard to proxy over firewalls. + <example> + ftp://ftp.debian.org/debian + </example> + +<tag>file<item> + The file scheme allows an arbitary directory in the file system to be + considered as a debian archive. This is usefull for NFS mounts and + local mirrors/archives. + <example> + file:/var/debian + </example> + +<tag>mirror<item> + The mirror scheme is special in that it does not specify the location of a + debian archive but specifies the location of a list of mirrors to use + to access the archive. Some technique will be used to determine the + best choice for a mirror. The mirror file is specified in the Mirror File + section. If/when URIs take off they should obsolete this field. + <example> + mirror:http://www.debian.org/archivemirrors + </example> + +<tag>smb<item> + A possible future expansion may be to have direct support for smb (Samba + servers). + <example> + smb://ftp.kernel.org/pub/mirrors/debian + </example> +</taglist> +</sect1> + +<sect1>Hashing the URI +<p> +All permanent information aquired from any of the sources is stored in the +lists directory. Thus, there must be a way to relate the filename in the +lists directory to a line in the sourcelist. To simplify things this is +done by quoting the URI and treating ='s as quoteable characters and +converting / to =. The URI spec says this is done by converting a +sensitive character into %xx where xx is the hexadecimal representation +from the ascii character set. Examples: + +<example> +http://www.debian.org/archive/dists/stable/binary-i386/Packages +/var/state/apt/lists/www.debian.org=archive=dists=stable=binary-i386=Packages + +cdrom:Debian 1.3/debian/Packages +/var/state/apt/info/Debian%201.3=debian=Packages +</example> + +<p> +The other alternative that was considered was to use a deep directory +structure but this poses two problems, it makes it very difficult to prune +directories back when sources are no longer used and complicates the handling +of the partial directory. This gives a very simple way to deal with all +of the situations that can arise. The equals sign was choosen on the +suggestion of Manoj because it is very infrequently used in filenames. +Also note that the same rules described in the <em>Archive Directory</> +section regarding the partial sub dir apply here as well. +</sect1> + +</sect> + <!-- }}} --> +<!-- Extra Status {{{ --> +<!-- ===================================================================== --> +<sect>Extra Status File (xstatus) + +<p> +The extra status file serves the same purpose as the normal dpkg status file +(/var/lib/dpkg/status) except that it stores information unique to diety. +This includes the autoflag, target distribution and version and any other +uniqe features that come up over time. It duplicates nothing from the normal +dpkg status file. Please see other APT documentation for a discussion +of the exact internal behavior of these fields. The Package field is +placed directly before the new fields to indicate which package they +apply to. The new fields are as follows: + +<taglist> +<tag>X-Auto<item> + The Auto flag can be Yes or No and controls whether the package is in + auto mode. + +<tag>X-TargetDist<item> + The TargetDist item indicates which distribution versions are offered for + installation from. It should be stable, unstable or frozen. + +<tag>X-TargetVersion<item> + The target version item is set if the user selects a specific version, it + overrides the TargetDist selection if both are present. +</taglist> +</sect> + <!-- }}} --> +<!-- Binary Package Cache {{{ --> +<!-- ===================================================================== --> +<sect>Binary Package Cache (pkgcache.bin) + +<p> +Please see cache.sgml for a complete description of what this file is. The +cache file is updated whenever the contents of the lists directory changes. +If the cache is erased, corrupted or of a non-matching version it will +be automatically rebuilt by all of the tools that need it. +<em>srcpkgcache.bin</> contains a cache of all of the package files in the +source list. This allows regeneration of the cache when the status files +change to use a prebuilt version for greater speed. +</sect> + <!-- }}} --> +<!-- Downloads Directory {{{ --> +<!-- ===================================================================== --> +<sect>Downloads Directory (archives) + +<p> +The archives directory is where all downloaded .deb archives go. When the +file transfer is initiated the deb is placed in partial. Once the file +is fully downloaded and its MD5 hash and size are verifitied it is moved +from partial into archives/. Any files found in archives/ can be assumed +to be verified. + +<p> +No dirctory structure is transfered from the receiving site and all .deb +file names conform to debian conventions. No short (msdos) filename should +be placed in archives. If the need arises .debs should be unpacked, scanned +and renamed to their correct internal names. This is mostly to prevent +file name conflicts but other programs may depend on this if convenient. +Downloaded .debs must be found in one of the package lists with an exact +name + version match.. +</sect> + <!-- }}} --> +<!-- The Methods Directory {{{ --> +<!-- ===================================================================== --> +<sect> The Methods Directory (/usr/lib/apt/methods) + +<p> +Like dselect, APT will support plugable acquisition methods to complement +its internaly supported methods. The files in +this directory are execultables named after the URI type. APT will +sort the required URIs and spawn these programs giving a full sorted, quoted +list of URIs. + +<p> +The interface is simple, the program will be given a list +of URIs on the command line. The URIs will be in pairs, the first +being the actual URI and the second being the filename to write the data to. +The current directory will be set properly by APT and it is +expected the method will put files relative to the current directory. +The output of these programs is strictly speficied. The programs must accept +nothing from stdin (stdin will be an invalid fd) and they must output +status information to stdout according to the format below. +Stderr will be redirected to the logging facility. + +<p> +Each line sent to stdout must be a line that has a single letter and a +space. Strings after the first letter do not need quoting, they are taken +as is till the end of the line. The tag letters, listed in expected order, +is as follows: + +<taglist> + +<tag>F - Change URI<item> +This specifies a change in URI. All information after this will be applied +to the new URI. When the URI is changed it is assumed that the old URI has +completed unless an error is set. The format is <var>F URI</> + +<tag>S - Object Size<item> +This specifies the expected size of the object. APT will use this to +compute percent done figures. If it is not sent then a kilobyte meter +will be used instead of a percent display. The foramat is <var>S INTEGER</> + +<tag>E - Error Information<item> +Exactly one line of error information can be set for each URI. The +information will be summarized for the user. If an E tag is send before +any F tags then the error is assumed to be a fatal method error and all URI +fetches for that method are aborted with that error string. The format +is <var>E String</> + +<tag>I - Informative progress information<item> +The I tag allows the method to specify the status of the connection. +Typically the GUI will show the last recieved I line. The format is +<var>I String</> As a general rule an I tag should be ommitted before a +lengthy operation only. Things that always take a short period are not +suited for I tags. I tags should change wnenever the methods state changes. +Some standard forms, in order of occurance, are <var>Connecting to SITE</>, +<var>Connecting to SITE (1.1.1.1)</>, <var>Waiting for file</>, +<var>Authenticating</>, <var>Downloading</>, <var>Resuming (size)</>, +<var>Computing MD5</> <var>I</> lines should never print out information that +APT is already aware of, such as file names. + +<tag>R - Set final path<item> +The R tag allows the method to tell APT that the file is present in the +local file system. APT might copy it into a the download directory. The format +is <var>R String</> + +<tag>M - MD5Sum of the file<item> +The method is expected to compute the md5 hash on the fly as the download +progresses. The final md5 of the file is to be output when the file is +completed. If the md5 is not output it will not be checked! Some methods +such as the file method will not check md5's because they are most +commonly used on mirrors or local CD-ROM's, a paranoid option may be +provided in future to force checking. The format is <var>M MD5-String</> + +<tag>L - Log output<item> +This tag indicates a string that should be dumped to some log file. The +string is for debugging and is not ment to be seen by the user. The format +is <var>L String</> Log things should only be used in a completed method +if they have special relavence to what is happening. +</taglist> + +<p> +APT monitors the progress of the transfer by watching the file size. This +means the method must not create any temp files and must use a fairly small +buffer. The method is also responsible for If-Modified-Since (IMS) queries +for the object. It should check ../outputname to get the time stamp but not +size. The size may be different because the file was uncompressed after +it was transfed. A method must <em>never</> change the file in .., it may +only change the output file in the current directory. + +<p> +The APT 'http' program is the reference implementation of this specification, +it implements all of the features a method is expected to do. +</sect> + <!-- }}} --> +<!-- The Mirror List {{{ --> +<!-- ===================================================================== --> +<sect> The Mirror List + +<p> +The mirror list is stored on the primary debian web server (www.debian.org) +and contains a machine readable list of all known debian mirrors. The mirror +URI type will cause this list to be downloaded and considered. It has the +same form as the source list. When the source list specifies mirror +as the target the mirror list is scanned to find the nescessary parts for +the requested distributions and components. This means the user could +have a line like: + +<var>deb mirror:http://www.debian.org/mirrorlist stable main non-us</var> + +which would likely cause APT to choose two separate sites to download from, +one for main and another for non-us. + +<p> +Some form of network measurement will have to be used to gauge performance +of each of the mirrors. This will be discussed later, initial versions +will use the first found URI. +</sect> + <!-- }}} --> +<!-- The Release File {{{ --> +<!-- ===================================================================== --> +<sect> The Release File + +<p> +This file plays and important role in how APT presents the archive to the +user. Its main purpose is to present a descriptive name for the source +of each version of each package. It also is used to detect when new versions +of debian are released. It augments the package file it is associated with +by providing meta information about the entire archive which the Packages +file describes. + +<p> +The full name of the distribution for presentation to the user is formed +as 'label version archive', with a possible extended name being +'label version archive component'. + +<p> +The file is formed as the package file (RFC-822) with the following tags +defined: + +<taglist> +<tag>Archive<item> +This is the common name we give our archives, such as <em>stable</> or +<em>unstable</>. + +<tag>Component<item> +Referes to the sub-component of the archive, <em>main</>, <em>contrib</> +etc. + +<tag>Version<item> +This is a version string with the same properties as in the Packages file. +It represents the release level of the archive. + +<tag>Origin<item> +This specifies who is providing this archive. In the case of Debian the +string will read 'Debian'. Other providers may use their own string + +<tag>Label<item> +This carries the encompassing name of the distribution. For Debian proper +this field reads 'Debian'. For derived distributions it should contain their +proper name. + +<tag>Architecture<item> +When the archive has packages for a single architecture then the Architecture +is listed here. If a mixed set of systems are represented then this should +contain the keyword <em>mixed</em>. + +<tag>NotAutomatic<item> +A Yes/No flag indicating that the archive is extremely unstable and its +version's should never be automatically selected. This is to be used by +experimental. + +<tag>Description<item> +Description is used to describe the release. For instance experimental would +contain a warning that the packages have problems. +</taglist> + +<p> +The location of the Release file in the archive is very important, it must +be located in the same location as the packages file so that it can be +located in all situations. The following is an example for the current stable +release, 1.3.1r6 + +<example> +Archive: stable +Compontent: main +Version: 1.3.1r6 +Origin: Debian +Label: Debian +Architecture: i386 +</example> + +This is an example of experimental, +<example> +Archive: experimental +Version: 0 +Origin: Debian +Label: Debian +Architecture: mixed +NotAutomatic: Yes +</example> + +And unstable, +<example> +Archive: unstable +Compontent: main +Version: 2.1 +Origin: Debian +Label: Debian +Architecture: i386 +</example> + +</sect> + <!-- }}} --> + +</book> diff --git a/doc/ftp.conf.5 b/doc/ftp.conf.5 new file mode 100644 index 000000000..30c7c031b --- /dev/null +++ b/doc/ftp.conf.5 @@ -0,0 +1,93 @@ +.\" This manpage is copyright (C) 1998 Branden Robinson <branden@debian.org>
+.\" and Manoj Srivastava <srivasta@datasync.com>.
+.\"
+.\" This is free software; you may redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2,
+.\" or (at your option) any later version.
+.\"
+.\" This is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public
+.\" License along with APT; if not, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+.\" 02111-1307 USA
+.TH ftp.conf 5 "16 June 1998" "Debian GNU/Linux"
+.SH NAME
+ftp.conf \- configuration file for APT FTP method
+.SH DESCRIPTION
+The ftp.conf file determines the behavior of the FTP method for the APT
+packaging tool. The syntax of the file is
+.IR variable = value .
+Quotes are not required around
+.IR value s.
+Comments start with a '#' and end at the next newline. Blank lines are
+ignored. The following
+.I variables
+are understood:
+.IP Firewall
+is the hostname of a machine which acts as an FTP firewall. This can be
+overridden by an environment variable
+.IR FTP_FIREWALL .
+If specified, and the given hostname cannot be directly contacted, a connection
+is made to the firewall machine and the string
+.B @hostname
+is appended to the login identifier. This type of setup is also known as an
+FTP proxy.
+.IP ProxyLogName
+is a parameter used by some firewall FTP proxies. It is used to authorize
+the user specified by
+.I ProxyLogName
+to send data beyond the
+.I Firewall
+machine.
+.IP ProxyPassword
+is the password used to authenticate
+.I ProxyLogName
+on the
+.I Firewall
+machine.
+.IP TimeOut
+sets a timeout value in seconds (the default is sixty seconds).
+.IP Passive
+is either
+.B true
+or
+.BR false .
+If true, then all data transfers will be done using passive mode. This is
+required for some dumb FTP servers and firewall configurations. It can
+also be overridden by the environment variable
+.IR FTP_PASSIVE .
+.IP Verbose
+is either
+.B true
+or
+.B false,
+and makes the FTP method output more data than it normally does.
+.IP Debug
+is either
+.B true
+or
+.B false,
+and makes the FTP method output debugging information. This variable is
+not currently implemented.
+.IP MaxReTry
+sets the number of times a connection is re-tried before giving up (the
+default is twice).
+.SH SEE ALSO
+.BR apt (8),
+.BR apt-get (8)
+.SH BUGS
+See <http://www.debian.org/Bugs/db/pa/lapt.html>. If you wish to report a
+bug in
+.BR apt-get ,
+please see
+.I /usr/doc/debian/bug-reporting.txt
+or the
+.BR bug (1)
+command.
+.SH AUTHOR
+APT was written by the APT team <apt@packages.debian.org>.
diff --git a/doc/guide.sgml b/doc/guide.sgml new file mode 100644 index 000000000..bbc01b78b --- /dev/null +++ b/doc/guide.sgml @@ -0,0 +1,548 @@ +<!doctype debiandoc system> +<!-- -*- mode: sgml; mode: fold -*- --> +<book> +<title>APT User's Guide</title> + +<author>Jason Gunthorpe <email>jgg@debian.org</email></author> +<version>$Id: guide.sgml,v 1.1 1998/07/02 02:58:12 jgg Exp $</version> + +<abstract> +This document provides an overview of how to use the the APT package manager. +</abstract> + +<copyright> +Copyright © Jason Gunthorpe, 1998. +<p> +"APT" and this document are free software; you can redistribute them and/or +modify them under the terms of the GNU General Public License as published +by the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +<p> +For more details, on Debian GNU/Linux systems, see the file +/usr/doc/copyright/GPL for the full license. +</copyright> + +<toc sect> + +<!-- General {{{ --> +<!-- ===================================================================== --> +<chapt>General + +<p> +The APT package currently contains two sections, the APT <prgn>dselect</> +method and the <prgn>apt-get</> command line user interface. Both provide +a way to install and remove packages as well as download new packages from +the Internet. + +<sect>Anatomy of the Package System +<p> +The Debian packaging system has a large amount of information associated with +each package to help assure that it integrates cleanly and easily into +the system. The most prominent of features is the dependency system. + +<p> +The dependency system allows individual programs to make use of shared +elements in the system such as libraries. It simplifies placing infrequently +used portions of a program in separate packages to reduce the +number of things the average user is required to install. Also, it allows +a choices in for such things as mail transport agents, X servers and +so on. + +<p> +The first step to understanding the dependency system is to grasp the concept +of a simple dependency. The meaning of a simple dependency is that a package +requires another package to be installed at the same time to work properly. + +<p> +For instance, mail-crypt is an emacs extension that aids in encrypting email +with PGP. Without PGP installed mail-crypt is useless, so mail-crypt has a +simple dependency on PGP. Also, because it is an emacs extension it has a +simple dependency on emacs, without emacs it is completely useless. + +<p> +The other important dependency to understand is a conflicting dependency. It +means that a package, when installed with another package, will not work and +may possibly be extremely harmful to the system. As an example consider a +mail transport agent such as sendmail, exim or qmail. It is not possible +to have two mail transport agents installed because both need to listen to +the network to receive mail. Attempting to install two will seriously +damage the system so all mail transport agents have a conflicting dependency +with all other mail transport agents. + +<p> +As an added complication there is the possibility for a package to pretend +to be another package. Consider that exim and sendmail for many intents are +identical, they both deliver mail and understand a common interface. Hence, +the package system has a way for them to declare that they are both +mail-transport-agents. So, exim and sendmail both declare that they provide a +mail-transport-agent and other packages that need a mail transport agent +depend on mail-transport-agent. This can add a great deal of confusion when +trying to manually fix packages. + +<p> +At any given time a single dependency may be met by packages that are already +installed or it may not be. APT attempts to help resolve dependency issues +by providing a number of automatic algorithms that help in selecting packages +for installation. +</sect> + +</chapt> + <!-- }}} --> +<!-- apt-get {{{ --> +<!-- ===================================================================== --> +<chapt>apt-get + +<p> +<prgn>apt-get</> provides a simple way to install packages from the command +line. Unlike <prgn>dpkg</>, <prgn>apt-get</> does not understand .deb files, +it works with the packages proper name and can only install .deb archives from +a <em>Source</>. + +<p> +The first <footnote>If you are using an http proxy server you must set the +http_proxy environment variable first, see sources.list(5)</footnote> thing that +should be done before using <prgn>apt-get</> is to fetch the package lists +from the <em>Sources</> so that it knows what packages are +available. This is done with <tt>apt-get update</>. For instance, + +<p> +<example> +# apt-get update +Get http://ftp.de.debian.org/debian-non-US/ stable/binary-i386/ Packages +Get http://llug.sep.bnl.gov/debian/ frozen/contrib Packages +Updating package file cache...done +Updating package status cache...done +Checking system integrity...ok +</example> + +<p> +Once updated there are several useful commands that can be used, +<taglist> +<tag>upgrade<item> +Upgrade will attempt to gently upgrade the whole system. Upgrade will +never install a new package or remove an existing package, nor will it +ever upgrade a package that might cause some other package to break. +This can be used daily to relatively safely upgrade the system. Upgrade +will list all of the packages that it could not upgrade, this usually +means that they depend on new packages or conflict with some other package. +<prgn>Dselect</> or <tt>apt-get install</> can be used to force these +packages to install. + +<tag>install<item> +Install is used to install single packages by name. The package is +automatically fetched and installed. This can be useful if you already +know the name of the package to install and do not want to go into a GUI +to select it. Any number of packages may be passed to install, they will +all be fetched. Install automatically attempts to resolve dependency problems +with the listed packages and will print a summary and ask for confirmation +if anything other than it's arguments are changed + +<tag>dist-upgrade<item> +Dist-upgrade is a complete upgrader designed to make simple upgrading between +releases of Debian. It uses a sophisticated algorithm to determine the best +set of packages to install, upgrade and remove to get as much of the system +to the newest release. In some situations it may be desired to use dist-upgrade +rather than spend the time manually resolving dependencies in <prgn>dselect</>. +Once dist-upgrade has completed then <prgn>dselect</> can be used to install +any packages that may have been left out. + +<p> +It is important to closely look at what dist-upgrade is going to do, its +decisions may sometimes be quite surprising. +</taglist> + +<p> +<prgn>apt-get</> has several command line options that are detailed in it's +man page, <manref name="apt-get" section="8">. The most useful option is +<tt>-d</> which does not install the fetched files. If the system has to +download a large number of package it would be undesired to start installing +them in case something goes wrong. When <tt>-d</> is used the downloaded +archives can be installed by simply running the command that caused them to +be downloaded again without <tt>-d</>. + +</chapt> + <!-- }}} --> +<!-- DSelect {{{ --> +<!-- ===================================================================== --> +<chapt>DSelect +<p> +The APT <prgn>dselect</> method provides the complete APT system with +the <prgn>dselect</> package selection GUI. <prgn>dselect</> is used to +select the packages to be installed or removed and APT actually installs them. + +<p> +To enable the APT method you need to to select [A]ccess in <prgn>dselect</> +and then choose the APT method. You will be prompted for a set of +<em>Sources</> which are places to fetch archives from. These can be remote +Internet sites, local Debian mirrors or CDROMs. Each source can provide +a fragment of the total Debian archive, APT will automatically combine them +to form a complete set of packages. If you have a CDROM then it is a good idea +to specify it first and then specify a mirror so that you have access to +the latest bug fixes. APT will automatically use packages on your CDROM before +downloading from the Internet. + +<p> +<example> + Set up a list of distribution source locations + + Please give the base URL of the debian distribution. + The access schemes I know about are: http file + + For example: + file:/mnt/debian, + ftp://ftp.debian.org/debian, + http://ftp.de.debian.org/debian, + + + URL [http://llug.sep.bnl.gov/debian]: +</example> + +<p> +The <em>Sources</> setup starts by asking for the base of the Debian +archive, defaulting to a HTTP mirror. Next it asks for the distribution to +get. + +<p> +<example> + Please give the distribution tag to get or a path to the + package file ending in a /. The distribution + tags are typically something like: stable unstable frozen non-US + + Distribution [stable]: +</example> + +<p> +The distribution refers to the Debian version in the archive, <em>stable</> +refers to the latest released version and <em>unstable</> refers to the +developmental version. <em>non-US</> is only available on some mirrors and +refers to packages that contain encryption technology or other things that +cannot be exported from the United States. Importing these packages into the +US is legal however. +<footnote>As of this writing the non-US distribution has +not been created, the only way to access it is by specifying +stable/binary-i386/ at this prompt and by specifying a URL ending in +debian-non-US </footnote> + +<p> +<example> + Please give the components to get + The components are typically something like: main contrib non-free + + Components [main contrib non-free]: +</example> + +<p> +The components list refers to the list of sub distributions to fetch. The +distribution is split up based on software copyright, main being DFSG free +packages while contrib and non-free contain things that have various +restrictions placed on their use and distribution. + +<p> +Any number of sources can be added, the setup script will continue to +prompt until you have specified all that you want. + +<p> +Before starting to use <prgn>dselect</> it is necessary to update the +available list by selecting [U]pdate from the menu. This is a super-set of +<tt>apt-get update</> that makes the fetched information available to +<prgn>dselect</>. [U]pdate must be performed even if <tt>apt-get update</> +has been run before. + +<p> +You can then go on and make your selections using [S]elect and then +perform the installation using [I]nstall. When using the APT method +the [C]onfig and [R]emove commands have no meaning, the [I]nstall command +performs both of them together. + +</chapt> + <!-- }}} --> +<!-- The Interfaces {{{ --> +<!-- ===================================================================== --> +<chapt>The Interface + +<p> +Both that APT <prgn>dselect</> method and <prgn>apt-get</> share the same +interface. It is a simple system that generally tells you what it will do +and then goes and does it. +<footnote> +The <prgn>dselect</> method actually is a set of wrapper scripts +to <prgn>apt-get</>. The method actually provides more functionality than +is present in <prgn>apt-get</> alone. +</footnote> +After printing out a summary of what will happen APT then will print out some +informative status messages so that you can estimate how far along it is and +how much is left to do. + +<!-- ===================================================================== --> +<sect>The Pre-Checks + +<p> +Before all operations, except update, APT performs a number of checks on the +systems. These are designed to safe guard the operations it is about to +undertake. At any time the full set of checks may be run by performing +<tt>apt-get check</>. +<p> +<example> +# apt-get check +Updating package file cache...done +Updating package status cache...done +Checking system integrity...ok +</example> + +<p> +The first check is to ensure that the archive package lists are matched to +the pre-generated data cache, if they are not then the cache is automatically +refreshed. This may fail if <tt>apt-get update</> has not been run to +synchronize with the <em>Sources</>. The next check verifies that the state of +the system matches the cached state and automatically rebuilds the cached +state if they are not synchronized. This check should never fail and it +indicates a serious error if it ever does. + +<p> +The final check performs a detailed analysis of the system integrity. It +checks every dependency of every installed or unpacked package and considers +if it is ok. Should this find a problem then a report will be printed out and +<prgn>apt-get</> will refuse to run. + +<p> +<example> +# apt-get check +Updating package file cache...done +Updating package status cache...done +Checking system integrity...dependency error +You might want to run apt-get -f install' to correct these. +Sorry, but the following packages are broken - this means they have unmet +dependencies: + libdbd-mysql-perl: Depends:perl + xzx: Depends:xlib6 + libdbd-msql-perl: Depends:perl + mailpgp: Depends:pgp-i Depends:pgp-us + xdpkg: Depends:python + squake: Depends:quake-lib Depends:quake-lib-stub + debmake: Depends:fileutils + libreadlineg2: Conflicts:libreadline2 + ssh: Depends:gmp2 Depends:xlib6g Depends:zlib1g +</example> + +<p> +In this example the system has many problems, including a serious problem +with libreadlineg2. For each package that has unmet dependencies a line +is printed out indicating the package with the problem and the dependencies +that are unmet. For brevity the version inter-relationships are omitted. + +<p> +There are two ways a system can get into a broken state like this. The +first is caused by <prgn>dpkg missing</> some subtle relationships between +packages when performing upgrades. <footnote>APT however considers all known +dependencies and attempts to prevent broken packages</footnote>. The second is +if a package installation fails during an operation. In this situation a +package may have been unpacked without its dependents being installed. + +<p> +The second situation is much less serious than the first because APT places +certain assurances on the order that packages are installed. In both cases +supplying the <tt>-f</> option to <prgn>atp-get</> will cause APT to deduce a +possible solution to the problem and then continue on. The APT <prgn>dselect</> +method always supplies the <tt>-f</> option to allow for easy continuation +of failed maintainer scripts. + +<p> +However, if the <tt>-f</> option is used to correct a seriously broken system +caused by the first case then it is possible that it will either fail +immediately or the installation sequence will fail. In either case it is +necessary to manually use dpkg (possibly with forcing options) to correct +the situation enough to allow APT to proceed. +</sect> + +<!-- ===================================================================== --> +<sect>The Status Report + +<p> +Before proceeding <prgn>apt-get</> will present a report on what will happen. +Generally the report reflects the type of operation being performed but there +are several common elements. In all cases the lists reflect the final state +of things, taking into account the <tt>-f</> option and any other relevant +activities to the command being executed. + +<sect1>The Extra Package list +<p> +<example> +The following extra packages will be installed: + libdbd-mysql-perl xlib6 zlib1 xzx libreadline2 libdbd-msql-perl + mailpgp xdpkg fileutils pinepgp zlib1g xlib6g perl-base + bin86 libgdbm1 libgdbmg1 quake-lib gmp2 bcc xbuffy + squake pgp-i python-base debmake ldso perl libreadlineg2 + ssh +</example> + +<p> +The Extra Package list shows all of the packages that will be installed +or upgraded in excess of the ones mentioned on the command line. It is +only generated for an <tt>install</> command. The listed packages are +often the result of an Auto Install. +</sect1> + +<sect1>The Packages to Remove +<p> +<example> +The following packages will be REMOVED: + xlib6-dev xpat2 tk40-dev xkeycaps xbattle xonix + xdaliclock tk40 tk41 xforms0.86 ghostview xloadimage xcolorsel + xadmin xboard perl-debug tkined xtetris libreadline2-dev perl-suid + nas xpilot xfig +</example> + +<p> +The Packages to Remove list shows all of the packages that will be +removed from the system. It can be shown for any of the operations and +should be given a careful inspection to ensure nothing important is to +be taken off. The <tt>-f</> option is especially good at generating packages +to remove so extreme care should be used in that case. The list may contain +packages that are going to be removed because they are only +partially removed, possibly due to an aborted installation. +</sect1> + +<sect1>The New Packages list +<p> +<example> +The following NEW packages will installed: + zlib1g xlib6g perl-base libgdbmg1 quake-lib gmp2 pgp-i python-base +</example> + +<p> +The New Packages list is simply a reminder of what will happen. The packages +listed are not presently installed in the system but will be when APT is done. +</sect1> + +<sect1>The Kept Back list +<p> +<example> +The following packages have been kept back + compface man-db tetex-base msql libpaper svgalib1 + gs snmp arena lynx xpat2 groff xscreensaver +</example> + +<p> +Whenever the whole system is being upgraded there is the possibility that +new versions of packages cannot be installed because they require new things +or conflict with already installed things. In this case the package will +appear in the Kept Back list. The best way to convince packages listed +there to install is with <tt>apt-get install</> or by using <prgn>dselect</> +to resolve their problems. +</sect1> + +<sect1>Held Packages warning +<p> +<example> +The following held packages will be changed: + cvs +</example> + +<p> +Sometimes you can ask APT to install a package that is on hold, in such a +case it prints out a warning that the held package is going to be +changed. This should only happen during dist-upgrade or install. +</sect1> + +<sect1>Final summary +<p> +Finally, APT will print out a summary of all the changes that will occur. + +<p> +<example> +206 packages upgraded, 8 newly installed, 23 to remove and 51 not upgraded. +12 packages not fully installed or removed. +Need to get 65.7M/66.7M of archives. After unpacking 26.5M will be used. +</example> + +<p> +The first line of the summary simply is a reduced version of all of the +lists and includes the number of upgrades - that is packages already +installed that have new versions available. The second line indicates the +number of poorly configured packages, possibly the result of an aborted +installation. The final line shows the space requirements that the +installation needs. The first pair of numbers refer to the size of +the archive files. The first number indicates the number of bytes that +must be fetched from remote locations and the second indicates the +total size of all the archives required. The next number indicates the +size difference between the presently installed packages and the newly +installed packages. It is roughly equivalent to the space required in +/usr after everything is done. If a large number of packages are being +removed then the value may indicate the amount of space that will be +freed. + +</sect> + +<!-- ===================================================================== --> +<sect>The Status Display +<p> +During the download of archives and package files APT prints out a series of +status messages, + +<p> +<example> +# apt-get update +Get http://ftp.de.debian.org/debian-non-US/ stable/binary-i386/ Packages +Get http://llug.sep.bnl.gov/debian/ frozen/contrib Packages +Get http://llug.sep.bnl.gov/debian/ frozen/main Packages +Get http://ftp.de.debian.org/debian-non-US/ unstable/binary-i386/ Packages +Get http://llug.sep.bnl.gov/debian/ frozen/non-free Packages +11% [Packages `Waiting for file' 0/32.1k 0%] 2203b/s 1m52s +</example> + +<p> +The lines starting with <em>Get</> are printed out when APT begins to fetch +a file while the last line indicates the progress of the download. The first +percent value on the progress line indicates the total percent done of all +files. Unfortunately since the size of the Package files is unknown +<tt>apt-get update</> estimates the percent done which causes some +inaccuracies. + +<p> +The next section of the status line is repeated once for each dowload thread +and indicates the operation being performed and some usefull information +about what is happening. Sometimes this section will simply read <em>Forking</> +which means the OS is loading the download module. The first word after the [ +is the short form name of the object being downloaded. For archives it will +contain the name of the package that is being fetched. + +<p> +Inside of the single quote is an informative string indicating the progress +of the negotiation phase of the download. Typically it progresses from +<em>Connecting</> to <em>Waiting for file</> to <em>Downloading</> or +<em>Resuming</>. The final value is the number of bytes downloaded from the +remote site. Once the download beings this is represented as <tt>102/10.2k</> +indicating that 102 bytes have been fetched and 10.2 kilobytes is expected. +The total size is always shown in 4 figure notation to preserve space. After +the size display is a percent meter for the file itself. +The second last element is the instantenous average speed. This values is +updated every 5 seconds and reflects the rate of data transfer for that +period. Finally is shown the estimated transfer time. This is updated +regularly and reflects the time to complete everything at the shown +transfer rate. + +<p> +The status display updates every half second to provide a constant feedback +on the download progress while the Get lines scroll back whenever a new +file is started. Since the status display is constantly updated it is +unsuitable for logging to a file, use the <tt>-q</> option to remove the +status display. +</sect> + +<!-- ===================================================================== --> +<sect>Dpkg + +<p> +APT uses <prgn>dpkg</> for installing the archives and will switch +over to the <prgn>dpkg</> interface once downloading is completed. +<prgn>dpkg</> will also as a number of questions as it processes the packages +and the packages themselves may also ask several questions. Before each +question there is usually a description of what it is asking and the +questions are too varied to discuss completely here. +</sect> + +</chapt> + <!-- }}} --> + +</book> diff --git a/doc/sources.list.5 b/doc/sources.list.5 new file mode 100644 index 000000000..779f216bf --- /dev/null +++ b/doc/sources.list.5 @@ -0,0 +1,177 @@ +.\" $Id: sources.list.5,v 1.1 1998/07/02 02:58:12 jgg Exp $
+.\" This manpage is copyright (C) 1998 Branden Robinson <branden@debian.org>.
+.\"
+.\" This is free software; you may redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2,
+.\" or (at your option) any later version.
+.\"
+.\" This is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public
+.\" License along with APT; if not, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+.\" 02111-1307 USA
+.TH sources.list 5 "16 June 1998" "Debian GNU/Linux"
+.SH NAME
+sources.list \- package resource list for APT
+.SH DESCRIPTION
+The package resource list is used to locate archives of the package
+distribution system in use on the system. At this time, this manual page
+documents only the packaging system used by the Debian GNU/Linux system.
+.PP
+The source list is designed to support any number of active sources and a
+variety of source media. The file lists one source per line, with the
+most preferred source listed first. The format of each line is:
+.I type uri args
+The first item,
+.IR type ,
+determines the format for
+.IR args .
+.I uri
+is a Universal Resource Identifier (URI), which is a superset of the more
+specific and well-known Universal Resource Locator, or URL.
+.SS The deb type
+The
+.B deb
+type describes a typical two-level Debian archive,
+.IR distribution / component .
+Typically,
+.I distribution
+is one of
+.BR stable ,
+.BR unstable ,
+or
+.BR frozen ,
+while component is one of
+.BR main ,
+.BR contrib ,
+.BR non-free ,
+or
+.BR non-us .
+The format for a
+.I sources.list
+entry using the
+.B deb
+type is:
+.RS
+deb
+.I uri distribution
+.RI [ component
+.I ...
+]
+.RE
+The URI for the
+.B deb
+type must specify the base of the Debian distribution, from which
+.B APT
+will find the information it needs.
+.I distribution
+can specify an exact path, in which case the
+.IR component s
+must be omitted and
+.I distribution
+must end with a slash (/). This is useful for when only a particular
+sub-section of the archive denoted by the URI is of interest.
+If
+.I distribution
+does not specify an exact path, at least one
+.I component
+must be present.
+.PP
+.I distribution
+may also contain a variable,
+.BR $(ARCH) ,
+which expands to the Debian architecture (i386, m68k, powerpc, ...)
+used on the system. This permits archiecture-independent
+.I sources.list
+files to be used.
+.PP
+Since only one distribution can be specified per line it may be necessary
+to have multiple lines for the same URI, if a subset of all available
+distributions or components at that location is desired.
+.B APT
+will sort the URI list after it has generated a complete set internally,
+and will collapse multiple references to the same Internet host, for
+instance, into a single connection, so that it does not inefficiently
+establish an FTP connection, close it, do something else, and then
+re-establish a connection to that same host. This feature is useful
+for accessing busy FTP sites with limits on the number of simultaneous
+anonymous users.
+.PP
+It is important to list sources in order of preference, with the most
+preferred source listed first. Typically this will result in sorting
+by speed from fastest to slowest (CD-ROM followed by hosts on a local
+network, followed by distant Internet hosts, for example).
+.SS URI specification
+The three currently recognized URI types are file, http, and ftp.
+.IP file
+The file scheme allows an arbitrary directory in the file system to be
+considered an archive. This is useful for NFS mounts and local mirrors or
+archives.
+.IP http
+The http scheme specifies an HTTP server for the archive. If an environment
+variable
+.B $http_proxy
+is set with the format
+.\" Ugly hackery ahead, nroff doesn't like three different typefaces in a
+.\" row with no spaces between anything.
+.BI http:// server : port /\c
+, the proxy server specified in
+.B $http_proxy
+will be used. Users of
+authenticated HTTP/1.1 proxies may use a string of the format
+.BI http:// user : pass @ server : port /\c
+.\" For some reason, starting the next line with \. didn't work. So we kludge.
+\&. Note that this is an insecure method of authentication.
+.IP ftp
+The ftp scheme specifies an FTP server for the archive. APT's FTP behavior
+is highly configurable; for more information see the
+.BR ftp.conf (5)
+manual page.
+.SH EXAMPLES
+.IP "deb file:/home/jason/debian stable main contrib non-free"
+Uses the archive stored locally (or NFS mounted) at
+.I /home/jason/debian
+for stable/main, stable/contrib, and stable/non-free.
+.IP "deb file:/home/jason/debian unstable main contrib non-free"
+As above, except this uses the unstable (development) distribution.
+.IP "deb http://www.debian.org/archive stable main"
+Uses HTTP to access the archive at www.debian.org, and uses only the
+stable/main area.
+.IP "deb ftp://ftp.debian.org/debian stable contrib"
+Uses FTP to access the archive at ftp.debian.org, under the debian
+directory, and uses only the stable/contrib area.
+.IP "deb ftp://ftp.debian.org/debian unstable contrib"
+Uses FTP to access the archive at ftp.debian.org, under the debian
+directory, and uses only the unstable/contrib area. If this line appears as
+well as the one in the previous example in
+.IR sources.list ,
+a single FTP session will be used for both resource lines.
+.IP "deb ftp://nonus.debian.org/debian-non-US unstable/binary-i386/"
+Uses FTP to access the archive at nonus.debian.org, under the debian-non-US
+directory, and uses only files found under unstable/binary-i386.
+.IP "deb http://ftp.de.debian.org/debian-non-US unstable/binary-$(ARCH)/"
+Uses HTTP to access the archive at nonus.debian.org, under the
+debian-non-US directory, and uses only files found under
+unstable/binary-i386 on i386 machines, unstable/binary-m68k on m68k, and so
+forth for other supported architectures.
+.SH SEE ALSO
+.BR apt (8),
+.BR apt-cache (8),
+.BR apt-get (8),
+.BR ftp.conf (5)
+.SH BUGS
+See <http://www.debian.org/Bugs/db/pa/lapt.html>. If you wish to report a
+bug in
+.BR apt-get ,
+please see
+.I /usr/doc/debian/bug-reporting.txt
+or the
+.BR bug (1)
+command.
+.SH AUTHOR
+APT was written by the APT team <apt@packages.debian.org>.
|