0.3.19cnc55-alt3
- Added librpm-4.0.4 build support. - Built with librpm-4.0.4, updated buildrequires.
This commit is contained in:
commit
e3ad0ef694
4
.gear-rules
Normal file
4
.gear-rules
Normal file
@ -0,0 +1,4 @@
|
||||
copy: *.conf
|
||||
copy: *.patch
|
||||
tar.bz2: apt
|
||||
copy: rpmpriorities
|
21
apt-0.3.19cnc32-alt-distro.patch
Normal file
21
apt-0.3.19cnc32-alt-distro.patch
Normal file
@ -0,0 +1,21 @@
|
||||
diff -k.orig -urN apt-0.3.19cnc32/cmdline/apt-cdrom.cc.orig apt-0.3.19cnc32/cmdline/apt-cdrom.cc
|
||||
--- apt-0.3.19cnc32/cmdline/apt-cdrom.cc.orig Thu Jan 4 23:26:14 2001
|
||||
+++ apt-0.3.19cnc32/cmdline/apt-cdrom.cc Mon Jan 22 17:22:32 2001
|
||||
@@ -723,7 +723,7 @@
|
||||
if (0)
|
||||
return _error->Error(_("Unable to locate any package files, perhaps this is not a Debian Disc"));
|
||||
else
|
||||
- return _error->Error(_("Unable to locate any package files, perhaps this is not a Conectiva Disc"));
|
||||
+ return _error->Error(_("Unable to locate any package files, perhaps this is not a ALT Linux Disc"));
|
||||
}
|
||||
// Check if the CD is in the database
|
||||
string Name;
|
||||
@@ -748,7 +748,7 @@
|
||||
if (_config->FindB("APT::CDROM::Rename",false) == true ||
|
||||
Name.empty() == true)
|
||||
{
|
||||
- cout << _("Please provide a name for this Disc, such as 'MyDistro 6.0 Disk 1'");
|
||||
+ cout << _("Please provide a name for this Disc, such as 'Spring 2001 Disk 1'");
|
||||
|
||||
while (1)
|
||||
{
|
11
apt-0.3.19cnc52-alt-INLINEDEPFLAG.patch
Normal file
11
apt-0.3.19cnc52-alt-INLINEDEPFLAG.patch
Normal file
@ -0,0 +1,11 @@
|
||||
--- apt-0.3.19cnc52/buildlib/environment.mak.in.orig Thu Aug 2 01:31:58 2001
|
||||
+++ apt-0.3.19cnc52/buildlib/environment.mak.in Sun Aug 5 13:49:41 2001
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
# Dep generation - this only works for gnu stuff
|
||||
GCC3DEP = @GCC3DEP@
|
||||
-INLINEDEPFLAG = -MD
|
||||
+#INLINEDEPFLAG = -MD
|
||||
|
||||
# Debian doc stuff
|
||||
DEBIANDOC_HTML = @DEBIANDOC_HTML@
|
63
apt-0.3.19cnc53-alt-configure-build.patch
Normal file
63
apt-0.3.19cnc53-alt-configure-build.patch
Normal file
@ -0,0 +1,63 @@
|
||||
diff -ur apt-0.3.19cnc55~/configure.in apt-0.3.19cnc55/configure.in
|
||||
--- apt-0.3.19cnc55~/configure.in Wed Mar 6 20:17:10 2002
|
||||
+++ apt-0.3.19cnc55/configure.in Tue Mar 26 21:14:21 2002
|
||||
@@ -64,20 +64,12 @@
|
||||
dnl AC_MSG_ERROR(failed: I need posix threads, pthread)
|
||||
dnl fi
|
||||
|
||||
-dnl Check for DB2
|
||||
-AC_CHECK_HEADER(db2/db.h,
|
||||
- [AC_CHECK_LIB(db2,db_open,
|
||||
- [AC_DEFINE(HAVE_DB2) DB2LIB="-ldb2"])])
|
||||
-AC_SUBST(DB2LIB)
|
||||
-
|
||||
-
|
||||
dnl Check for rpm version --akk
|
||||
rpm_version="none"
|
||||
SAVE_LIBS="$LIBS"
|
||||
SAVE_CPPFLAGS="$CPPFLAGS"
|
||||
|
||||
CPPFLAGS="$SAVE_CPPFLAGS -I/usr/include/rpm"
|
||||
-AC_CHECK_HEADERS(db1/db.h)
|
||||
AC_CHECK_HEADER(rpm/rpmlib.h, rpm_header_ok=1, rpm_header_ok=0)
|
||||
|
||||
if test $rpm_header_ok = 1; then
|
||||
@@ -85,7 +77,7 @@
|
||||
LIBS="$SAVE_LIBS -lrpm -lrpmio -lz -lbz2 -lpopt"
|
||||
AC_CHECK_LIB(rpmdb,rpmdbOpen,
|
||||
[RPMDBLIBS="-lrpmdb"],
|
||||
- [RPMDBLIBS="-ldb-3.1"])
|
||||
+ [RPMDBLIBS="-ldb"])
|
||||
|
||||
LIBS="$SAVE_LIBS $RPMDBLIBS -lrpmio -lz -lbz2 -lpopt"
|
||||
AC_CHECK_LIB(rpm,rpmdbGetIteratorOffset,
|
||||
@@ -100,6 +92,7 @@
|
||||
[AC_DEFINE_UNQUOTED(HAVE_RPM, 1)
|
||||
RPMLIBS="-lrpm -ldb1 -lz -lbz2 -lpopt"
|
||||
SAVE_CPPFLAGS="$SAVE_CPPFLAGS -I/usr/include/rpm"
|
||||
+ AC_CHECK_HEADERS(db1/db.h)
|
||||
rpm_version="3"])
|
||||
fi
|
||||
fi
|
||||
diff -ur apt-0.3.19cnc55~/tools/cached_md5.cc apt-0.3.19cnc55/tools/cached_md5.cc
|
||||
--- apt-0.3.19cnc55~/tools/cached_md5.cc Sun Feb 17 01:46:11 2002
|
||||
+++ apt-0.3.19cnc55/tools/cached_md5.cc Sun Feb 17 01:46:25 2002
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <rpm/rpmlib.h>
|
||||
+#include <rpm/misc.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
diff -ur apt-0.3.19cnc55~/tools/hdlist2pkglist.cc apt-0.3.19cnc55/tools/hdlist2pkglist.cc
|
||||
--- apt-0.3.19cnc55~/tools/hdlist2pkglist.cc Sun Feb 17 01:46:11 2002
|
||||
+++ apt-0.3.19cnc55/tools/hdlist2pkglist.cc Sun Feb 17 01:46:46 2002
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <rpmlib.h>
|
||||
+#include <rpm/misc.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
11
apt-0.3.19cnc53-alt-strsignal.patch
Normal file
11
apt-0.3.19cnc53-alt-strsignal.patch
Normal file
@ -0,0 +1,11 @@
|
||||
--- apt-0.3.19cnc53/apt-pkg/rpm/rpmpm.cc~ Tue Nov 13 20:32:08 2001
|
||||
+++ apt-0.3.19cnc53/apt-pkg/rpm/rpmpm.cc Fri Nov 16 19:10:19 2001
|
||||
@@ -402,7 +402,7 @@
|
||||
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
|
||||
{
|
||||
if (WIFSIGNALED(Status) != 0)
|
||||
- return _error->Error(_("Sub-process %s terminated by signal (%i)") ,Args[0], WTERMSIG(Status) );
|
||||
+ return _error->Error(_("Sub-process %s terminated by signal (%s)") ,Args[0], strsignal(WTERMSIG(Status)) );
|
||||
|
||||
if (WIFEXITED(Status) != 0)
|
||||
return _error->Error(_("Sub-process %s returned an error code (%u)"),Args[0],
|
47
apt-0.3.19cnc53-stelian-apt-pkg-algorithms-scores.patch
Normal file
47
apt-0.3.19cnc53-stelian-apt-pkg-algorithms-scores.patch
Normal file
@ -0,0 +1,47 @@
|
||||
On Tue, Nov 20, 2001 at 02:28:53PM +0200, Matilainen Panu wrote:
|
||||
|
||||
> > I think this is the same bug (if it's a bug of course).
|
||||
[...]
|
||||
> The sane-split? I got it working by changing sane-frontends to have
|
||||
> Provides: sane = %{version}
|
||||
> and sane-backends
|
||||
> Conflicts: sane < %{version}
|
||||
>
|
||||
> With the additional version information it manages to sort this out
|
||||
> correctly.
|
||||
|
||||
I managed to find a hack permitting this to work without any
|
||||
package modifications: when package scores are calculated
|
||||
(based on package priorities and Depends:), I've added some
|
||||
additionnal code to increment the priority of a package which
|
||||
obsoletes another. This additionnal 'point' score makes the
|
||||
right package to be selected for installation.
|
||||
|
||||
It works for me in simple cases, but it definately needs more
|
||||
testing.
|
||||
|
||||
Comments ?
|
||||
|
||||
Stelian.
|
||||
|
||||
|
||||
--- apt-0.3.19cnc53/apt-pkg/algorithms.cc.orig Wed Nov 21 17:45:34 2001
|
||||
+++ apt-0.3.19cnc53/apt-pkg/algorithms.cc Wed Nov 21 17:46:12 2001
|
||||
@@ -454,6 +454,8 @@
|
||||
{
|
||||
if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
|
||||
Scores[D.TargetPkg()->ID]++;
|
||||
+ if (D->Type == pkgCache::Dep::Obsoletes)
|
||||
+ Scores[I->ID]++;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
Stelian Pop <stelian.pop@fr.alcove.com>
|
||||
|---------------- Free Software Engineer -----------------|
|
||||
| Alcôve - http://www.alcove.com - Tel: +33 1 49 22 68 00 |
|
||||
|------------- Alcôve, liberating software ---------------|
|
||||
_______________________________________________
|
||||
Apt-rpm mailing list
|
||||
Apt-rpm@distro.conectiva.com.br
|
||||
http://distro.conectiva.com.br/mailman/listinfo/apt-rpm
|
18
apt-0.3.19cnc55-alt-AllowedDupPkgs-HoldPkgs.patch
Normal file
18
apt-0.3.19cnc55-alt-AllowedDupPkgs-HoldPkgs.patch
Normal file
@ -0,0 +1,18 @@
|
||||
diff -ur apt-0.3.19cnc55~/apt-pkg/init.cc apt-0.3.19cnc55/apt-pkg/init.cc
|
||||
--- apt-0.3.19cnc55~/apt-pkg/init.cc Thu Aug 2 01:35:12 2001
|
||||
+++ apt-0.3.19cnc55/apt-pkg/init.cc Thu Mar 21 18:47:24 2002
|
||||
@@ -38,12 +38,9 @@
|
||||
Cnf.Set("Dir::State::status","/var/lib/dpkg/status");
|
||||
} else {
|
||||
Cnf.Set("Acquire::cdrom::mount", "/mnt/cdrom");
|
||||
- Cnf.Set("RPM::AllowedDupPkgs::","^kernel$");
|
||||
- Cnf.Set("RPM::AllowedDupPkgs::", "kernel-smp");
|
||||
- Cnf.Set("RPM::AllowedDupPkgs::", "kernel-enterprise");
|
||||
+ Cnf.Set("RPM::AllowedDupPkgs::", "^(NVIDIA_)?(kernel|alsa)[0-9]*($|-up|-smp|-secure|-custom|-enterprise|-BOOT|-tape|-aureal)");
|
||||
|
||||
- Cnf.Set("RPM::HoldPkgs::", "kernel-source");
|
||||
- Cnf.Set("RPM::HoldPkgs::", "kernel-headers");
|
||||
+ Cnf.Set("RPM::HoldPkgs::", "^(kernel|alsa)[0-9]*-source");
|
||||
|
||||
Cnf.Set("Dir::State::status","/var/lib/rpm/status");
|
||||
}
|
56
apt-0.3.19cnc55-alt-apt-pkg-rpmpm-execute_rpm.patch
Normal file
56
apt-0.3.19cnc55-alt-apt-pkg-rpmpm-execute_rpm.patch
Normal file
@ -0,0 +1,56 @@
|
||||
--- apt-0.3.19cnc55~/apt-pkg/rpm/rpmpm.cc Wed Mar 6 20:17:13 2002
|
||||
+++ apt-0.3.19cnc55/apt-pkg/rpm/rpmpm.cc Thu Mar 21 22:35:05 2002
|
||||
@@ -287,14 +287,16 @@
|
||||
case OInstall:
|
||||
options = "-i";
|
||||
|
||||
- Args[n++] = "-i";
|
||||
+ Args[n++] = "-iv";
|
||||
|
||||
Args[n++] = "--replacepkgs";
|
||||
|
||||
if (noninteractive)
|
||||
Args[n++] = "--percent";
|
||||
- else
|
||||
+ else {
|
||||
Args[n++] = "-h";
|
||||
+ Args[n++] = "--fancypercent";
|
||||
+ }
|
||||
|
||||
if (_config->FindB("RPM::Force", false) == true)
|
||||
Args[n++] = "--force";
|
||||
@@ -309,8 +311,10 @@
|
||||
|
||||
if (noninteractive)
|
||||
Args[n++] = "--percent";
|
||||
- else
|
||||
+ else {
|
||||
Args[n++] = "-h";
|
||||
+ Args[n++] = "--fancypercent";
|
||||
+ }
|
||||
|
||||
if (_config->FindB("RPM::Force", false) == true)
|
||||
Args[n++] = "--force";
|
||||
@@ -330,6 +334,13 @@
|
||||
if (nodeps)
|
||||
Args[n++] = "--nodeps";
|
||||
|
||||
+ string cmd;
|
||||
+ for (unsigned i = 0; i < n; ++i)
|
||||
+ {
|
||||
+ if (cmd.length())
|
||||
+ cmd += ' ';
|
||||
+ cmd += Args[i];
|
||||
+ }
|
||||
|
||||
for (slist<char*>::iterator i = files->begin();
|
||||
i != files->end() && n < sizeof(Args);
|
||||
@@ -349,7 +360,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
- cout << _("Executing RPM (")<<options<<")..." << endl;
|
||||
+ cout << _("Executing RPM (") << cmd << ")..." << endl;
|
||||
|
||||
cout << flush;
|
||||
clog << flush;
|
95
apt-0.3.19cnc55-alt-enable-rsh-method.patch
Normal file
95
apt-0.3.19cnc55-alt-enable-rsh-method.patch
Normal file
@ -0,0 +1,95 @@
|
||||
diff -ur apt-0.3.19cnc55/methods/makefile apt-0.3.19cnc53/methods/makefile
|
||||
--- apt-0.3.19cnc55/methods/makefile Fri Aug 10 18:03:50 2001
|
||||
+++ apt-0.3.19cnc53/methods/makefile Thu Mar 21 19:36:03 2002
|
||||
@@ -58,8 +58,8 @@
|
||||
include $(PROGRAM_H)
|
||||
|
||||
# The rsh method
|
||||
-#PROGRAM=rsh
|
||||
-#SLIBS = -lapt-pkg $(SOCKETLIBS) $(RPMLIBS)
|
||||
-#LIB_MAKES = apt-pkg/makefile
|
||||
-#SOURCE = rsh.cc
|
||||
-#include $(PROGRAM_H)
|
||||
+PROGRAM=rsh
|
||||
+SLIBS = -lapt-pkg $(SOCKETLIBS) $(RPMLIBS)
|
||||
+LIB_MAKES = apt-pkg/makefile
|
||||
+SOURCE = rsh.cc
|
||||
+include $(PROGRAM_H)
|
||||
diff -ur apt-0.3.19cnc55/methods/rsh.cc apt-0.3.19cnc53/methods/rsh.cc
|
||||
--- apt-0.3.19cnc55/methods/rsh.cc Fri Nov 30 23:34:13 2001
|
||||
+++ apt-0.3.19cnc53/methods/rsh.cc Thu Mar 21 20:05:08 2002
|
||||
@@ -271,7 +271,7 @@
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool RSHConn::Get(const char *Path,FileFd &To,unsigned long Resume,
|
||||
- Hashes &Hash,bool &Missing, unsigned long Size)
|
||||
+ MD5Summation &MD5,bool &Missing, unsigned long Size)
|
||||
{
|
||||
Missing = false;
|
||||
|
||||
@@ -284,7 +284,7 @@
|
||||
return false;
|
||||
|
||||
if (Resume != 0) {
|
||||
- if (Hash.AddFD(To.Fd(),Resume) == false) {
|
||||
+ if (MD5.AddFD(To.Fd(),Resume) == false) {
|
||||
_error->Errno("read","Problem hashing file");
|
||||
return false;
|
||||
}
|
||||
@@ -323,7 +323,7 @@
|
||||
}
|
||||
MyLen += Res;
|
||||
|
||||
- Hash.Add(Buffer,Res);
|
||||
+ MD5.Add(Buffer,Res);
|
||||
if (To.Write(Buffer,Res) == false)
|
||||
{
|
||||
Close();
|
||||
@@ -428,7 +428,7 @@
|
||||
}
|
||||
|
||||
// Open the file
|
||||
- Hashes Hash;
|
||||
+ MD5Summation MD5;
|
||||
{
|
||||
FileFd Fd(Itm->DestFile,FileFd::WriteAny);
|
||||
if (_error->PendingError() == true)
|
||||
@@ -441,7 +441,7 @@
|
||||
FailFd = Fd.Fd();
|
||||
|
||||
bool Missing;
|
||||
- if (Server->Get(File,Fd,Res.ResumePoint,Hash,Missing,Res.Size) == false)
|
||||
+ if (Server->Get(File,Fd,Res.ResumePoint,MD5,Missing,Res.Size) == false)
|
||||
{
|
||||
Fd.Close();
|
||||
|
||||
@@ -462,7 +462,7 @@
|
||||
}
|
||||
|
||||
Res.LastModified = FailTime;
|
||||
- Res.TakeHashes(Hash);
|
||||
+ Res.MD5Sum = MD5.Result();
|
||||
|
||||
// Timestamp
|
||||
struct utimbuf UBuf;
|
||||
diff -ur apt-0.3.19cnc55/methods/rsh.h apt-0.3.19cnc53/methods/rsh.h
|
||||
--- apt-0.3.19cnc55/methods/rsh.h Fri Nov 30 23:34:13 2001
|
||||
+++ apt-0.3.19cnc53/methods/rsh.h Thu Mar 21 20:05:08 2002
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <apt-pkg/strutl.h>
|
||||
-#include <apt-pkg/hashes.h>
|
||||
+#include <apt-pkg/md5.h>
|
||||
#include <apt-pkg/acquire-method.h>
|
||||
#include <apt-pkg/fileutl.h>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
bool Size(const char *Path,unsigned long &Size);
|
||||
bool ModTime(const char *Path, time_t &Time);
|
||||
bool Get(const char *Path,FileFd &To,unsigned long Resume,
|
||||
- Hashes &Hash,bool &Missing, unsigned long Size);
|
||||
+ MD5Summation &MD5,bool &Missing, unsigned long Size);
|
||||
|
||||
RSHConn(URI Srv);
|
||||
~RSHConn();
|
489
apt-0.3.19cnc55-alt-genbasedir.patch
Normal file
489
apt-0.3.19cnc55-alt-genbasedir.patch
Normal file
@ -0,0 +1,489 @@
|
||||
--- apt-0.3.19cnc55~/tools/genbasedir Wed Mar 6 20:17:13 2002
|
||||
+++ apt-0.3.19cnc55/tools/genbasedir Thu Mar 21 22:15:32 2002
|
||||
@@ -69,99 +69,103 @@
|
||||
# Language setting to generate a consistent pkglist.
|
||||
#
|
||||
|
||||
-usage="\
|
||||
-Usage: genbasedir [<options>] <distribution> <comp1> [<comp2> ... <compN>]\n\
|
||||
-Options:\n\
|
||||
- -s, --sign Generate and sign hashfile\n\
|
||||
- --hashonly Do hashfile stuff only\n\
|
||||
- --listonly Generate pkglists/srclists and quit\n\
|
||||
- --bz2only Generate only compressed lists\n\
|
||||
- --topdir=dir Top directory of repository\n\
|
||||
- --progress Show progress bars for genpkglist/gensrclist\n\
|
||||
- --updateinfo=file Update information file\n"
|
||||
+PROG="${0##*/}"
|
||||
|
||||
basedir=.
|
||||
signature=0
|
||||
listonly=0
|
||||
hashonly=0
|
||||
-updateinfo=""
|
||||
-mapi=0
|
||||
-bz2only=0
|
||||
+updateinfo=
|
||||
+mapi=
|
||||
+gpguid=
|
||||
+topdir=
|
||||
+bz2only=k
|
||||
progress=
|
||||
|
||||
# bloat is necessary for non-Conectiva distros, at least RH,
|
||||
# because they use file dependencies with a non-predictable
|
||||
# heuristic. So we can't strip-off paths that will probably
|
||||
# never appear in dependencies.
|
||||
-bloat=""
|
||||
-
|
||||
+bloat=
|
||||
|
||||
# flat is for repositories where RPMS and SRPMS are kept in the
|
||||
# same directory level.
|
||||
flat=""
|
||||
|
||||
-while test $# -gt 0 ; do
|
||||
- case "${1}" in
|
||||
- -h | --help)
|
||||
- echo -e "${usage}"
|
||||
- exit 0
|
||||
- ;;
|
||||
- --mapi)
|
||||
- # hee hee hee..
|
||||
- mapi=1
|
||||
- ;;
|
||||
- --listonly)
|
||||
- listonly=1
|
||||
- ;;
|
||||
- --hashonly)
|
||||
- hashonly=1
|
||||
- ;;
|
||||
- --bz2only)
|
||||
- bz2only=1
|
||||
- ;;
|
||||
- --updateinfo=*)
|
||||
- updateinfo=${1}
|
||||
- ;;
|
||||
- --bloat)
|
||||
- bloat="--bloat"
|
||||
- ;;
|
||||
- --flat)
|
||||
- flat="--flat"
|
||||
- ;;
|
||||
- --topdir=*)
|
||||
- topdir="`echo \"${1}\" | sed -e 's/^[^=]*=//'`"
|
||||
- if [ ! -d $topdir ]; then
|
||||
- echo "Invalid top directory for distribution ${topdir}" 1>&2
|
||||
- exit 1
|
||||
- fi
|
||||
- ;;
|
||||
- --progress)
|
||||
- progress="--progress"
|
||||
- ;;
|
||||
- -s | --sign)
|
||||
- signature=1;
|
||||
- ;;
|
||||
- -*)
|
||||
- echo -e "${usage}" 1>&2
|
||||
- exit 1
|
||||
- ;;
|
||||
- *)
|
||||
- break
|
||||
- ;;
|
||||
- esac
|
||||
- shift
|
||||
+USAGE()
|
||||
+{
|
||||
+ cat >&2 <<EOF
|
||||
+Usage: genbasedir [<options>] <distribution> <comp1> [<comp2> ... <compN>]
|
||||
+Options:
|
||||
+ -s, --sign Generate and sign hashfile
|
||||
+ --hashonly Do hashfile stuff only
|
||||
+ --listonly Generate pkglists/srclists and quit
|
||||
+ --bz2only Generate only compressed lists
|
||||
+ --topdir=dir Top directory of repository
|
||||
+ --updateinfo=file Update information file
|
||||
+ --bloat Do not strip the package file list. Needed for some
|
||||
+ distributions that use non-automatically generated file dependencies
|
||||
+ --uid=uid Pass different GPG user ID for signing
|
||||
+ --progress Show progress bars for genpkglist/gensrclist
|
||||
+EOF
|
||||
+ [ -n "$1" ] && exit "$1" || exit
|
||||
+}
|
||||
+
|
||||
+TEMP=`getopt -n $PROG -o hs -l help,mapi,listonly,bz2only,hashonly,updateinfo:,bloat,topdir:,sign,uid:,progress -- "$@"` || USAGE
|
||||
+eval set -- "$TEMP"
|
||||
+
|
||||
+while :; do
|
||||
+ case "$1" in
|
||||
+ --listonly) shift; listonly=1
|
||||
+ ;;
|
||||
+ --bz2only) shift; bz2only=
|
||||
+ ;;
|
||||
+ --hashonly) shift; hashonly=1
|
||||
+ ;;
|
||||
+ -s|--sign) shift; signature=1
|
||||
+ ;;
|
||||
+ --bloat) shift; bloat="--bloat"
|
||||
+ ;;
|
||||
+ --mapi) shift; mapi="--mapi"
|
||||
+ ;;
|
||||
+ --updateinfo) shift; updateinfo="$1"; shift
|
||||
+ ;;
|
||||
+ --uid) shift; gpguid="$1"; shift
|
||||
+ ;;
|
||||
+ --topdir) shift; topdir="$1"; shift
|
||||
+ ;;
|
||||
+ --flat) shift; float="--float"
|
||||
+ ;;
|
||||
+ --progress) shift; progress="--progress"
|
||||
+ ;;
|
||||
+ -h|--help) USAGE 0
|
||||
+ ;;
|
||||
+ --) shift; break
|
||||
+ ;;
|
||||
+ *) echo "$PROG: unrecognized option: $1" >&2; exit 1
|
||||
+ ;;
|
||||
+ esac
|
||||
done
|
||||
|
||||
-distro=${1}
|
||||
-shift
|
||||
+topdir="$(echo "$topdir" |sed '
|
||||
+s:/\(\./\)\+:/:g
|
||||
+s:/\+:/:g
|
||||
+s:/$::
|
||||
+')"
|
||||
|
||||
-components=$*
|
||||
+[ -n "$topdir" ] || USAGE 1
|
||||
|
||||
-if [ -z "$components" ]; then
|
||||
- echo -e "${usage}"
|
||||
- exit 0
|
||||
+if [ ! -d "$topdir" ]; then
|
||||
+ echo "Invalid top directory for distribution: $topdir" >&2
|
||||
+ exit 1
|
||||
fi
|
||||
|
||||
+distro=${1}
|
||||
+shift
|
||||
+
|
||||
+components="$*"
|
||||
+
|
||||
+[ -n "$components" ] || USAGE 1
|
||||
|
||||
getsize() {
|
||||
tmp=`wc -c $1`
|
||||
@@ -186,75 +190,88 @@
|
||||
basedir_=`echo ${distro}/base|tr -s /`
|
||||
basedir=${topdir}/$basedir_
|
||||
|
||||
+WORKDIR=
|
||||
+
|
||||
+Exit()
|
||||
+{
|
||||
+ RETVAL=$?
|
||||
+ trap '' EXIT
|
||||
+ [ -z "$WORKDIR" ] || rm -rf "$WORKDIR"
|
||||
+ exit $RETVAL
|
||||
+}
|
||||
+
|
||||
+trap 'Exit ' SIGHUP SIGPIPE SIGINT SIGQUIT SIGTERM EXIT
|
||||
+
|
||||
+WORKDIR="$(mktemp -dt "$PROG.XXXXXXXXXX")"
|
||||
+
|
||||
+SRCIDX_COMP="$WORKDIR/comp"
|
||||
+SRCIDX="$WORKDIR/total"
|
||||
+
|
||||
+saved_list=
|
||||
+
|
||||
+save_file()
|
||||
+{
|
||||
+ saved_list="$1"
|
||||
+
|
||||
+ if [ -f "$saved_list" ]; then
|
||||
+ mv -f "$saved_list" "$saved_list.old"
|
||||
+ else
|
||||
+ saved_list=
|
||||
+ fi
|
||||
+}
|
||||
|
||||
-# release file
|
||||
-# ------------
|
||||
+compare_file()
|
||||
+{
|
||||
+ if [ -n "$saved_list" -a -f "$saved_list.old" ]; then
|
||||
+ if cmp -s "$saved_list.old" "$saved_list"; then
|
||||
+ mv -f "$saved_list.old" "$saved_list"
|
||||
+ else
|
||||
+ rm -f "$saved_list.old"
|
||||
+ fi
|
||||
+ fi
|
||||
+}
|
||||
|
||||
-#for comp in ${components}; do
|
||||
-# true > ${basedir}/release.$comp
|
||||
-#
|
||||
-#done
|
||||
+for comp in ${components}; do
|
||||
+ [ -f "$basedir/release.$comp" ] || touch "$basedir/release.$comp"
|
||||
+done
|
||||
|
||||
|
||||
-if [ $hashonly -ne 1 ]; then
|
||||
+if [ "$hashonly" -ne 1 ]; then
|
||||
# package lists
|
||||
# -------------
|
||||
|
||||
-true > /tmp/srcidx.$$
|
||||
-
|
||||
for comp in ${components}; do
|
||||
echo -n "${comp}: "
|
||||
|
||||
echo -n "pkglist "
|
||||
|
||||
+ newlist="$basedir/pkglist.$comp"
|
||||
+
|
||||
# Save older pkglist
|
||||
- if [ -f $basedir/pkglist.$comp ]; then
|
||||
- mv -f $basedir/pkglist.$comp $basedir/pkglist.$comp.old
|
||||
- fi
|
||||
+ save_file "$newlist"
|
||||
|
||||
- if test x$updateinfo = x; then
|
||||
- (cd $basedir; genpkglist $progress $bloat --index /tmp/srcidx.$comp.$$ $topdir/${distro} $comp)
|
||||
+ :>"$SRCIDX_COMP"
|
||||
+ if [ -z "$updateinfo" ]; then
|
||||
+ (cd "$basedir"; genpkglist $progress $bloat --index "$SRCIDX_COMP" "$topdir/$distro" "$comp")
|
||||
else
|
||||
- (cd $basedir; genpkglist $progress $bloat --index /tmp/srcidx.$comp.$$ --info $updateinfo $topdir/${distro} $comp)
|
||||
+ (cd "$basedir"; genpkglist $progress $bloat --index "$SRCIDX_COMP" --info "$updateinfo" "$topdir/$distro" "$comp")
|
||||
fi
|
||||
+
|
||||
if [ $? -ne 0 ]; then
|
||||
echo
|
||||
echo "Error executing genpkglist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- if [ -f $basedir/pkglist.$comp ]; then
|
||||
-
|
||||
- # Compare with older pkglist.
|
||||
- if [ -f $basedir/pkglist.$comp.old ]; then
|
||||
- if cmp -s $basedir/pkglist.$comp.old $basedir/pkglist.$comp; then
|
||||
- mv -f $basedir/pkglist.$comp.old $basedir/pkglist.$comp
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- # Save older compressed pkglist
|
||||
- if [ -f $basedir/pkglist.$comp.bz2 ]; then
|
||||
- mv -f $basedir/pkglist.$comp.bz2 $basedir/pkglist.$comp.bz2.old
|
||||
- fi
|
||||
-
|
||||
- bzip2 -c $basedir/pkglist.$comp > $basedir/pkglist.$comp.bz2
|
||||
-
|
||||
- # Compare with older compressed pkglist.
|
||||
- if [ -f $basedir/pkglist.$comp.bz2.old ]; then
|
||||
- if cmp -s $basedir/pkglist.$comp.bz2.old $basedir/pkglist.$comp.bz2; then
|
||||
- mv -f $basedir/pkglist.$comp.bz2.old $basedir/pkglist.$comp.bz2
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- if [ $bz2only -eq 1 ]; then
|
||||
- rm -f $basedir/pkglist.$comp
|
||||
- fi
|
||||
+ # Compare with older pkglist.
|
||||
+ compare_file
|
||||
|
||||
- rm -f $basedir/pkglist.$comp.old
|
||||
- rm -f $basedir/pkglist.$comp.bz2.old
|
||||
+ if [ -f "$newlist" ]; then
|
||||
+ rm -f "$newlist.bz2"
|
||||
+ bzip2 -9$bz2only "$newlist"
|
||||
fi
|
||||
|
||||
- cat /tmp/srcidx.$comp.$$ >> /tmp/srcidx.$$
|
||||
+ cat "$SRCIDX_COMP" >> "$SRCIDX"
|
||||
|
||||
echo "done"
|
||||
done
|
||||
@@ -264,77 +281,38 @@
|
||||
|
||||
echo -n "srclist "
|
||||
|
||||
- # Save older srclist
|
||||
- if [ -f $basedir/srclist.$comp ]; then
|
||||
- mv -f $basedir/srclist.$comp $basedir/srclist.$comp.old
|
||||
- fi
|
||||
+ newlist="$basedir/srclist.$comp"
|
||||
|
||||
+ # Save older srclist
|
||||
+ save_file "$newlist"
|
||||
|
||||
- sfix="/.."
|
||||
- if test x$flat != x; then
|
||||
- sfix=""
|
||||
- fi
|
||||
+ :>"$SRCIDX_COMP"
|
||||
+ (cd "$basedir"; gensrclist $progress $flat $mapi "$topdir/$distro/.." "$comp" "$SRCIDX_COMP")
|
||||
|
||||
- if [ $mapi -ne 0 ]; then
|
||||
- (cd $basedir; gensrclist $progress $flat --mapi $topdir/${distro}${sfix} $comp /tmp/srcidx.$comp.$$)
|
||||
- else
|
||||
- (cd $basedir; gensrclist $progress $flat $topdir/${distro}${sfix} $comp /tmp/srcidx.$$)
|
||||
- fi
|
||||
if [ $? -ne 0 ]; then
|
||||
echo
|
||||
echo "Error executing gensrclist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+ # Compare with older srclist.
|
||||
+ compare_file
|
||||
|
||||
-
|
||||
- if [ -f $basedir/srclist.$comp ]; then
|
||||
-
|
||||
- # Compare with older srclist.
|
||||
- if [ -f $basedir/srclist.$comp.old ]; then
|
||||
- if cmp -s $basedir/srclist.$comp.old $basedir/srclist.$comp; then
|
||||
- mv -f $basedir/srclist.$comp.old $basedir/srclist.$comp
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- # Save older compressed srclist
|
||||
- if [ -f $basedir/srclist.$comp.bz2 ]; then
|
||||
- mv -f $basedir/srclist.$comp.bz2 $basedir/srclist.$comp.bz2.old
|
||||
- fi
|
||||
-
|
||||
- bzip2 -c $basedir/srclist.$comp > $basedir/srclist.$comp.bz2
|
||||
-
|
||||
- # Compare with older compressed srclist.
|
||||
- if [ -f $basedir/srclist.$comp.bz2.old ]; then
|
||||
- if cmp -s $basedir/srclist.$comp.bz2.old $basedir/srclist.$comp.bz2; then
|
||||
- mv -f $basedir/srclist.$comp.bz2.old $basedir/srclist.$comp.bz2
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
- if [ $bz2only -eq 1 ]; then
|
||||
- rm -f $basedir/srclist.$comp
|
||||
- fi
|
||||
-
|
||||
- rm -f $basedir/srclist.$comp.old
|
||||
- rm -f $basedir/srclist.$comp.bz2.old
|
||||
+ if [ -f "$newlist" ]; then
|
||||
+ rm -f "$newlist.bz2"
|
||||
+ bzip2 -9$bz2only "$newlist"
|
||||
fi
|
||||
|
||||
- rm -f /tmp/srcidx.$comp.$$
|
||||
-
|
||||
echo "done"
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
-rm -f /tmp/srcidx.$$
|
||||
-
|
||||
-if [ $listonly -eq 0 ]; then
|
||||
+if [ "$listonly" -eq 0 ]; then
|
||||
# Save older hashfile
|
||||
- if [ -f $basedir/hashfile ]; then
|
||||
- mv -f $basedir/hashfile $basedir/hashfile.old
|
||||
- fi
|
||||
+ save_file "$basedir/hashfile"
|
||||
hf=${basedir}/hashfile
|
||||
- true > $hf
|
||||
+ : > $hf
|
||||
else
|
||||
hf=/dev/null
|
||||
fi
|
||||
@@ -348,27 +326,21 @@
|
||||
srclist=${basedir}/srclist
|
||||
release=${basedir}/release
|
||||
|
||||
-for comp in ${components}; do
|
||||
- echo -n "${comp}: "
|
||||
-
|
||||
- echo -n "hashfile "
|
||||
- if [ -f ${pkglist}.$comp ]; then
|
||||
- phashstuff ${pkglist}.$comp ${pkglist_}.$comp >> $hf
|
||||
- fi
|
||||
- if [ -f ${srclist}.$comp ]; then
|
||||
- phashstuff ${srclist}.$comp ${srclist_}.$comp >> $hf
|
||||
- fi
|
||||
+phash()
|
||||
+{
|
||||
+ if [ -f "$1" ]; then
|
||||
+ phashstuff "$1" "$2" >> "$3"
|
||||
+ fi
|
||||
+}
|
||||
|
||||
- if [ -f ${pkglist}.$comp.bz2 ]; then
|
||||
- phashstuff ${pkglist}.$comp.bz2 ${pkglist_}.$comp.bz2 >> $hf
|
||||
- fi
|
||||
- if [ -f ${srclist}.$comp.bz2 ]; then
|
||||
- phashstuff ${srclist}.$comp.bz2 ${srclist_}.$comp.bz2 >> $hf
|
||||
- fi
|
||||
+for comp in ${components}; do
|
||||
+ echo -n "$comp: hashfile "
|
||||
|
||||
- if [ -f ${release}.$comp ]; then
|
||||
- phashstuff ${release}.$comp ${release_}.$comp >> $hf
|
||||
- fi
|
||||
+ phash "$pkglist.$comp" "$pkglist_.$comp" "$hf"
|
||||
+ phash "$srclist.$comp" "$srclist_.$comp" "$hf"
|
||||
+ phash "$pkglist.$comp.bz2" "$pkglist_.$comp.bz2" "$hf"
|
||||
+ phash "$srclist.$comp.bz2" "$srclist_.$comp.bz2" "$hf"
|
||||
+ phash "$release.$comp" "$release_.$comp" "$hf"
|
||||
|
||||
echo "done"
|
||||
done
|
||||
@@ -377,34 +349,26 @@
|
||||
|
||||
if [ $listonly -eq 0 ]; then
|
||||
# Compare with older hashfile.
|
||||
- if [ -f $basedir/hashfile.old ]; then
|
||||
- if cmp -s $basedir/hashfile.old $basedir/hashfile; then
|
||||
- mv -f $basedir/hashfile.old $basedir/hashfile
|
||||
- fi
|
||||
- fi
|
||||
+ compare_file
|
||||
fi
|
||||
|
||||
-if [ $signature -ne 0 -a $listonly -eq 0 ]; then
|
||||
+if [ "$signature" -ne 0 -a "$listonly" -eq 0 ]; then
|
||||
+ if [ -n "$gpguid" ]; then
|
||||
+ DEFAULTKEY="--default-key $gpguid"
|
||||
+ else
|
||||
+ DEFAULTKEY=
|
||||
+ fi
|
||||
|
||||
# Save older hashfile.gpg
|
||||
- if [ -f $basedir/hashfile.gpg ]; then
|
||||
- mv -f $basedir/hashfile.gpg $basedir/hashfile.gpg.old
|
||||
- fi
|
||||
+ save_file "$basedir/hashfile.gpg"
|
||||
|
||||
- gpg -armour -qs --yes $basedir/hashfile
|
||||
- mv -f $basedir/hashfile.asc $basedir/hashfile.gpg
|
||||
- rm -f $basedir/hashfile
|
||||
+ gpg -armour $DEFAULTKEY -qs --yes $basedir/hashfile
|
||||
+ mv -f "$basedir/hashfile.asc" "$basedir/hashfile.gpg"
|
||||
+ rm -f "$basedir/hashfile"
|
||||
|
||||
# Compare with older hashfile.gpg
|
||||
- if [ -f $basedir/hashfile.gpg.old ]; then
|
||||
- if cmp -s $basedir/hashfile.gpg.old $basedir/hashfile.gpg; then
|
||||
- mv -f $basedir/hashfile.gpg.old $basedir/hashfile.gpg
|
||||
- fi
|
||||
- fi
|
||||
+ compare_file
|
||||
fi
|
||||
-
|
||||
-rm -f $basedir/hashfile.old
|
||||
-rm -f $basedir/hashfile.gpg.old
|
||||
|
||||
echo "All your base are belong to us !!"
|
||||
|
36
apt.conf
Normal file
36
apt.conf
Normal file
@ -0,0 +1,36 @@
|
||||
Dir
|
||||
{
|
||||
Bin
|
||||
{
|
||||
Methods "/usr/lib/apt";
|
||||
}
|
||||
}
|
||||
|
||||
APT
|
||||
{
|
||||
Get
|
||||
{
|
||||
Show-Upgraded "true";
|
||||
}
|
||||
|
||||
GPG
|
||||
{
|
||||
PubringPath "/usr/lib/rpm/gnupg";
|
||||
}
|
||||
|
||||
Architecture "i586";
|
||||
}
|
||||
|
||||
Debug
|
||||
{
|
||||
pkgRPMPM "false";
|
||||
}
|
||||
|
||||
Acquire::CDROM::Copy "true";
|
||||
|
||||
RPM
|
||||
{
|
||||
Options "-vv";
|
||||
}
|
||||
|
||||
|
600
apt.spec
Normal file
600
apt.spec
Normal file
@ -0,0 +1,600 @@
|
||||
# hey Emacs, its -*- rpm-spec -*-
|
||||
# $Id: apt,v 1.5 2002/03/13 19:01:26 ab Exp $
|
||||
|
||||
Name: apt
|
||||
Version: 0.3.19cnc55
|
||||
Release: alt3
|
||||
|
||||
Summary: Debian's Advanced Packaging Tool with RPM support
|
||||
Summary(ru_RU.CP1251): Debian APT - Óñîâåðøåíñòâîâàííîå ñðåäñòâî óïðàâëåíèÿ ïàêåòàìè ñ ïîääåðæêîé RPM
|
||||
License: GPL
|
||||
Group: System/Configuration/Packaging
|
||||
Packager: APT Development Team <apt@alt-linux.org>
|
||||
|
||||
Source0: %name-%version.tar.bz2
|
||||
Source1: %name.conf
|
||||
Source2: rpmpriorities
|
||||
|
||||
Patch1: %name-0.3.19cnc32-alt-distro.patch
|
||||
Patch2: %name-0.3.19cnc55-alt-AllowedDupPkgs-HoldPkgs.patch
|
||||
Patch3: %name-0.3.19cnc52-alt-INLINEDEPFLAG.patch
|
||||
Patch4: %name-0.3.19cnc53-alt-configure-build.patch
|
||||
Patch5: %name-0.3.19cnc53-alt-strsignal.patch
|
||||
Patch6: %name-0.3.19cnc55-alt-genbasedir.patch
|
||||
Patch7: %name-0.3.19cnc55-alt-apt-pkg-rpmpm-execute_rpm.patch
|
||||
Patch8: %name-0.3.19cnc53-stelian-apt-pkg-algorithms-scores.patch
|
||||
Patch9: %name-0.3.19cnc55-alt-enable-rsh-method.patch
|
||||
|
||||
Requires: lib%name = %version-%release, mktemp >= 1:1.3.1, getopt
|
||||
Requires: %{get_dep rpm}, gnupg, apt-conf
|
||||
|
||||
BuildPreReq: librpm-devel >= 4.0.4, rpm-build >= 4.0.4
|
||||
|
||||
# Automatically added by buildreq on Tue Mar 26 2002
|
||||
BuildRequires: bison bzlib-devel gcc-c++ libbeecrypt libdb4 libpopt-devel librpm-devel libstdc++-devel openjade perl-SGMLSpm zlib-devel
|
||||
|
||||
%description
|
||||
A port of Debian's APT tools for RPM based distributions,
|
||||
or at least for Conectiva. It provides the %name-get utility that
|
||||
provides a simpler, safer way to install and upgrade packages.
|
||||
APT features complete installation ordering, multiple source
|
||||
capability and several other unique features.
|
||||
|
||||
This package is still under development.
|
||||
|
||||
%define risk_usage Äàííûé ïàêåò ïîêà åùå íàõîäèòñÿ â ñòàäèè ðàçðàáîòêè.
|
||||
|
||||
%description -l ru_RU.CP1251
|
||||
Ïåðåíåñåííûå èç Debian ñðåäñòâà óïðàâëåíèÿ ïàêåòàìè APT, âêëþ÷àþùèå
|
||||
â ñåáÿ ïîääåðæêó RPM, âûïîëíåííóþ êîìïàíèåé Conectiva (Áðàçèëèÿ).
|
||||
Ýòîò ïàêåò ñîäåðæèò óòèëèòó %name-get äëÿ ïðîñòîé è íàäåæíîé óñòàíîâêè
|
||||
è îáíîâëåíèÿ ïàêåòîâ. APT óìååò àâòîìàòè÷åñêè ðàçðåøàòü çàâèñèìîñòè
|
||||
ïðè óñòàíîâêå, îáåñïå÷èâàåò óñòàíîâêó èç íåñêîëüêèõ èñòî÷íèêîâ è
|
||||
öåëûé ðÿä äðóãèõ óíèêàëüíûõ âîçìîæíîñòåé.
|
||||
|
||||
%risk_usage
|
||||
|
||||
%package -n lib%name
|
||||
Summary: APT's lib%name-pkg
|
||||
Group: System/Libraries
|
||||
Conflicts: %name < %version-%release
|
||||
|
||||
%package -n lib%name-devel
|
||||
Summary: Development files and documentation for APT's lib%name-pkg
|
||||
Summary(ru_RU.CP1251): Ôàéëû è äîêóìåíòàöèÿ äëÿ ðàçðàáîò÷èêîâ, èñïîëüçóþùèõ lib%name-pkg
|
||||
Group: Development/C
|
||||
Requires: lib%name = %version-%release
|
||||
Provides: %name-devel = %version
|
||||
Obsoletes: %name-devel lib%name-pkg-devel lib%name-pkg-doc
|
||||
|
||||
%package -n lib%name-devel-static
|
||||
Summary: Development static library for APT's lib%name-pkg
|
||||
Summary(ru_RU.CP1251): Ñòàòè÷åñêàÿ áèáëèîòåêà APT äëÿ ðàçðàáîò÷èêîâ, èñïîëüçóþùèõ lib%name-pkg
|
||||
Group: Development/C
|
||||
Requires: lib%name-devel = %version-%release
|
||||
Provides: %name-devel-static = %version
|
||||
Obsoletes: %name-devel-static
|
||||
|
||||
%description -n lib%name
|
||||
This package contains APT's lib%name-pkg package manipulation library,
|
||||
modified for RPM.
|
||||
|
||||
This package is still under development.
|
||||
|
||||
%description -n lib%name-devel
|
||||
This package contains the header files and libraries for developing with
|
||||
APT's lib%name-pkg package manipulation library, modified for RPM.
|
||||
|
||||
This package is still under development.
|
||||
|
||||
%description -n lib%name-devel-static
|
||||
This package contains static libraries for developing with APT's
|
||||
lib%name-pkg package manipulation library, modified for RPM.
|
||||
|
||||
This package is still under development.
|
||||
|
||||
%description -n lib%name -l ru_RU.CP1251
|
||||
 ýòîì ïàêåòå íàõîäèòñÿ lib%name-pkg -- áèáëèîòåêà óïðàâëåíèÿ ïàêåòàìè
|
||||
èç êîìïëåêòà APT.  îòëè÷èå îò îðèãèíàëüíîé âåðñèè äëÿ Debian, ýòîò
|
||||
ïàêåò ñîäåðæèò ïîääåðæêó äëÿ ôîðìàòà RPM.
|
||||
|
||||
%risk_usage
|
||||
|
||||
%description -n lib%name-devel -l ru_RU.CP1251
|
||||
 ýòîì ïàêåòå íàõîäÿòñÿ çàãîëîâî÷íûå ôàéëû è áèáëèîòåêè äëÿ ðàçðàáîòêè
|
||||
ïðîãðàìì, èñïîëüçóþùèõ lib%name-pkg -- áèáëèîòåêó óïðàâëåíèÿ ïàêåòàìè
|
||||
èç êîìïëåêòà APT.  îòëè÷èå îò îðèãèíàëüíîé âåðñèè äëÿ Debian, ýòîò
|
||||
ïàêåò ñîäåðæèò ïîääåðæêó äëÿ ôîðìàòà RPM.
|
||||
|
||||
%risk_usage
|
||||
|
||||
%description -n lib%name-devel-static -l ru_RU.CP1251
|
||||
 ýòîì ïàêåòå íàõîäÿòñÿ ñòàòè÷åñêèå áèáëèîòåêè äëÿ ðàçðàáîòêè ïðîãðàìì,
|
||||
èñïîëüçóþùèõ lib%name-pkg -- áèáëèîòåêó óïðàâëåíèÿ ïàêåòàìè èç
|
||||
êîìïëåêòà APT.  îòëè÷èå îò îðèãèíàëüíîé âåðñèè äëÿ Debian, ýòîò ïàêåò
|
||||
ñîäåðæèò ïîääåðæêó äëÿ ôîðìàòà RPM.
|
||||
|
||||
%risk_usage
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch8 -p1
|
||||
%patch9 -p1
|
||||
|
||||
#install -p -m644 %SOURCE3 po/ru.po
|
||||
|
||||
%build
|
||||
%add_optflags -fno-exceptions -D_GNU_SOURCE
|
||||
|
||||
libtoolize --copy --force
|
||||
aclocal -I buildlib
|
||||
autoconf
|
||||
|
||||
# BEGIN HACK: fix broken files.
|
||||
%configure --with-proc-multiply=1 --with-procs=%__nprocs
|
||||
for n in LOCALEDIR `sed -ne 's/.*}\(ENABLE\|HAVE\|NEED\)\(_[A-Z_0-9]*\)\$.*/\1\2/pg' config.status |LC_COLLATE=C sort -u`; do
|
||||
%__grep -Fqs "$n" buildlib/config.h.in || echo "#undef $n"
|
||||
done >config.h.add
|
||||
cat config.h.add >>buildlib/config.h.in
|
||||
# END HACK
|
||||
|
||||
%configure --with-proc-multiply=1 --with-procs=%__nprocs
|
||||
|
||||
find -type f -print0 |
|
||||
xargs -r0 %__grep -EZl '/var(/lib)?/state/%name' |
|
||||
xargs -r0 %__perl -pi -e 's,/var(/lib)?/state/%name,%_localstatedir/%name,g'
|
||||
for f in `find -type f -name '*.[58]'`; do
|
||||
[ -f "$f.yo" ] || touch -r "$f" "$f.yo"
|
||||
done
|
||||
%make clean
|
||||
|
||||
%make_build STATICLIBS=1 NOISY=1
|
||||
tar xzf docs.tar.gz
|
||||
bzip2 -9 docs/*.text
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT{%_bindir,%_libdir/%name,%_mandir/man{5,8},%_includedir/%name-pkg,%_sysconfdir/%name}
|
||||
mkdir -p $RPM_BUILD_ROOT%_localstatedir/%name/lists/partial
|
||||
mkdir -p $RPM_BUILD_ROOT/var/cache/%name/{archives/partial,genpkglist,gensrclist}
|
||||
|
||||
cp -a bin/lib*.so* $RPM_BUILD_ROOT%_libdir
|
||||
cp -a bin/lib*.a* $RPM_BUILD_ROOT%_libdir
|
||||
|
||||
install -p -m755 bin/methods/* $RPM_BUILD_ROOT%_libdir/%name
|
||||
install -p -m755 bin/{%name-*,*list} tools/genbasedir $RPM_BUILD_ROOT%_bindir
|
||||
|
||||
install -p -m644 %name-pkg/{,*/}*.h $RPM_BUILD_ROOT%_includedir/%name-pkg
|
||||
|
||||
install -p -m644 doc/*.5 $RPM_BUILD_ROOT%_man5dir/
|
||||
install -p -m644 doc/*.8 $RPM_BUILD_ROOT%_man8dir/
|
||||
|
||||
install -p -m644 %SOURCE1 %SOURCE2 $RPM_BUILD_ROOT%_sysconfdir/%name
|
||||
|
||||
# Make possible SSH method via RSH one.
|
||||
%__ln_s rsh $RPM_BUILD_ROOT%_libdir/%name/ssh
|
||||
|
||||
%make_install install -C po DESTDIR=$RPM_BUILD_ROOT
|
||||
%find_lang %name
|
||||
|
||||
%post -n lib%name -p /sbin/ldconfig
|
||||
%postun -n lib%name -p /sbin/ldconfig
|
||||
|
||||
%files -f %name.lang
|
||||
%_bindir/*
|
||||
%_libdir/%name
|
||||
%dir %_sysconfdir/%name
|
||||
%config(noreplace) %_sysconfdir/%name/%name.conf
|
||||
%config(noreplace) %_sysconfdir/%name/rpmpriorities
|
||||
%_mandir/man?/*
|
||||
%doc README* TODO docs/examples REPOSITORIO-APT-HOWTO
|
||||
|
||||
%defattr(2770,root,rpm,2770)
|
||||
%_localstatedir/%name
|
||||
%_cachedir/%name
|
||||
|
||||
%files -n lib%name
|
||||
%_libdir/*.so.*
|
||||
|
||||
%files -n lib%name-devel
|
||||
%_libdir/*.so
|
||||
%_includedir/*
|
||||
%doc docs/*.{text.*,html}
|
||||
|
||||
%files -n lib%name-devel-static
|
||||
%_libdir/*.a
|
||||
|
||||
%changelog
|
||||
* Tue Mar 26 2002 Dmitry V. Levin <ldv@alt-linux.org> 0.3.19cnc55-alt3
|
||||
- Added librpm-4.0.4 build support.
|
||||
- Built with librpm-4.0.4, updated buildrequires.
|
||||
|
||||
* Thu Mar 21 2002 Dmitry V. Levin <ldv@alt-linux.org> 0.3.19cnc55-alt2
|
||||
- Added kernel-aureal and NVIDIA_kernel to default AllowedDupPkgs.
|
||||
- Updated patch for pkgRPMPM::ExecRPM.
|
||||
- Reenabled rsh method.
|
||||
- Updated rpmpriorities.
|
||||
- fixed genbasedir patch.
|
||||
- Set explicit Packager tag.
|
||||
- Dropped obsolete trigger.
|
||||
- lib%name: Conflicts: %name < %%version-%%release.
|
||||
- Renamed patches.
|
||||
|
||||
* Wed Mar 13 2002 Alexander Bokovoy <ab@altlinux.ru> 0.3.19cnc55-alt1
|
||||
- apt-0.3.19cnc55 integrated
|
||||
- Fixed:
|
||||
+ rpmpm-exec_rpm patch
|
||||
+ genbasedir
|
||||
- Removed:
|
||||
+ rpmpm-nodeps patch (already upstream)
|
||||
+ rsh method (already upstream)
|
||||
|
||||
* Mon Dec 10 2001 Dmitry V. Levin <ldv@alt-linux.org> 0.3.19cnc53-alt6
|
||||
- Fixed rpm --nodeps option usage in pkgRPMPM::ExecRPM (#0000215).
|
||||
|
||||
* Fri Nov 23 2001 Dmitry V. Levin <ldv@alt-linux.org> 0.3.19cnc53-alt5
|
||||
- Applied scoring algorithm patch (Stelian Pop <stelian.pop@fr.alcove.com>)
|
||||
- Updated package requires.
|
||||
|
||||
* Mon Nov 19 2001 Dmitry V. Levin <ldv@alt-linux.org> 0.3.19cnc53-alt4
|
||||
- Dropped outdated pofile (already upstream).
|
||||
- Corrected "Executing RPM" message generation.
|
||||
|
||||
* Fri Nov 16 2001 Dmitry V. Levin <ldv@alt-linux.org> 0.3.19cnc53-alt3
|
||||
- Updated patches: genbasedir, configure-db3, i18n.
|
||||
|
||||
* Wed Nov 15 2001 Alexander Bokovoy <ab@altlinux.ru> 0.3.19cnc53-alt2
|
||||
+ apt-0.3.19cnc53-2cl integrated. Most of our patches moved to upstream
|
||||
- Fixed (from Conectiva's changelog):
|
||||
+ fixed bug in mirror patch
|
||||
+ cleaned up gen{pkg,src}list (Alexander Bokovoy <ab@altlinux.ru
|
||||
+ fixed crash bug in genpkglist
|
||||
+ configure.in patch to detect rpmdb (Stelian Pop <stelian.pop@fr.alcove.com>)
|
||||
+ * Skips correctly over empty package directories
|
||||
+ * Adds the --bz2only argument which makes genbasedir
|
||||
+ to generate only the .bz2 compressed versions of pkglist
|
||||
+ and srclist (space gain...)
|
||||
+ * Doesn't change the timestamps on pkglists/srclists if
|
||||
+ the contents are not modified (making possible for example
|
||||
+ to make several consecutive runs of genbasedir without
|
||||
+ having the apt clients download the indexes again and again).
|
||||
+ * Some minor cleanups (remove the temporary files in /tmp
|
||||
+ at the end of the script etc).
|
||||
+ (Stelian Pop <stelian.pop@fr.alcove.com>)
|
||||
+ cleanup patch for gensrclist (Stelian Pop <stelian.pop@fr.alcove.com>)
|
||||
+ fixed multi-arch pkg handling (Stelian Pop <stelian.pop@fr.alcove.com>)
|
||||
+ updated russian translation (Alexander Bokovoy <ab@altlinux.ru>
|
||||
+ updated i18n (Dmitry Levin <ldv@alt-linux.org>)
|
||||
+ replaced Apt::GPG::Pubring with Apt::GPG::PubringPath
|
||||
also uses --homedir instead of --keyring in gpg
|
||||
(Alexander Bokovoy <ab@altlinux.ru>)
|
||||
+ patch to detect replaced (instead of just removed) packages
|
||||
Dmitry Levin <ldv@alt-linux.org>
|
||||
+ updated mirrors patch
|
||||
+ Fixed mirrors infinite loop bug (closes: #4420).
|
||||
+ Fixed error handling.
|
||||
- Added:
|
||||
+ added kernel-tape to default AllowedDupPkgs
|
||||
+ added patch to fix bug in genbasedir with empty dirs
|
||||
(Stelian Pop <stelian.pop@fr.alcove.com>)
|
||||
+ added -K (RPM::Check-Signatures) option to verify rpm sigs
|
||||
+ Added mirrors patch.
|
||||
|
||||
* Fri Nov 02 2001 Dmitry V. Levin <ldv@alt-linux.org> 0.3.19cnc52-alt6
|
||||
- Initial build with rpm4.
|
||||
|
||||
* Thu Oct 04 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc52-alt5
|
||||
- Fixed i18n support and probably smth else
|
||||
(configure.in, config.h.in and i18n.h were broken, kojima sux).
|
||||
- Implemented 18n for apt-pkg/rpm, updated POTFILES.in and russian translation.
|
||||
|
||||
* Mon Oct 01 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc52-alt4
|
||||
- Removed "^(kernel|alsa)[0-9]*-headers" from RPM::HoldPkgs list.
|
||||
- Added (experimental) replaced packages support.
|
||||
|
||||
* Fri Sep 07 2001 Ivan Zakharyaschev <imz@altlinux.ru> 0.3.19cnc52-alt3.1
|
||||
- apt-cdrom fix (patch 6) reworked: apt-cdrom used to not detect a second
|
||||
list file (srclist) if both (pkglist and srclist) were present in one
|
||||
directory on the disk (in non-thorough mode); hopefully now it works how
|
||||
we expect it to do.
|
||||
|
||||
* Thu Aug 09 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc52-alt3
|
||||
- Libification.
|
||||
- Reworked compilation options again: we add only '-fno-exceptions' now.
|
||||
|
||||
* Tue Aug 07 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc52-alt2
|
||||
- More code cleanup in tools/gen{pkg,src}list.cc.
|
||||
- Added %%optflags_nocpp to compilation options.
|
||||
|
||||
* Mon Aug 06 2001 Alexander Bokovoy <ab@altlinux.ru> 0.3.19cnc52-alt1
|
||||
- cnc52, gcc 3 and Solaris fixes
|
||||
- RPM4 check is disabled for the moment
|
||||
- File method fix has been integrated into mainstream
|
||||
- RPM::RemoveOptions, RPM::UpdateOptions have been added
|
||||
- Generation of Package list fixed
|
||||
|
||||
* Thu Aug 02 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc51-alt4
|
||||
- Added trigger for better apt-conf-* migration.
|
||||
|
||||
* Tue Jul 31 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc51-alt3
|
||||
- Updated:
|
||||
+ rpmpriorities,
|
||||
+ AllowedDupPkgs,
|
||||
+ HoldPkgs.
|
||||
- Moved *.list to apt-conf-* packages.
|
||||
|
||||
* Fri Jul 20 2001 Alexander Bokovoy <ab@altlinux.ru> 0.3.19cnc51-alt2
|
||||
- Fixed:
|
||||
+ Bug in file method which prevented authentication from working correctly
|
||||
|
||||
* Fri Jul 20 2001 Alexander Bokovoy <ab@altlinux.ru> 0.3.19cnc51-alt1
|
||||
- cnc51
|
||||
|
||||
* Wed Jun 27 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc46-alt2
|
||||
- cnc46
|
||||
- kernel(|24)-{headers,source} added to HoldPkgs
|
||||
- REPOSITORIO-APT-HOWTO added (Portugal)
|
||||
- AllowedDupPackages -> AllowedDupPkgs
|
||||
|
||||
* Thu Jun 07 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc38-alt4
|
||||
- Various fixes in %_bindir/genbasedir.
|
||||
|
||||
* Thu May 17 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc38-alt3
|
||||
- Fixed build.
|
||||
- Updated rpmpriorities.
|
||||
|
||||
* Mon Apr 16 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc38-alt2
|
||||
- More duplicate packages from kernel series allowed.
|
||||
|
||||
* Sun Apr 15 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc38-alt1
|
||||
- cnc38
|
||||
- Updated:
|
||||
+ apt-cdrom now works correctly
|
||||
+ default architecture has been changed to i586
|
||||
+ ssh method as wrapper to rsh one
|
||||
|
||||
* Mon Mar 19 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc37-ipl3mdk
|
||||
- Updated:
|
||||
+ New patch for genbasedir to allow pass default key to GnuPG
|
||||
|
||||
* Sun Mar 18 2001 Dmitry V. Levin <ldv@altlinux.ru> 0.3.19cnc37-ipl2mdk
|
||||
- Fixed:
|
||||
+ Build/installation of manpages without yodl sources;
|
||||
+ Uncompressed small patches.
|
||||
- Updated:
|
||||
+ AllowedDupPackages list according to new kernel naming scheme;
|
||||
+ URLs to use new domain name.
|
||||
|
||||
* Sat Mar 17 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc37-ipl1mdk
|
||||
- Fixed:
|
||||
+ APT::GPG::Pubring renamed to APT::GPG::PubringPath
|
||||
+ Pubring support patch changed to use --homedir instead of --keyring
|
||||
- Updated:
|
||||
+ APT cnc37
|
||||
+ Fingerprint and repository sources changed to reflect ALT Linux
|
||||
new public key ring
|
||||
|
||||
* Mon Feb 19 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc36-ipl4mdk
|
||||
- Sisyphus source repository added to sources.list
|
||||
|
||||
* Mon Feb 19 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc36-ipl3mdk
|
||||
- New version
|
||||
|
||||
* Fri Feb 16 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc35-ipl2mdk
|
||||
- Static library compilation added
|
||||
- Static library goes to apt-devel-static due sizes of library
|
||||
|
||||
* Thu Feb 15 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc35-ipl1mdk
|
||||
- New version
|
||||
- Rsh method from upstream apt-get ported
|
||||
- Spec file follows libification of rpm now
|
||||
|
||||
* Mon Jan 22 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc32-ipl4mdk
|
||||
- New upstream version
|
||||
- Russian translation updated
|
||||
- Rebuild with new RPM library
|
||||
|
||||
* Mon Jan 22 2001 Alexander Bokovoy <ab@avilink.net> 0.3.19cnc28-ipl1mdk
|
||||
- New upstream version
|
||||
- cnc28 still lacks correct GNUPG checking code, our patch is neccessary.
|
||||
- Genbasedir slightly patched again.
|
||||
|
||||
* Sun Jan 21 2001 Alexander Bokovoy <ab@avilink.net> ipl11mdk
|
||||
- Typo in methods/gpg.cc fixed.
|
||||
|
||||
* Sun Jan 21 2001 Alexander Bokovoy <ab@avilink.net> ipl10mdk
|
||||
- APT::GPG::Pubring option to specify default gnupg public ring added to check
|
||||
distributors' signs automatically via default pubring in RPM package
|
||||
- ftp user password changed to IPL one.
|
||||
|
||||
* Tue Jan 09 2001 Dmitry V. Levin <ldv@fandra.org> 0.3.19cnc27-ipl7mdk
|
||||
- Specfile cleanup.
|
||||
|
||||
* Mon Jan 08 2001 Alexander Bokovoy <ab@avilink.net> ipl5mdk
|
||||
- genbasedir help message fixed
|
||||
|
||||
* Mon Jan 08 2001 Alexander Bokovoy <ab@avilink.net> ipl4mdk
|
||||
- Integration with main IPL package:
|
||||
- Russian translation for command line messages added
|
||||
- Russian translation of package summary/description
|
||||
|
||||
* Thu Jan 04 2001 AEN <aen@logic.ru>
|
||||
- Real Sisyphus URL & IPLabs Fingerptint added
|
||||
- changed rpmpriorities
|
||||
|
||||
* Thu Jan 04 2001 AEN <aen@logic.ru>
|
||||
- build for RE
|
||||
|
||||
* Tue Dec 12 2000 Frederic Lepied <flepied@mandrakesoft.com> 0.3.19cnc27-1mdk
|
||||
- first mandrake version.
|
||||
|
||||
* Thu Dec 07 2000 Andreas Hasenack <andreas@conectiva.com>
|
||||
- damn! Wrong URL in sources.list, atualizacoes.conectiva.com
|
||||
doesn't exist, of course...
|
||||
|
||||
* Thu Dec 07 2000 Andreas Hasenack <andreas@conectiva.com>
|
||||
- updated sources.list with new mirrors and new download tree
|
||||
- removed (noreplace) for the sources.list file for this
|
||||
upgrade. It will be easier for the user. The (noreplace)
|
||||
should be back in place after this update as we expect no
|
||||
further big modifications for that file, only new mirrors.
|
||||
|
||||
* Wed Dec 06 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- fixed prob in vendors.list
|
||||
|
||||
* Tue Dec 05 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc27
|
||||
|
||||
* Wed Nov 08 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc26
|
||||
|
||||
* Mon Nov 06 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc25
|
||||
|
||||
* Thu Nov 02 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc24
|
||||
|
||||
* Thu Nov 02 2000 Rud<E1> Moura <ruda@conectiva.com>
|
||||
- updated source.list (again)
|
||||
|
||||
* Thu Nov 02 2000 Rud<E1> Moura <ruda@conectiva.com>
|
||||
- updated source.list
|
||||
|
||||
* Wed Nov 01 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc23
|
||||
- added cache directories for gen{pkg,src}list
|
||||
- pt_BR manpages
|
||||
|
||||
* Tue Oct 31 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc22
|
||||
- Requires -> PreReq in apt-devel
|
||||
|
||||
* Mon Oct 30 2000 Alfredo Kojima <kojima@conectiva.com>
|
||||
- collapsed libapt-pkg-devel and -doc to apt-devel
|
||||
|
||||
* Mon Oct 30 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc21
|
||||
|
||||
* Sun Oct 29 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc20
|
||||
|
||||
* Sun Oct 29 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc19
|
||||
- added gensrclist
|
||||
- support for apt-get source
|
||||
|
||||
* Fri Oct 27 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc18
|
||||
|
||||
* Thu Oct 26 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc17
|
||||
- new manpages
|
||||
|
||||
* Wed Oct 25 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc16
|
||||
|
||||
* Sun Oct 22 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc15
|
||||
|
||||
* Sat Oct 21 2000 Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
- released version 0.3.19cnc14
|
||||
|
||||
* Thu Oct 19 2000 Claudio Matsuoka <claudio@conectiva.com>
|
||||
- new upstream release: 0.3.9cnc13
|
||||
|
||||
* Tue Oct 17 2000 Eliphas Levy Theodoro <eliphas@conectiva.com>
|
||||
- added rpmpriorities to filelist and install
|
||||
|
||||
* Tue Oct 17 2000 Claudio Matsuoka <claudio@conectiva.com>
|
||||
- updated to 0.3.19cnc12
|
||||
- fresh CVS snapshot including: support to Acquire::ComprExtension,
|
||||
debug messages removed, fixed apt-cdrom, RPM DB path, rpmlib call
|
||||
in pkgRpmLock::Close(), package priority kludge removed, i18n
|
||||
improvements, and genbasedir/genpkglist updates.
|
||||
- handling language setting in genpkglist to make aptitude happy
|
||||
|
||||
* Wed Oct 11 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc11
|
||||
- fixed problem with shard lib symlinks
|
||||
|
||||
* Tue Oct 10 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc10
|
||||
|
||||
* Mon Oct 2 2000 Claudio Matsuoka <claudio@conectiva.com>
|
||||
- fixed brown paper bag bug with method permissions
|
||||
- added parameter --sign to genbasedir
|
||||
- added html/text doc files
|
||||
|
||||
* Sat Sep 30 2000 Claudio Matsuoka <claudio@conectiva.com>
|
||||
- bumped to 0.3.19cnc9
|
||||
- added vendors.list
|
||||
- added gpg method
|
||||
- fixed minor stuff to make Aptitude work
|
||||
- added missing manpages
|
||||
- fixed shared libs
|
||||
- split in apt, libapt-pkg, libapt-pkg-devel, libapt-pkg-doc
|
||||
- rewrote genbasedir in shell script (original was in TCL)
|
||||
- misc cosmetic changes
|
||||
|
||||
* Tue Sep 26 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc8
|
||||
|
||||
* Wed Sep 20 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc7
|
||||
|
||||
* Mon Sep 18 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc6
|
||||
|
||||
* Sat Sep 16 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc5
|
||||
|
||||
* Fri Sep 15 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc4
|
||||
|
||||
* Mon Sep 12 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- released version 0.3.19cnc3
|
||||
|
||||
* Mon Sep 5 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- renamed package to apt, with version 0.3.19cncV
|
||||
|
||||
* Mon Sep 5 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- 0.10
|
||||
- added genpkglist and rapt-config
|
||||
- program names changed back to apt-*
|
||||
|
||||
* Mon Sep 4 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- 0.9
|
||||
|
||||
* Mon Sep 4 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- 0.8
|
||||
|
||||
* Mon Sep 4 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- 0.7
|
||||
|
||||
* Fri Sep 1 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- fixed typo in sources.list
|
||||
|
||||
* Tue Aug 31 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- version 0.6
|
||||
|
||||
* Tue Aug 31 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- version 0.5
|
||||
|
||||
* Tue Aug 31 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- version 0.4
|
||||
|
||||
* Wed Aug 30 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- version 0.3
|
||||
|
||||
* Thu Aug 28 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- second try. new release with direct hdlist handling
|
||||
|
||||
* Thu Aug 10 2000 Alfredo K. Kojima <kojima@conectiva.com>
|
||||
- initial package creation. Yeah, it's totally broken for sure.
|
||||
|
28
apt/AUTHORS
Normal file
28
apt/AUTHORS
Normal file
@ -0,0 +1,28 @@
|
||||
The project hierachy stands at:
|
||||
|
||||
CVS:jgg Jason Gunthorpe <jgg@debian.org>
|
||||
- Project leader
|
||||
|
||||
CVS:srivasta Manoj Srivastava <srivasta@datasync.com>
|
||||
- Dependency Expert
|
||||
|
||||
CVS:che Ben Gertzfield <che@debian.org>
|
||||
- Packaging and Releases
|
||||
|
||||
CVS:branden Branden Robinson <branden@purdue.edu>
|
||||
- Man Page Documentation
|
||||
|
||||
CVS:doogie Adam Heath <doogie@debian.org>
|
||||
- FTP method author
|
||||
|
||||
Past Contributures:
|
||||
|
||||
Brian White <bcwhite@verisim.com> - Project originator
|
||||
Tom Lees <tom@lpsg.demon.co.uk> - DPKG documentation and ideas
|
||||
Behan Webster <behanw@verisim.com> - Original GUI design
|
||||
Scott Ellis <storm@gate.net> - Original packaging and beta releases
|
||||
Many other bug reports through the Debian Bug system
|
||||
|
||||
NOTE: The ChangeLog generator will parse for names and email addresses. The
|
||||
'CVS:<name>' tag should indicate who this pair refers to.
|
||||
|
15
apt/AUTHORS.RPM
Normal file
15
apt/AUTHORS.RPM
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
RPM port brought to you by
|
||||
Alfredo K. Kojima <kojima@conectiva.com.br>
|
||||
with consulting help from:
|
||||
Packaging: Ruda Moura <ruda@conectiva.com.br>
|
||||
Security: Andreas Hasenack <andreas@conectiva.com.br>
|
||||
Misc.: Claudio Matsuoka <claudio@conectiva.com.br>
|
||||
|
||||
|
||||
added user specified public keyring option for gpg, fixed a bug
|
||||
in the file method with authentication
|
||||
Alexander Bokovoy <ab@avilink.net>
|
||||
|
||||
solaris portability fixes
|
||||
AUSTIN MURPHY <amurphy@nbcs.rutgers.edu>
|
71
apt/COMPILING
Normal file
71
apt/COMPILING
Normal file
@ -0,0 +1,71 @@
|
||||
General Information
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
To compile this you need a couple things
|
||||
- A working POSIX system with working POSIX gcc, g++, make (GNU),
|
||||
ar, sh, awk and sed in the path
|
||||
- GNU Make 3.74 or so, -- normal UNIX make will NOT work
|
||||
* Note 3.77 is broken.
|
||||
- A working ANSI C++ compiler, this is not g++ 2.7.*
|
||||
g++ 2.8 works OK and newer egcs work well also. Nobody has tried it
|
||||
on other compilers :< You will need a properly working STL as well.
|
||||
- A C library with the usual POSIX functions and a BSD socket layer.
|
||||
If you OS conforms to the Single User Spec then you are fine:
|
||||
http://www.opengroup.org/onlinepubs/7908799/index.html
|
||||
|
||||
Guidelines
|
||||
~~~~~~~~~~
|
||||
I am not interested in making 'ultra portable code'. I will accept patches
|
||||
to make the code that already exists conform more to SUS or POSIX, but
|
||||
I don't really care if your not-SUS OS doesn't work. It is simply too
|
||||
much work to maintain patches for dysfunctional OSs. I highly suggest you
|
||||
contact your vendor and express intrest in a conforming C library.
|
||||
|
||||
That said, there are lots of finniky problems that must be delt with even
|
||||
between the supported OS's. Primarily the path I choose to take is to put
|
||||
a shim header file in build/include that transparently adds the required
|
||||
functionality. Patches to make autoconf detect these cases and generate the
|
||||
required shims are OK.
|
||||
|
||||
Current shims:
|
||||
* C9x integer types 'inttypes.h'
|
||||
* sys/statvfs.h to convert from BSD/Linux statfs to SUS statvfs
|
||||
* rfc2553 hostname resolution (methods/rfc*), shims to normal gethostbyname.
|
||||
The more adventerous could steal the KAME IPv6 enabled resolvers for those
|
||||
OS's with IPv6 support but no rfc2553 (why?)
|
||||
* define _XOPEN_EXTENDES_SOURCE to bring in h_errno on HP-UX
|
||||
* socklen_t shim in netdb.h if the OS does not have socklen_t
|
||||
|
||||
The only completely non-shimed OS is Linux with glibc2.1, glibc2.0 requires
|
||||
the first three shims.
|
||||
|
||||
Platform Notes
|
||||
~~~~~~~~~~~~~~
|
||||
Debian GNU Linux 2.1 'slink'
|
||||
Debian GNU Linux 'potato'
|
||||
* All Archs
|
||||
- Works flawlessly
|
||||
- You will want to have debiandoc-sgml and yodl installed to get
|
||||
best results.
|
||||
- No IPv6 Support in glibc's < 2.1.
|
||||
|
||||
Sun Solaris
|
||||
SunOS cab101 5.7 Generic_106541-04 sun4u sparc
|
||||
- Works fine
|
||||
- Note, no IPv6 Support, OS lacks RFC 2553 hostname resolution
|
||||
|
||||
OpenBSD
|
||||
OpenBSD gsb086 2.5 CMPUT#0 i386 unknown
|
||||
- Works fine
|
||||
- OS needs 'ranlib' to generate the symbol table after 'ar'.. (not using
|
||||
GNU ar with the gnu tool chain :<)
|
||||
- Note, no IPv6 Support, OS lacks RFC 2553 hostname resolution
|
||||
|
||||
HP-UX
|
||||
HP-UX nyquist B.10.20 C 9000/780 2016574337 32-user license
|
||||
- Evil OS, does not conform very well to SUS
|
||||
1) snprintf exists but is not prototyped, ignore spurios warnings
|
||||
2) No socklen_t
|
||||
3) Requires -D_XOPEN_SOURCE_EXTENDED for h_errno
|
||||
configure should fix the last two (see above)
|
||||
- Note, no IPv6 Support, OS lacks RFC 2553 hostname resolution
|
||||
|
142
apt/COPYING
Normal file
142
apt/COPYING
Normal file
@ -0,0 +1,142 @@
|
||||
Apt is copyright 1997, 1998, 1999 Jason Gunthorpe and others.
|
||||
|
||||
Apt is licened under the terms of the GNU General Public License (GPL),
|
||||
version 2.0 or later, as published by the Free Software Foundation. See
|
||||
the file COPYING.GPL [included], /usr/share/common-licenses/GPL, or
|
||||
<http://www.gnu.org/copyleft/gpl.txt> for the terms of the latest version
|
||||
of the GNU General Public License.
|
||||
|
||||
In addition, prior to November 15th, 2000, apt may be distributed under
|
||||
terms identical to the above with the following addition:
|
||||
|
||||
Works using apt may link against the GUI library "libqt", copyright by
|
||||
Troll Tech AS, Norway, provided that:
|
||||
|
||||
1. The version of "libqt" is licensed under the terms of the "Qt Free Edition
|
||||
License" published by Troll Tech AS. The license terms identified as
|
||||
the Qt Free Edition License below are the only such terms under which
|
||||
distribution of works derived from both apt and "libqt" are permitted;
|
||||
|
||||
and
|
||||
|
||||
2. The source code of the version of "libqt" used is
|
||||
|
||||
a) Distributed with the binary version;
|
||||
|
||||
or
|
||||
|
||||
b) Downloadable by anyone, without fee, using a publicly-announced
|
||||
URL on the Internet, for a duration of at least three years
|
||||
starting with distribution of the binary version.
|
||||
|
||||
On and after November 15th, 2000, the above additional terms lose all
|
||||
force, and apt will be licensed only under the terms of the GNU General
|
||||
Public License, version 2.0 or later.
|
||||
|
||||
_______________________________________________________________
|
||||
|
||||
The following text, up to the text of the Qt Free Edition License, is
|
||||
informational and not part of the license terms on apt.
|
||||
|
||||
Modifications to apt in either source or compiled form must be licensed
|
||||
under the terms of the GNU General Public License, version 2.0 (or later),
|
||||
but need not include the above clause permitting usage of the "libqt"
|
||||
library under the Qt Free Edition License. Note that removal of this
|
||||
clause will result in software which is not licensed for binary
|
||||
redistribution linked against software governed by the Qt Free Edition
|
||||
License. In the event that a version of "libqt" is released that is
|
||||
licensed under terms that do not conflict with the GPL, the additional
|
||||
clause above is not required to grant permission for distribution of works
|
||||
that are derived from both apt and "libqt".
|
||||
|
||||
No part of apt is licensed under the Qt Free Edition License. The terms
|
||||
below are provided to help identify the circumstances under which the
|
||||
"libqt" library may be used with apt (or a work derived from both). The
|
||||
terms below are copied from the LICENSE file of the qt-1.44 distribution,
|
||||
as of November 10th, 1999.
|
||||
|
||||
_______________________________________________________________
|
||||
|
||||
QT FREE EDITION LICENSE
|
||||
|
||||
Copyright (C) 1992-1999 Troll Tech AS. All rights reserved.
|
||||
|
||||
This is the license for Qt Free Edition version 1.44; it covers private use,
|
||||
use of third-party application programs based on Qt, and development of
|
||||
free software for the free software community.
|
||||
|
||||
|
||||
COPYRIGHT AND RESTRICTIONS
|
||||
|
||||
The Qt toolkit is a product of Troll Tech AS. The Qt Free Edition is limited
|
||||
to use with the X Window System.
|
||||
|
||||
You may copy this version of the Qt Free Edition provided that the entire
|
||||
archive is distributed unchanged and as a whole, including this notice.
|
||||
|
||||
You may use this version of the Qt Free Edition to compile, link and run
|
||||
application programs legally developed by third parties.
|
||||
|
||||
You may use the Qt Free Edition to create application programs
|
||||
provided that:
|
||||
|
||||
You accept this license.
|
||||
Your software does not require modifications to Qt Free Edition.
|
||||
You satisfy ONE of the following three requirements
|
||||
EITHER
|
||||
Users of your software can freely obtain source code for the
|
||||
software, freely modify the source code (possibly with
|
||||
restrictions on copyright notices, attributions and legal
|
||||
responsibility), and freely redistribute original or modified
|
||||
versions of the software.
|
||||
OR
|
||||
Your software is distributed under the GNU GENERAL
|
||||
PUBLIC LICENSE, version 2 or later, as defined by the
|
||||
Free Software Foundation.
|
||||
OR
|
||||
Your software is distributed under the GNU LIBRARY
|
||||
GENERAL PUBLIC LICENSE, version 2 or later, as
|
||||
defined by the Free Software Foundation.
|
||||
|
||||
If you are paid to develop something with Qt Free Edition or it is a part of
|
||||
your job the following conditions also apply:
|
||||
|
||||
Your software must not require libraries, programs, data or
|
||||
documentation that are not available outside your organization in
|
||||
order to compile or use.
|
||||
If and when your organization starts using the software, you must
|
||||
notify Troll Tech AS of the following:
|
||||
Your organization's name and purpose.
|
||||
The software's name and purpose.
|
||||
The software's license.
|
||||
That your organization considers the software to be free
|
||||
software.
|
||||
|
||||
You may also use the Qt Free Edition to create reusable components
|
||||
(such as libraries) provided that you accept the terms above, and in
|
||||
addition that:
|
||||
|
||||
Your components' license includes the following text:
|
||||
|
||||
[Your package] requires the Qt library, which is
|
||||
copyright Troll Tech AS. Freely distributable
|
||||
programs may generally use Qt Free Edition free of
|
||||
charge, see [README.QT] for details.
|
||||
|
||||
README.QT is distributed along with your components.
|
||||
Qt Free Edition is not distributed as an integral part of your
|
||||
components.
|
||||
|
||||
LIMITATIONS OF LIABILITY
|
||||
|
||||
Troll Tech AS makes no obligation under this license to support or
|
||||
upgrade Qt Free Edition, or assist in the use of Qt Free Edition.
|
||||
|
||||
In no event shall Troll Tech AS be liable for any lost revenue or profits or
|
||||
other direct, indirect, special, incidental or consequential damages, even
|
||||
if Troll Tech has been advised of the possibility of such damages.
|
||||
|
||||
QT FREE EDITION IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND,
|
||||
INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE.
|
||||
_______________________________________________________________
|
340
apt/COPYING.GPL
Normal file
340
apt/COPYING.GPL
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can 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 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
30
apt/CVS/Entries
Normal file
30
apt/CVS/Entries
Normal file
@ -0,0 +1,30 @@
|
||||
/AUTHORS.RPM/1.4/Wed Aug 1 21:35:12 2001//
|
||||
/Makefile/1.4/Wed Aug 1 22:05:11 2001//
|
||||
D/apt-pkg////
|
||||
D/buildlib////
|
||||
D/cmdline////
|
||||
D/debian////
|
||||
D/deity////
|
||||
D/doc////
|
||||
D/dselect////
|
||||
D/gui////
|
||||
D/intl////
|
||||
D/methods////
|
||||
D/po////
|
||||
D/test////
|
||||
D/tools////
|
||||
/AUTHORS/1.1.1.1/Fri Aug 10 13:57:00 2001//
|
||||
/COMPILING/1.1.1.1/Fri Aug 10 13:57:00 2001//
|
||||
/COPYING/1.1.1.1/Fri Aug 10 13:57:01 2001//
|
||||
/COPYING.GPL/1.1.1.1/Fri Aug 10 13:57:02 2001//
|
||||
/ChangeLog/1.2/Fri Aug 10 13:57:23 2001//
|
||||
/README.RPM/1.12/Fri Aug 10 13:57:23 2001//
|
||||
/README.make/1.1.1.1/Fri Aug 10 13:57:24 2001//
|
||||
/REPOSITORIO-APT-HOWTO/1.2/Fri Aug 10 13:57:24 2001//
|
||||
/TODO/1.2/Fri Aug 10 13:57:24 2001//
|
||||
/apt.dia/1.3/Fri Aug 10 13:57:26 2001//
|
||||
/docs.tar.gz/1.1/Fri Aug 10 13:58:18 2001//
|
||||
/mkinstalldirs/1.1/Fri Aug 10 13:58:18 2001//
|
||||
/rpmpriorities/1.2/Fri Aug 10 13:58:19 2001//
|
||||
/configure.in/1.75/Wed Mar 6 17:17:10 2002//
|
||||
/release/1.73/Wed Mar 6 17:17:10 2002//
|
1
apt/CVS/Repository
Normal file
1
apt/CVS/Repository
Normal file
@ -0,0 +1 @@
|
||||
rapt
|
1
apt/CVS/Root
Normal file
1
apt/CVS/Root
Normal file
@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs
|
1780
apt/ChangeLog
Normal file
1780
apt/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
28
apt/Makefile
Normal file
28
apt/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- make -*-
|
||||
|
||||
# This is the top level make file for APT, it recurses to each lower
|
||||
# level make file and runs it with the proper target
|
||||
ifndef NOISY
|
||||
.SILENT:
|
||||
endif
|
||||
|
||||
.PHONY: headers library clean veryclean all binary program doc
|
||||
all headers library clean veryclean binary program doc dirs:
|
||||
$(MAKE) -C apt-pkg $@
|
||||
$(MAKE) -C methods $@
|
||||
$(MAKE) -C cmdline $@
|
||||
$(MAKE) -C dselect $@
|
||||
$(MAKE) -C tools $@
|
||||
$(MAKE) -C doc $@
|
||||
|
||||
# Some very common aliases
|
||||
.PHONY: maintainer-clean dist-clean distclean pristine sanity
|
||||
maintainer-clean dist-clean distclean pristine sanity: veryclean
|
||||
|
||||
# The startup target builds the necessary configure scripts. It should
|
||||
# be used after a CVS checkout.
|
||||
CONVERTED=environment.mak include/config.h makefile
|
||||
include buildlib/configure.mak
|
||||
$(BUILDDIR)/include/config.h: buildlib/config.h.in
|
||||
$(BUILDDIR)/environment.mak: buildlib/environment.mak.in
|
||||
$(BUILDDIR)/makefile: buildlib/makefile.in
|
41
apt/README.RPM
Normal file
41
apt/README.RPM
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
RPM enabled APT
|
||||
|
||||
WARNING
|
||||
=======
|
||||
This is an EARLY DEVELOPMENT release of apt-get. It might
|
||||
F*&# UP YOUR SYSTEM BEYOND REPAIR. So use at your own
|
||||
risk etc etc bla bla.
|
||||
|
||||
DO NOT TRY TO COMPILE THIS ON A DEBIAN SYSTEM.
|
||||
THIS IS A WORK IN PROGRESS AND WILL NOT WORK ON DEBIAN
|
||||
RIGHT NOW.
|
||||
|
||||
If you find a problem, contact kojima@conectiva.com.br,
|
||||
not the original developers.
|
||||
|
||||
|
||||
WTF is this??
|
||||
=============
|
||||
|
||||
This is a port of debian's apt tools to RPM based
|
||||
distro (at least Conectiva). apt-get is an advanced
|
||||
package management utility frontend (dpkg in debian,
|
||||
rpm in Conectiva and similars), which allows you to easily
|
||||
perform package installation, upgrading and removal.
|
||||
Dependencies are automatically handled, so if you
|
||||
try to install a package that needs others to be installed,
|
||||
it will download all needed packages and install them.
|
||||
|
||||
|
||||
How to Use It
|
||||
=============
|
||||
|
||||
The manpages are properly updated, but if you
|
||||
want simpler/friendlier documentation, you can
|
||||
get the APT+RPM HOWTO at:
|
||||
http://bazar.conectiva.com.br/~godoy/apt-howto/
|
||||
|
||||
|
||||
|
114
apt/README.make
Normal file
114
apt/README.make
Normal file
@ -0,0 +1,114 @@
|
||||
The Make System
|
||||
~~~ ~~~~ ~~~~~~
|
||||
To compile this program you require GNU Make. In fact you probably need
|
||||
GNU Make 3.76.1 or newer. The makefiles contained make use of many
|
||||
GNU Make specific features and will not run on other makes.
|
||||
|
||||
The make system has a number of interesting properties that are not found
|
||||
in other systems such as automake or the GNU makefile standards. In
|
||||
general some semblance of expectedness is kept so as not to be too
|
||||
surprising. Basically the following will work as expected:
|
||||
|
||||
./configure
|
||||
make
|
||||
or
|
||||
cd build
|
||||
../configure
|
||||
make
|
||||
|
||||
There are a number of other things that are possible that may make software
|
||||
development and software packaging simpler. The first of these is the
|
||||
environment.mak file. When configure is run it creates an environment.mak
|
||||
file in the build directory. This contains -all- configurable parameters
|
||||
for all of the make files in all of the subdirectories. Changing one
|
||||
of these parameters will have an immediate effect. The use of makefile.in
|
||||
and configure substitutions across build makefiles is not used at all.
|
||||
|
||||
Furthermore, the make system runs with a current directory equal to the
|
||||
source directory irregardless of the destination directory. This means
|
||||
#include "" and #include <> work as epected and more importantly
|
||||
running 'make' in the source directory will work as expected. The
|
||||
environment variable or make parameter 'BUILD' set the build directory.
|
||||
It may be an absolute path or a path relative to the top level directory.
|
||||
By default build/ will be used with a fall back to ./ This means
|
||||
you can get all the advantages of a build directory without having to
|
||||
cd into it to edit your source code!
|
||||
|
||||
The make system also performs dependency generation on the fly as the
|
||||
compiler runs. This is extremely fast and accurate. There is however
|
||||
one failure condition that occures when a header file is erased. In
|
||||
this case you should run make clean to purge the .o and .d files to
|
||||
rebuild.
|
||||
|
||||
The final significant deviation from normal make practicies is
|
||||
in how the build directory is managed. It is not mearly a mirror of
|
||||
the source directory but is logically divided in the following manner
|
||||
bin/
|
||||
methods/
|
||||
doc/
|
||||
examples/
|
||||
include/
|
||||
apt-pkg/
|
||||
deity/
|
||||
obj/
|
||||
apt-pkg/
|
||||
deity/
|
||||
cmndline/
|
||||
[...]
|
||||
Only .o and .d files are placed in the obj/ subdirectory. The final compiled
|
||||
binaries are placed in bin, published headers for inter-component linking
|
||||
are placed in include/ and documentation is generated into doc/. This means
|
||||
all runnable programs are within the bin/ directory, a huge benifit for
|
||||
debugging inter-program relationships. The .so files are also placed in
|
||||
bin/ for simplicity.
|
||||
|
||||
By default make is put into silent mode. During operation there should be
|
||||
no shell or compiler messages only status messages from the makefiles,
|
||||
if any pop up that indicates there may be a problem with your environment.
|
||||
For debugging you can disable this by setting NOISY=1, ala
|
||||
make NOISY=1
|
||||
|
||||
Using the makefiles
|
||||
~~~~~ ~~~ ~~~~~~~~~
|
||||
The makefiles for the components are really simple. The complexity is hidden
|
||||
within the buildlib/ directory. Each makefile defines a set of make variables
|
||||
for the bit it is going to make then includes a makefile fragment from
|
||||
the buildlib/. This fragment generates the necessary rules based on the
|
||||
originally defined variables. This process can be repeated as many times as
|
||||
necessary for as many programs or libraries as are in the directory.
|
||||
|
||||
Many of the make fragments have some useful properties involving sub
|
||||
directories and other interesting features. They are more completely
|
||||
described in the fragment code in buildlib. Some tips on writing fragments
|
||||
are included in buildlib/defaults.mak
|
||||
|
||||
The fragments are NEVER processed by configure, so if you make changes to
|
||||
them they will have an immediate effect.
|
||||
|
||||
Autoconf
|
||||
~~~~~~~~
|
||||
Straight out of CVS you have to initialize autoconf. This requires
|
||||
automake (I really don't know why) and autoconf and requires doing
|
||||
aclocal -I buidlib
|
||||
autoconf
|
||||
[Altertatively you can run make startup in the top level build dir]
|
||||
|
||||
Autoconf is configured to do some basic system probes for optional and
|
||||
required functionality and generate an environment.mak and include/config.h
|
||||
from it's findings. It will then write a 'makefile' and run make dirs to
|
||||
create the output directory tree.
|
||||
|
||||
It is not my belief that autoconf should be used to generate substantial
|
||||
source code markup to escape OS problems. If an OS problem does crop up
|
||||
it can likely be corrected by installing the correct files into the
|
||||
build include/ dir and perhaps writing some replacement code and
|
||||
linking it in. To the fullest extent possible the source code should conform
|
||||
to standards and not cater to broken systems.
|
||||
|
||||
Autoconf will also wite a makefile into the top level of the build dir,
|
||||
this simply acts as a wrapper to the main top level make in the source tree.
|
||||
There is one big warning, you can't use both this make file and the
|
||||
ones in the top level tree. Make is not able to resolve rules that
|
||||
go to the same file through different paths and this will confuse the
|
||||
depends mechanism. I recommend always using the makefiles in the
|
||||
source directory and exporting BUILD.
|
117
apt/REPOSITORIO-APT-HOWTO
Normal file
117
apt/REPOSITORIO-APT-HOWTO
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
|
||||
Repositório de APT HOWTO
|
||||
|
||||
|
||||
** Ingredientes
|
||||
|
||||
- 1 máquina com acesso rápido à rede e bastante largura de banda
|
||||
- 1 servidor de ftp (anônimo) ou http rodando
|
||||
|
||||
** Modo de Preparo
|
||||
|
||||
1) Vá ao diretório raiz do servidor de ftp/http
|
||||
2) Crie a seguinte estrutura de diretórios nele:
|
||||
|
||||
<versao>/SRPMS/
|
||||
<versao>/conectiva/RPMS.<comp1>/
|
||||
<versao>/conectiva/RPMS.<comp2>/
|
||||
...
|
||||
<versao>/conectiva/RPMS.<compn>/
|
||||
<versao>/conectiva/base/
|
||||
|
||||
Você pode substituir <versao> pela versão da distribuição
|
||||
que será disponibilizada ou se você estiver disponibilizando
|
||||
algum outro software, a versão da distribuição a que se destinam
|
||||
os pacotes.
|
||||
|
||||
<comp1>...<compn> são os diretórios dos componentes da distribuição
|
||||
e podem ser qualquer string.
|
||||
|
||||
No diretório SRPMS devem estar contidos os srpms dos pacotes
|
||||
do repositório.
|
||||
|
||||
3) Crie os arquivos de índice do apt (os pkglists) no diretório base.
|
||||
Para isso, vá ao diretório base e execute o seguinte comando para
|
||||
cada componente:
|
||||
|
||||
genpkglist <path>/<versao> <comp>
|
||||
|
||||
Onde:
|
||||
|
||||
<path>/<versao> é o caminho completo até o topo do diretório onde
|
||||
está o repositório
|
||||
|
||||
<comp> é o nome do componente.
|
||||
|
||||
Repita a operação para cada um dos componentes que você criou.
|
||||
|
||||
4) Comprima os arquivos de índice com gzip.
|
||||
|
||||
5) Distribua a linha do sources.list para o seu repositório. Ela
|
||||
tem o seguinte formato:
|
||||
|
||||
rpm URL/<path> <versao>/conectiva <comp1> <comp2> ... <compn>
|
||||
^ ^ ^ ^ ^ ^ ^
|
||||
| | | +------+------+-----+- Nomes dos
|
||||
| | | componentes
|
||||
| | |
|
||||
| | versao da distribuição e nome da distribuição
|
||||
| |
|
||||
| URL para o diretório raiz do repositório
|
||||
|
|
||||
Tipo de distribuição. No caso, rpm
|
||||
|
||||
** Exemplos:
|
||||
|
||||
## Quer se fazer um repositório de pacotes para o Conectiva 6.0, na máquina
|
||||
repo.conectiva.com.br, usando http:
|
||||
|
||||
cd /home/httpd
|
||||
mkdir -p coisas/6.0
|
||||
cd coisas/6.0
|
||||
mkdir SRPMS
|
||||
mkdir -p conectiva/RPMS.bla
|
||||
mkdir -p conectiva/base
|
||||
cp /meus/pacotes/*src.rpm SRPMS
|
||||
cp /meus/pacotes/*i386.rpm conectiva/RPMS.bla
|
||||
cd conectiva/base
|
||||
genpkglist /home/httpd/coisas/6.0/conectiva bla
|
||||
gzip pkglist.bla
|
||||
|
||||
Em sources.list deve se adicionar:
|
||||
|
||||
rpm http://repo.conectiva.com.br/coisas 6.0/conectiva bla
|
||||
|
||||
|
||||
## Quer se fazer um repositório de pacotes para a distribuição RedRat 20.0,
|
||||
em bla.redrat.com, usando ftp:
|
||||
|
||||
cd /home/ftp/pub
|
||||
mkdir -p stuff/20.0
|
||||
cd stuff/20.0
|
||||
mkdir SRPMS
|
||||
mkdir -p redrat/RPMS.1
|
||||
mkdir -p redrat/RPMS.2
|
||||
mkdir -p redrat/base
|
||||
cp /tmp/pacotes*src.rpm SRPMS
|
||||
cp <bla bla bla> redrat/RPMS.1
|
||||
cp <bla bla bla> redrat/RPMS.2
|
||||
cd redrat/base
|
||||
genpkglist /home/ftp/stuff/20.0/redrat 1
|
||||
genpkglist /home/ftp/stuff/20.0/redrat 2
|
||||
gzip pkglist.1
|
||||
gzip pkglist.2
|
||||
|
||||
Em sources.list deve se adicionar:
|
||||
|
||||
rpm ftp://bla.redrat.com/pub/stuff 20.0/redrat 1 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
6
apt/TODO
Normal file
6
apt/TODO
Normal file
@ -0,0 +1,6 @@
|
||||
- check support for installation of packages scattered across multiple CDs
|
||||
- port the authentication stuff to the aliencode branch of APT
|
||||
- port the RPM support to the aliencode branch of APT
|
||||
- rewrite rpm repository maintenance tools
|
||||
- package "hold"ing
|
||||
- package ignoring (exclude from apt-get check)
|
43
apt/apt-pkg/CVS/Entries
Normal file
43
apt/apt-pkg/CVS/Entries
Normal file
@ -0,0 +1,43 @@
|
||||
/init.cc/1.16/Wed Aug 1 21:35:12 2001//
|
||||
D/cnc////
|
||||
D/contrib////
|
||||
D/deb////
|
||||
D/rpm////
|
||||
/acquire-method.cc/1.4/Fri Aug 10 13:58:21 2001//
|
||||
/acquire-method.h/1.2/Fri Aug 10 13:58:24 2001//
|
||||
/acquire-worker.cc/1.2/Fri Aug 10 13:58:24 2001//
|
||||
/acquire-worker.h/1.1.1.1/Fri Aug 10 13:58:24 2001//
|
||||
/acquire.cc/1.3/Fri Aug 10 13:58:24 2001//
|
||||
/acquire.h/1.2/Fri Aug 10 13:58:26 2001//
|
||||
/algorithms.h/1.1.1.1/Fri Aug 10 13:58:29 2001//
|
||||
/cachefile.cc/1.8/Fri Aug 10 13:58:29 2001//
|
||||
/cachefile.h/1.4/Fri Aug 10 13:58:29 2001//
|
||||
/cacheiterators.h/1.2/Fri Aug 10 13:58:31 2001//
|
||||
/clean.cc/1.2/Fri Aug 10 13:58:31 2001//
|
||||
/clean.h/1.1.1.1/Fri Aug 10 13:58:31 2001//
|
||||
/init.h/1.1.1.1/Fri Aug 10 13:58:33 2001//
|
||||
/makefile/1.12/Fri Aug 10 13:58:33 2001//
|
||||
/orderlist.cc/1.4/Fri Aug 10 13:58:34 2001//
|
||||
/orderlist.h/1.1.1.1/Fri Aug 10 13:58:34 2001//
|
||||
/packagemanager.h/1.2/Fri Aug 10 13:59:57 2001//
|
||||
/pkgcache.cc/1.11/Fri Aug 10 14:00:19 2001//
|
||||
/pkgcache.h/1.2/Fri Aug 10 14:00:19 2001//
|
||||
/pkgcachegen.h/1.5/Fri Aug 10 14:00:20 2001//
|
||||
/pkgrecords.cc/1.5/Fri Aug 10 14:00:20 2001//
|
||||
/pkgrecords.h/1.3/Fri Aug 10 14:00:20 2001//
|
||||
/srcrecords.cc/1.4/Fri Aug 10 14:00:21 2001//
|
||||
/srcrecords.h/1.2/Fri Aug 10 14:00:21 2001//
|
||||
/systemfactory.cc/1.8/Fri Aug 10 14:00:23 2001//
|
||||
/systemfactory.h/1.5/Fri Aug 10 14:00:23 2001//
|
||||
/tagfile.cc/1.2/Fri Aug 10 14:00:23 2001//
|
||||
/tagfile.h/1.1.1.1/Fri Aug 10 14:00:23 2001//
|
||||
/version.cc/1.4/Fri Aug 10 14:00:23 2001//
|
||||
/acquire-item.cc/1.20/Tue Nov 13 14:24:16 2001//
|
||||
/acquire-item.h/1.6/Tue Nov 13 14:24:16 2001//
|
||||
/sourcelist.cc/1.25/Tue Nov 13 14:24:16 2001//
|
||||
/sourcelist.h/1.9/Tue Nov 13 14:24:16 2001//
|
||||
/algorithms.cc/1.11/Fri Nov 16 01:13:06 2001//
|
||||
/depcache.cc/1.20/Fri Nov 16 01:13:06 2001//
|
||||
/depcache.h/1.3/Fri Nov 16 01:13:06 2001//
|
||||
/packagemanager.cc/1.15/Fri Nov 16 01:13:06 2001//
|
||||
/pkgcachegen.cc/1.24/Wed Mar 6 17:17:10 2002//
|
1
apt/apt-pkg/CVS/Repository
Normal file
1
apt/apt-pkg/CVS/Repository
Normal file
@ -0,0 +1 @@
|
||||
rapt/apt-pkg
|
1
apt/apt-pkg/CVS/Root
Normal file
1
apt/apt-pkg/CVS/Root
Normal file
@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs
|
1016
apt/apt-pkg/acquire-item.cc
Normal file
1016
apt/apt-pkg/acquire-item.cc
Normal file
File diff suppressed because it is too large
Load Diff
200
apt/apt-pkg/acquire-item.h
Normal file
200
apt/apt-pkg/acquire-item.h
Normal file
@ -0,0 +1,200 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: acquire-item.h,v 1.6 2001/11/12 16:34:00 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Acquire Item - Item to acquire
|
||||
|
||||
When an item is instantiated it will add it self to the local list in
|
||||
the Owner Acquire class. Derived classes will then call QueueURI to
|
||||
register all the URI's they wish to fetch at the initial moment.
|
||||
|
||||
Two item classes are provided to provide functionality for downloading
|
||||
of Index files and downloading of Packages.
|
||||
|
||||
A Archive class is provided for downloading .deb files. It does Md5
|
||||
checking and source location as well as a retry algorithm.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_ACQUIRE_ITEM_H
|
||||
#define PKGLIB_ACQUIRE_ITEM_H
|
||||
|
||||
#include <apt-pkg/acquire.h>
|
||||
#include <apt-pkg/sourcelist.h>
|
||||
#include <apt-pkg/pkgrecords.h>
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/acquire-item.h"
|
||||
#endif
|
||||
|
||||
// Item to acquire
|
||||
class pkgAcquire::Item
|
||||
{
|
||||
protected:
|
||||
bool RecheckFile(string path, string MD5, unsigned long Size);
|
||||
|
||||
// Some private helper methods for registering URIs
|
||||
pkgAcquire *Owner;
|
||||
inline void QueueURI(ItemDesc &Item)
|
||||
{Owner->Enqueue(Item);};
|
||||
inline void Dequeue() {Owner->Dequeue(this);};
|
||||
|
||||
// Safe rename function with timestamp preservation
|
||||
void Rename(string From,string To);
|
||||
|
||||
public:
|
||||
|
||||
// State of the item
|
||||
enum {StatIdle, StatFetching, StatDone, StatError, StatAuthError} Status;
|
||||
string ErrorText;
|
||||
unsigned long FileSize;
|
||||
unsigned long PartialSize;
|
||||
char *Mode;
|
||||
unsigned long ID;
|
||||
bool Complete;
|
||||
bool Local;
|
||||
|
||||
// Number of queues we are inserted into
|
||||
unsigned int QueueCounter;
|
||||
|
||||
// File to write the fetch into
|
||||
string DestFile;
|
||||
|
||||
// Action members invoked by the worker
|
||||
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
|
||||
virtual void Done(string Message,unsigned long Size,string Md5Hash,
|
||||
pkgAcquire::MethodConfig *Cnf);
|
||||
virtual void Start(string Message,unsigned long Size);
|
||||
virtual string Custom600Headers() {return string();};
|
||||
virtual string DescURI() = 0;
|
||||
virtual void Finished() {};
|
||||
|
||||
// Inquire functions
|
||||
virtual string MD5Sum() {return string();};
|
||||
pkgAcquire *GetOwner() {return Owner;};
|
||||
|
||||
Item(pkgAcquire *Owner);
|
||||
virtual ~Item();
|
||||
};
|
||||
|
||||
// Item class for index files
|
||||
class pkgAcqIndex : public pkgAcquire::Item
|
||||
{
|
||||
protected:
|
||||
|
||||
const pkgSourceList::Item *Location;
|
||||
bool Decompression;
|
||||
bool Erase;
|
||||
pkgAcquire::ItemDesc Desc;
|
||||
unsigned int Retries;
|
||||
|
||||
public:
|
||||
|
||||
// Specialized action members
|
||||
virtual void Done(string Message,unsigned long Size,string Md5Hash,
|
||||
pkgAcquire::MethodConfig *Cnf);
|
||||
virtual string Custom600Headers();
|
||||
virtual string DescURI() {return Location->PackagesURI();};
|
||||
|
||||
pkgAcqIndex(pkgAcquire *Owner,const pkgSourceList::Item *Location);
|
||||
};
|
||||
|
||||
// Item class for index files
|
||||
class pkgAcqIndexRel : public pkgAcquire::Item
|
||||
{
|
||||
protected:
|
||||
|
||||
const pkgSourceList::Item *Location;
|
||||
pkgAcquire::ItemDesc Desc;
|
||||
unsigned int Retries;
|
||||
|
||||
public:
|
||||
|
||||
// Specialized action members
|
||||
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
|
||||
virtual void Done(string Message,unsigned long Size,string Md5Hash,
|
||||
pkgAcquire::MethodConfig *Cnf);
|
||||
virtual string Custom600Headers();
|
||||
virtual string DescURI() {return Location->ReleaseURI();};
|
||||
|
||||
pkgAcqIndexRel(pkgAcquire *Owner,const pkgSourceList::Item *Location);
|
||||
};
|
||||
|
||||
// Item class for archive files
|
||||
class pkgAcqArchive : public pkgAcquire::Item
|
||||
{
|
||||
protected:
|
||||
|
||||
// State information for the retry mechanism
|
||||
pkgCache::VerIterator Version;
|
||||
pkgAcquire::ItemDesc Desc;
|
||||
pkgSourceList *Sources;
|
||||
pkgRecords *Recs;
|
||||
string MD5;
|
||||
string &StoreFilename;
|
||||
pkgCache::VerFileIterator Vf;
|
||||
unsigned int Retries;
|
||||
|
||||
// Queue the next available file for download.
|
||||
bool QueueNext();
|
||||
|
||||
public:
|
||||
|
||||
// Specialized action members
|
||||
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
|
||||
virtual void Done(string Message,unsigned long Size,string Md5Hash,
|
||||
pkgAcquire::MethodConfig *Cnf);
|
||||
virtual string MD5Sum() {return MD5;};
|
||||
virtual string DescURI() {return Desc.URI;};
|
||||
virtual void Finished();
|
||||
|
||||
pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
|
||||
pkgRecords *Recs,pkgCache::VerIterator const &Version,
|
||||
string &StoreFilename);
|
||||
};
|
||||
|
||||
|
||||
// Item class for index files
|
||||
class pkgAcqHashes : public pkgAcquire::Item
|
||||
{
|
||||
protected:
|
||||
|
||||
bool Authentication;
|
||||
pkgSourceList::RepositoryItem *Location;
|
||||
pkgAcquire::ItemDesc Desc;
|
||||
unsigned int Retries;
|
||||
|
||||
public:
|
||||
|
||||
// Specialized action members
|
||||
virtual void Done(string Message,unsigned long Size,string Md5Hash,
|
||||
pkgAcquire::MethodConfig *Cnf);
|
||||
virtual string DescURI() {return Location->HashesURI();};
|
||||
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
|
||||
|
||||
pkgAcqHashes(pkgAcquire *Owner,
|
||||
pkgSourceList::RepositoryItem *Location);
|
||||
};
|
||||
|
||||
// Fetch a generic file to the current directory
|
||||
class pkgAcqFile : public pkgAcquire::Item
|
||||
{
|
||||
pkgAcquire::ItemDesc Desc;
|
||||
string Md5Hash;
|
||||
unsigned int Retries;
|
||||
|
||||
public:
|
||||
|
||||
// Specialized action members
|
||||
virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
|
||||
virtual void Done(string Message,unsigned long Size,string Md5Hash,
|
||||
pkgAcquire::MethodConfig *Cnf);
|
||||
virtual string MD5Sum() {return Md5Hash;};
|
||||
virtual string DescURI() {return Desc.URI;};
|
||||
|
||||
pkgAcqFile(pkgAcquire *Owner,string URI,string MD5,unsigned long Size,
|
||||
string Desc,string ShortDesc);
|
||||
};
|
||||
|
||||
#endif
|
442
apt/apt-pkg/acquire-method.cc
Normal file
442
apt/apt-pkg/acquire-method.cc
Normal file
@ -0,0 +1,442 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: acquire-method.cc,v 1.4 2001/06/16 01:50:22 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Acquire Method
|
||||
|
||||
This is a skeleton class that implements most of the functionality
|
||||
of a method and some usefull functions to make method implementation
|
||||
simpler. The methods all derive this and specialize it. The most
|
||||
complex implementation is the http method which needs to provide
|
||||
pipelining, it runs the message engine at the same time it is
|
||||
downloading files..
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/acquire-method.h"
|
||||
#endif
|
||||
#include <apt-pkg/acquire-method.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
#include <apt-pkg/fileutl.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
/*}}}*/
|
||||
|
||||
// AcqMethod::pkgAcqMethod - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This constructs the initialization text */
|
||||
pkgAcqMethod::pkgAcqMethod(const char *Ver,unsigned long Flags)
|
||||
{
|
||||
char S[300] = "";
|
||||
char *End = S;
|
||||
strcat(End,"100 Capabilities\n");
|
||||
snprintf(End+strlen(End),sizeof(S),"Version: %s\n",Ver);
|
||||
|
||||
if ((Flags & SingleInstance) == SingleInstance)
|
||||
strcat(End,"Single-Instance: true\n");
|
||||
|
||||
if ((Flags & Pipeline) == Pipeline)
|
||||
strcat(End,"Pipeline: true\n");
|
||||
|
||||
if ((Flags & SendConfig) == SendConfig)
|
||||
strcat(End,"Send-Config: true\n");
|
||||
|
||||
if ((Flags & LocalOnly) == LocalOnly)
|
||||
strcat(End,"Local-Only: true\n");
|
||||
|
||||
if ((Flags & NeedsCleanup) == NeedsCleanup)
|
||||
strcat(End,"Needs-Cleanup: true\n");
|
||||
|
||||
if ((Flags & Removable) == Removable)
|
||||
strcat(End,"Removable: true\n");
|
||||
strcat(End,"\n");
|
||||
|
||||
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
|
||||
exit(100);
|
||||
|
||||
SetNonBlock(STDIN_FILENO,true);
|
||||
|
||||
Queue = 0;
|
||||
QueueBack = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::Fail - A fetch has failed /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcqMethod::Fail(bool Transient)
|
||||
{
|
||||
string Err = "Undetermined Error";
|
||||
if (_error->empty() == false)
|
||||
_error->PopMessage(Err);
|
||||
_error->Discard();
|
||||
Fail(Err,Transient);
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::Fail - A fetch has failed /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcqMethod::Fail(string Err,bool Transient)
|
||||
{
|
||||
// Strip out junk from the error messages
|
||||
for (char *I = Err.begin(); I != Err.end(); I++)
|
||||
{
|
||||
if (*I == '\r')
|
||||
*I = ' ';
|
||||
if (*I == '\n')
|
||||
*I = ' ';
|
||||
}
|
||||
|
||||
char S[1024];
|
||||
if (Queue != 0)
|
||||
{
|
||||
snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: %s\n"
|
||||
"Message: %s\n",Queue->Uri.c_str(),Err.c_str());
|
||||
|
||||
// Dequeue
|
||||
FetchItem *Tmp = Queue;
|
||||
Queue = Queue->Next;
|
||||
delete Tmp;
|
||||
if (Tmp == QueueBack)
|
||||
QueueBack = Queue;
|
||||
}
|
||||
else
|
||||
snprintf(S,sizeof(S)-50,"400 URI Failure\nURI: <UNKNOWN>\n"
|
||||
"Message: %s\n",Err.c_str());
|
||||
|
||||
// Set the transient flag
|
||||
if (Transient == true)
|
||||
strcat(S,"Transient-Failure: true\n\n");
|
||||
else
|
||||
strcat(S,"\n");
|
||||
|
||||
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
|
||||
exit(100);
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::URIStart - Indicate a download is starting /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcqMethod::URIStart(FetchResult &Res)
|
||||
{
|
||||
if (Queue == 0)
|
||||
abort();
|
||||
|
||||
char S[1024] = "";
|
||||
char *End = S;
|
||||
|
||||
End += snprintf(S,sizeof(S),"200 URI Start\nURI: %s\n",Queue->Uri.c_str());
|
||||
if (Res.Size != 0)
|
||||
End += snprintf(End,sizeof(S)-4 - (End - S),"Size: %lu\n",Res.Size);
|
||||
|
||||
if (Res.LastModified != 0)
|
||||
End += snprintf(End,sizeof(S)-4 - (End - S),"Last-Modified: %s\n",
|
||||
TimeRFC1123(Res.LastModified).c_str());
|
||||
|
||||
if (Res.ResumePoint != 0)
|
||||
End += snprintf(End,sizeof(S)-4 - (End - S),"Resume-Point: %lu\n",
|
||||
Res.ResumePoint);
|
||||
|
||||
strcat(End,"\n");
|
||||
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
|
||||
exit(100);
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::URIDone - A URI is finished /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcqMethod::URIDone(FetchResult &Res, FetchResult *Alt)
|
||||
{
|
||||
if (Queue == 0)
|
||||
abort();
|
||||
|
||||
char S[1024] = "";
|
||||
char *End = S;
|
||||
|
||||
End += snprintf(S,sizeof(S),"201 URI Done\nURI: %s\n",Queue->Uri.c_str());
|
||||
|
||||
if (Res.Filename.empty() == false)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Filename: %s\n",Res.Filename.c_str());
|
||||
|
||||
if (Res.Size != 0)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Size: %lu\n",Res.Size);
|
||||
|
||||
if (Res.LastModified != 0)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Last-Modified: %s\n",
|
||||
TimeRFC1123(Res.LastModified).c_str());
|
||||
|
||||
if (Res.MD5Sum.empty() == false)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"MD5-Hash: %s\n",Res.MD5Sum.c_str());
|
||||
|
||||
if (Res.SignatureKeyID.empty() == false)
|
||||
End += snprintf(End,sizeof(S)-80 - (End - S),"Signature-Key: %s\n",
|
||||
Res.SignatureKeyID.c_str());
|
||||
|
||||
if (Res.ResumePoint != 0)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Resume-Point: %lu\n",
|
||||
Res.ResumePoint);
|
||||
|
||||
if (Res.IMSHit == true)
|
||||
strcat(End,"IMS-Hit: true\n");
|
||||
End = S + strlen(S);
|
||||
|
||||
if (Alt != 0)
|
||||
{
|
||||
if (Alt->Filename.empty() == false)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-Filename: %s\n",Alt->Filename.c_str());
|
||||
|
||||
if (Alt->Size != 0)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-Size: %lu\n",Alt->Size);
|
||||
|
||||
if (Alt->LastModified != 0)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-Last-Modified: %s\n",
|
||||
TimeRFC1123(Alt->LastModified).c_str());
|
||||
|
||||
if (Alt->MD5Sum.empty() == false)
|
||||
End += snprintf(End,sizeof(S)-50 - (End - S),"Alt-MD5-Hash: %s\n",
|
||||
Alt->MD5Sum.c_str());
|
||||
|
||||
if (Alt->SignatureKeyID.empty() == false)
|
||||
End += snprintf(End,sizeof(S)-80 - (End - S),"Alt-Signature-Key: %s\n",
|
||||
Alt->SignatureKeyID.c_str());
|
||||
|
||||
if (Alt->IMSHit == true)
|
||||
strcat(End,"Alt-IMS-Hit: true\n");
|
||||
}
|
||||
|
||||
strcat(End,"\n");
|
||||
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
|
||||
exit(100);
|
||||
|
||||
// Dequeue
|
||||
FetchItem *Tmp = Queue;
|
||||
Queue = Queue->Next;
|
||||
delete Tmp;
|
||||
if (Tmp == QueueBack)
|
||||
QueueBack = Queue;
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::MediaFail - Syncronous request for new media /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This sends a 403 Media Failure message to the APT and waits for it
|
||||
to be ackd */
|
||||
bool pkgAcqMethod::MediaFail(string Required,string Drive)
|
||||
{
|
||||
char S[1024];
|
||||
snprintf(S,sizeof(S),"403 Media Failure\nMedia: %s\nDrive: %s\n\n",
|
||||
Required.c_str(),Drive.c_str());
|
||||
|
||||
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
|
||||
exit(100);
|
||||
|
||||
vector<string> MyMessages;
|
||||
|
||||
/* Here we read messages until we find a 603, each non 603 message is
|
||||
appended to the main message list for later processing */
|
||||
while (1)
|
||||
{
|
||||
if (WaitFd(STDIN_FILENO) == false)
|
||||
return false;
|
||||
|
||||
if (ReadMessages(STDIN_FILENO,MyMessages) == false)
|
||||
return false;
|
||||
|
||||
string Message = MyMessages.front();
|
||||
MyMessages.erase(MyMessages.begin());
|
||||
|
||||
// Fetch the message number
|
||||
char *End;
|
||||
int Number = strtol(Message.c_str(),&End,10);
|
||||
if (End == Message.c_str())
|
||||
{
|
||||
cerr << "Malformed message!" << endl;
|
||||
exit(100);
|
||||
}
|
||||
|
||||
// Change ack
|
||||
if (Number == 603)
|
||||
{
|
||||
while (MyMessages.empty() == false)
|
||||
{
|
||||
Messages.push_back(MyMessages.front());
|
||||
MyMessages.erase(MyMessages.begin());
|
||||
}
|
||||
|
||||
return !StringToBool(LookupTag(Message,"Failed"),false);
|
||||
}
|
||||
|
||||
Messages.push_back(Message);
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::Configuration - Handle the configuration message /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This parses each configuration entry and puts it into the _config
|
||||
Configuration class. */
|
||||
bool pkgAcqMethod::Configuration(string Message)
|
||||
{
|
||||
::Configuration &Cnf = *_config;
|
||||
|
||||
const char *I = Message.begin();
|
||||
|
||||
unsigned int Length = strlen("Config-Item");
|
||||
for (; I + Length < Message.end(); I++)
|
||||
{
|
||||
// Not a config item
|
||||
if (I[Length] != ':' || stringcasecmp(I,I+Length,"Config-Item") != 0)
|
||||
continue;
|
||||
|
||||
I += Length + 1;
|
||||
|
||||
for (; I < Message.end() && *I == ' '; I++);
|
||||
const char *Equals = I;
|
||||
for (; Equals < Message.end() && *Equals != '='; Equals++);
|
||||
const char *End = Equals;
|
||||
for (; End < Message.end() && *End != '\n'; End++);
|
||||
if (End == Equals)
|
||||
return false;
|
||||
|
||||
Cnf.Set(DeQuoteString(string(I,Equals-I)),
|
||||
DeQuoteString(string(Equals+1,End-Equals-1)));
|
||||
I = End;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::Run - Run the message engine /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Fetch any messages and execute them. In single mode it returns 1 if
|
||||
there are no more available messages - any other result is a
|
||||
fatal failure code! */
|
||||
int pkgAcqMethod::Run(bool Single)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
// Block if the message queue is empty
|
||||
if (Messages.empty() == true)
|
||||
{
|
||||
if (Single == false)
|
||||
if (WaitFd(STDIN_FILENO) == false)
|
||||
break;
|
||||
if (ReadMessages(STDIN_FILENO,Messages) == false)
|
||||
break;
|
||||
}
|
||||
|
||||
// Single mode exits if the message queue is empty
|
||||
if (Single == true && Messages.empty() == true)
|
||||
return -1;
|
||||
|
||||
string Message = Messages.front();
|
||||
Messages.erase(Messages.begin());
|
||||
|
||||
// Fetch the message number
|
||||
char *End;
|
||||
int Number = strtol(Message.c_str(),&End,10);
|
||||
if (End == Message.c_str())
|
||||
{
|
||||
cerr << "Malformed message!" << endl;
|
||||
return 100;
|
||||
}
|
||||
|
||||
switch (Number)
|
||||
{
|
||||
case 601:
|
||||
if (Configuration(Message) == false)
|
||||
return 100;
|
||||
break;
|
||||
|
||||
case 600:
|
||||
{
|
||||
FetchItem *Tmp = new FetchItem;
|
||||
|
||||
Tmp->Uri = LookupTag(Message,"URI");
|
||||
Tmp->DestFile = LookupTag(Message,"FileName");
|
||||
if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false)
|
||||
Tmp->LastModified = 0;
|
||||
Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false);
|
||||
Tmp->Next = 0;
|
||||
|
||||
// Append it to the list
|
||||
FetchItem **I = &Queue;
|
||||
for (; *I != 0; I = &(*I)->Next);
|
||||
*I = Tmp;
|
||||
if (QueueBack == 0)
|
||||
QueueBack = Tmp;
|
||||
|
||||
// Notify that this item is to be fetched.
|
||||
if (Fetch(Tmp) == false)
|
||||
Fail();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exit();
|
||||
return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::Log - Send a log message /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcqMethod::Log(const char *Format,...)
|
||||
{
|
||||
string CurrentURI = "<UNKNOWN>";
|
||||
if (Queue != 0)
|
||||
CurrentURI = Queue->Uri;
|
||||
|
||||
va_list args;
|
||||
va_start(args,Format);
|
||||
|
||||
// sprintf the description
|
||||
char S[1024];
|
||||
unsigned int Len = snprintf(S,sizeof(S)-4,"101 Log\nURI: %s\n"
|
||||
"Message: ",CurrentURI.c_str());
|
||||
|
||||
vsnprintf(S+Len,sizeof(S)-4-Len,Format,args);
|
||||
strcat(S,"\n\n");
|
||||
|
||||
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
|
||||
exit(100);
|
||||
}
|
||||
/*}}}*/
|
||||
// AcqMethod::Status - Send a status message /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcqMethod::Status(const char *Format,...)
|
||||
{
|
||||
string CurrentURI = "<UNKNOWN>";
|
||||
if (Queue != 0)
|
||||
CurrentURI = Queue->Uri;
|
||||
|
||||
va_list args;
|
||||
va_start(args,Format);
|
||||
|
||||
// sprintf the description
|
||||
char S[1024];
|
||||
unsigned int Len = snprintf(S,sizeof(S)-4,"102 Status\nURI: %s\n"
|
||||
"Message: ",CurrentURI.c_str());
|
||||
|
||||
vsnprintf(S+Len,sizeof(S)-4-Len,Format,args);
|
||||
strcat(S,"\n\n");
|
||||
|
||||
if (write(STDOUT_FILENO,S,strlen(S)) != (signed)strlen(S))
|
||||
exit(100);
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcqMethod::FetchResult::FetchResult() : LastModified(0),
|
||||
IMSHit(false), Size(0), ResumePoint(0)
|
||||
{
|
||||
}
|
||||
/*}}}*/
|
83
apt/apt-pkg/acquire-method.h
Normal file
83
apt/apt-pkg/acquire-method.h
Normal file
@ -0,0 +1,83 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: acquire-method.h,v 1.2 2000/09/26 14:22:14 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Acquire Method - Method helper class + functions
|
||||
|
||||
These functions are designed to be used within the method task to
|
||||
ease communication with APT.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_ACQUIRE_METHOD_H
|
||||
#define PKGLIB_ACQUIRE_METHOD_H
|
||||
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/acquire-method.h"
|
||||
#endif
|
||||
|
||||
class pkgAcqMethod
|
||||
{
|
||||
protected:
|
||||
|
||||
struct FetchItem
|
||||
{
|
||||
FetchItem *Next;
|
||||
|
||||
string Uri;
|
||||
string DestFile;
|
||||
time_t LastModified;
|
||||
bool IndexFile;
|
||||
};
|
||||
|
||||
struct FetchResult
|
||||
{
|
||||
string MD5Sum;
|
||||
string SignatureKeyID;
|
||||
time_t LastModified;
|
||||
bool IMSHit;
|
||||
string Filename;
|
||||
unsigned long Size;
|
||||
unsigned long ResumePoint;
|
||||
FetchResult();
|
||||
};
|
||||
|
||||
// State
|
||||
vector<string> Messages;
|
||||
FetchItem *Queue;
|
||||
FetchItem *QueueBack;
|
||||
|
||||
// Handlers for messages
|
||||
virtual bool Configuration(string Message);
|
||||
virtual bool Fetch(FetchItem * /*Item*/) {return true;};
|
||||
|
||||
// Outgoing messages
|
||||
void Fail(bool Transient = false);
|
||||
inline void Fail(const char *Why, bool Transient = false) {Fail(string(Why),Transient);};
|
||||
void Fail(string Why, bool Transient = false);
|
||||
void URIStart(FetchResult &Res);
|
||||
void URIDone(FetchResult &Res,FetchResult *Alt = 0);
|
||||
bool MediaFail(string Required,string Drive);
|
||||
virtual void Exit() {};
|
||||
|
||||
public:
|
||||
|
||||
enum CnfFlags {SingleInstance = (1<<0),
|
||||
Pipeline = (1<<1), SendConfig = (1<<2),
|
||||
LocalOnly = (1<<3), NeedsCleanup = (1<<4),
|
||||
Removable = (1<<5)};
|
||||
|
||||
void Log(const char *Format,...);
|
||||
void Status(const char *Format,...);
|
||||
|
||||
int Run(bool Single = false);
|
||||
|
||||
pkgAcqMethod(const char *Ver,unsigned long Flags = 0);
|
||||
virtual ~pkgAcqMethod() {};
|
||||
};
|
||||
|
||||
#endif
|
547
apt/apt-pkg/acquire-worker.cc
Normal file
547
apt/apt-pkg/acquire-worker.cc
Normal file
@ -0,0 +1,547 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: acquire-worker.cc,v 1.2 2001/01/11 02:03:26 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Acquire Worker
|
||||
|
||||
The worker process can startup either as a Configuration prober
|
||||
or as a queue runner. As a configuration prober it only reads the
|
||||
configuration message and
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/acquire-worker.h"
|
||||
#endif
|
||||
#include <apt-pkg/acquire-worker.h>
|
||||
#include <apt-pkg/acquire-item.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/fileutl.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <i18n.h>
|
||||
|
||||
/*}}}*/
|
||||
|
||||
// Worker::Worker - Constructor for Queue startup /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf,
|
||||
pkgAcquireStatus *Log) : Log(Log)
|
||||
{
|
||||
OwnerQ = Q;
|
||||
Config = Cnf;
|
||||
Access = Cnf->Access;
|
||||
CurrentItem = 0;
|
||||
TotalSize = 0;
|
||||
CurrentSize = 0;
|
||||
|
||||
Construct();
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::Worker - Constructor for method config startup /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::Worker::Worker(MethodConfig *Cnf)
|
||||
{
|
||||
OwnerQ = 0;
|
||||
Config = Cnf;
|
||||
Access = Cnf->Access;
|
||||
CurrentItem = 0;
|
||||
TotalSize = 0;
|
||||
CurrentSize = 0;
|
||||
|
||||
Construct();
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::Construct - Constructor helper /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcquire::Worker::Construct()
|
||||
{
|
||||
NextQueue = 0;
|
||||
NextAcquire = 0;
|
||||
Process = -1;
|
||||
InFd = -1;
|
||||
OutFd = -1;
|
||||
OutReady = false;
|
||||
InReady = false;
|
||||
Debug = _config->FindB("Debug::pkgAcquire::Worker",false);
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::~Worker - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::Worker::~Worker()
|
||||
{
|
||||
close(InFd);
|
||||
close(OutFd);
|
||||
|
||||
if (Process > 0)
|
||||
{
|
||||
/* Closing of stdin is the signal to exit and die when the process
|
||||
indicates it needs cleanup */
|
||||
if (Config->NeedsCleanup == false)
|
||||
kill(Process,SIGINT);
|
||||
ExecWait(Process,Access.c_str(),true);
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::Start - Start the worker process /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This forks the method and inits the communication channel */
|
||||
bool pkgAcquire::Worker::Start()
|
||||
{
|
||||
// Get the method path
|
||||
string Method = _config->FindDir("Dir::Bin::Methods") + Access;
|
||||
if (FileExists(Method) == false)
|
||||
return _error->Error(_("The method driver %s could not be found."),Method.c_str());
|
||||
|
||||
if (Debug == true)
|
||||
clog << "Starting method '" << Method << '\'' << endl;
|
||||
|
||||
// Create the pipes
|
||||
int Pipes[4] = {-1,-1,-1,-1};
|
||||
if (pipe(Pipes) != 0 || pipe(Pipes+2) != 0)
|
||||
{
|
||||
_error->Errno("pipe",_("Failed to create IPC pipe to subprocess"));
|
||||
for (int I = 0; I != 4; I++)
|
||||
close(Pipes[I]);
|
||||
return false;
|
||||
}
|
||||
for (int I = 0; I != 4; I++)
|
||||
SetCloseExec(Pipes[I],true);
|
||||
|
||||
// Fork off the process
|
||||
Process = ExecFork();
|
||||
|
||||
// Spawn the subprocess
|
||||
if (Process == 0)
|
||||
{
|
||||
// Setup the FDs
|
||||
dup2(Pipes[1],STDOUT_FILENO);
|
||||
dup2(Pipes[2],STDIN_FILENO);
|
||||
dup2(((filebuf *)clog.rdbuf())->fd(),STDERR_FILENO);
|
||||
SetCloseExec(STDOUT_FILENO,false);
|
||||
SetCloseExec(STDIN_FILENO,false);
|
||||
SetCloseExec(STDERR_FILENO,false);
|
||||
|
||||
const char *Args[2];
|
||||
Args[0] = Method.c_str();
|
||||
Args[1] = 0;
|
||||
execv(Args[0],(char **)Args);
|
||||
cerr << "Failed to exec method " << Args[0] << endl;
|
||||
_exit(100);
|
||||
}
|
||||
|
||||
// Fix up our FDs
|
||||
InFd = Pipes[0];
|
||||
OutFd = Pipes[3];
|
||||
SetNonBlock(Pipes[0],true);
|
||||
SetNonBlock(Pipes[3],true);
|
||||
close(Pipes[1]);
|
||||
close(Pipes[2]);
|
||||
OutReady = false;
|
||||
InReady = true;
|
||||
|
||||
// Read the configuration data
|
||||
if (WaitFd(InFd) == false ||
|
||||
ReadMessages() == false)
|
||||
return _error->Error(_("Method %s did not start correctly"),Method.c_str());
|
||||
|
||||
RunMessages();
|
||||
if (OwnerQ != 0)
|
||||
SendConfiguration();
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::ReadMessages - Read all pending messages into the list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgAcquire::Worker::ReadMessages()
|
||||
{
|
||||
if (::ReadMessages(InFd,MessageQueue) == false)
|
||||
return MethodFailure();
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::RunMessage - Empty the message queue /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This takes the messages from the message queue and runs them through
|
||||
the parsers in order. */
|
||||
bool pkgAcquire::Worker::RunMessages()
|
||||
{
|
||||
while (MessageQueue.empty() == false)
|
||||
{
|
||||
string Message = MessageQueue.front();
|
||||
MessageQueue.erase(MessageQueue.begin());
|
||||
|
||||
if (Debug == true)
|
||||
clog << " <- " << Access << ':' << QuoteString(Message,"\n") << endl;
|
||||
|
||||
// Fetch the message number
|
||||
char *End;
|
||||
int Number = strtol(Message.c_str(),&End,10);
|
||||
if (End == Message.c_str())
|
||||
return _error->Error(_("Invalid message from method %s: %s"),Access.c_str(),Message.c_str());
|
||||
|
||||
string URI = LookupTag(Message,"URI");
|
||||
pkgAcquire::Queue::QItem *Itm = 0;
|
||||
if (URI.empty() == false)
|
||||
Itm = OwnerQ->FindItem(URI,this);
|
||||
|
||||
// Determine the message number and dispatch
|
||||
switch (Number)
|
||||
{
|
||||
// 100 Capabilities
|
||||
case 100:
|
||||
if (Capabilities(Message) == false)
|
||||
return _error->Error(_("Unable to process Capabilities message from %s"),Access.c_str());
|
||||
break;
|
||||
|
||||
// 101 Log
|
||||
case 101:
|
||||
if (Debug == true)
|
||||
clog << " <- (log) " << LookupTag(Message,"Message") << endl;
|
||||
break;
|
||||
|
||||
// 102 Status
|
||||
case 102:
|
||||
Status = LookupTag(Message,"Message");
|
||||
break;
|
||||
|
||||
// 200 URI Start
|
||||
case 200:
|
||||
{
|
||||
if (Itm == 0)
|
||||
{
|
||||
_error->Error(_("Method gave invalid 200 URI Start message"));
|
||||
break;
|
||||
}
|
||||
|
||||
CurrentItem = Itm;
|
||||
CurrentSize = 0;
|
||||
TotalSize = atoi(LookupTag(Message,"Size","0").c_str());
|
||||
ResumePoint = atoi(LookupTag(Message,"Resume-Point","0").c_str());
|
||||
Itm->Owner->Start(Message,atoi(LookupTag(Message,"Size","0").c_str()));
|
||||
|
||||
// Display update before completion
|
||||
if (Log != 0 && Log->MorePulses == true)
|
||||
Log->Pulse(Itm->Owner->GetOwner());
|
||||
|
||||
if (Log != 0)
|
||||
Log->Fetch(*Itm);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// 201 URI Done
|
||||
case 201:
|
||||
{
|
||||
if (Itm == 0)
|
||||
{
|
||||
_error->Error("Method gave invalid 201 URI Done message");
|
||||
break;
|
||||
}
|
||||
|
||||
pkgAcquire::Item *Owner = Itm->Owner;
|
||||
pkgAcquire::ItemDesc Desc = *Itm;
|
||||
|
||||
// Display update before completion
|
||||
if (Log != 0 && Log->MorePulses == true)
|
||||
Log->Pulse(Owner->GetOwner());
|
||||
|
||||
OwnerQ->ItemDone(Itm);
|
||||
if (TotalSize != 0 &&
|
||||
(unsigned)atoi(LookupTag(Message,"Size","0").c_str()) != TotalSize)
|
||||
_error->Warning(_("Bizzar Error - File size is not what the server reported %s %u"),
|
||||
LookupTag(Message,"Size","0").c_str(),TotalSize);
|
||||
|
||||
Owner->Done(Message,atoi(LookupTag(Message,"Size","0").c_str()),
|
||||
LookupTag(Message,"MD5-Hash"),Config);
|
||||
ItemDone();
|
||||
|
||||
// Log that we are done
|
||||
if (Log != 0)
|
||||
{
|
||||
if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true ||
|
||||
StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
|
||||
{
|
||||
/* Hide 'hits' for local only sources - we also manage to
|
||||
hide gets */
|
||||
if (Config->LocalOnly == false)
|
||||
Log->IMSHit(Desc);
|
||||
}
|
||||
else
|
||||
Log->Done(Desc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 400 URI Failure
|
||||
case 400:
|
||||
{
|
||||
if (Itm == 0)
|
||||
{
|
||||
_error->Error(_("Method gave invalid 400 URI Failure message"));
|
||||
break;
|
||||
}
|
||||
|
||||
// Display update before completion
|
||||
if (Log != 0 && Log->MorePulses == true)
|
||||
Log->Pulse(Itm->Owner->GetOwner());
|
||||
|
||||
pkgAcquire::Item *Owner = Itm->Owner;
|
||||
pkgAcquire::ItemDesc Desc = *Itm;
|
||||
OwnerQ->ItemDone(Itm);
|
||||
Owner->Failed(Message,Config);
|
||||
ItemDone();
|
||||
|
||||
if (Log != 0)
|
||||
Log->Fail(Desc);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// 401 General Failure
|
||||
case 401:
|
||||
_error->Error(_("Method %s General failure: %s"),LookupTag(Message,"Message").c_str());
|
||||
break;
|
||||
|
||||
// 403 Media Change
|
||||
case 403:
|
||||
MediaChange(Message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::Capabilities - 100 Capabilities handler /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This parses the capabilities message and dumps it into the configuration
|
||||
structure. */
|
||||
bool pkgAcquire::Worker::Capabilities(string Message)
|
||||
{
|
||||
if (Config == 0)
|
||||
return true;
|
||||
|
||||
Config->Version = LookupTag(Message,"Version");
|
||||
Config->SingleInstance = StringToBool(LookupTag(Message,"Single-Instance"),false);
|
||||
Config->Pipeline = StringToBool(LookupTag(Message,"Pipeline"),false);
|
||||
Config->SendConfig = StringToBool(LookupTag(Message,"Send-Config"),false);
|
||||
Config->LocalOnly = StringToBool(LookupTag(Message,"Local-Only"),false);
|
||||
Config->NeedsCleanup = StringToBool(LookupTag(Message,"Needs-Cleanup"),false);
|
||||
Config->Removable = StringToBool(LookupTag(Message,"Removable"),false);
|
||||
|
||||
// Some debug text
|
||||
if (Debug == true)
|
||||
{
|
||||
clog << "Configured access method " << Config->Access << endl;
|
||||
clog << "Version:" << Config->Version <<
|
||||
" SingleInstance:" << Config->SingleInstance <<
|
||||
" Pipeline:" << Config->Pipeline <<
|
||||
" SendConfig:" << Config->SendConfig <<
|
||||
" LocalOnly: " << Config->LocalOnly <<
|
||||
" NeedsCleanup: " << Config->NeedsCleanup <<
|
||||
" Removable: " << Config->Removable << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::MediaChange - Request a media change /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgAcquire::Worker::MediaChange(string Message)
|
||||
{
|
||||
if (Log == 0 || Log->MediaChange(LookupTag(Message,"Media"),
|
||||
LookupTag(Message,"Drive")) == false)
|
||||
{
|
||||
char S[300];
|
||||
sprintf(S,"603 Media Changed\nFailed: true\n\n");
|
||||
if (Debug == true)
|
||||
clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl;
|
||||
OutQueue += S;
|
||||
OutReady = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
char S[300];
|
||||
sprintf(S,"603 Media Changed\n\n");
|
||||
if (Debug == true)
|
||||
clog << " -> " << Access << ':' << QuoteString(S,"\n") << endl;
|
||||
OutQueue += S;
|
||||
OutReady = true;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::SendConfiguration - Send the config to the method /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgAcquire::Worker::SendConfiguration()
|
||||
{
|
||||
if (Config->SendConfig == false)
|
||||
return true;
|
||||
|
||||
if (OutFd == -1)
|
||||
return false;
|
||||
|
||||
string Message = "601 Configuration\n";
|
||||
Message.reserve(2000);
|
||||
|
||||
/* Write out all of the configuration directives by walking the
|
||||
configuration tree */
|
||||
const Configuration::Item *Top = _config->Tree(0);
|
||||
for (; Top != 0;)
|
||||
{
|
||||
if (Top->Value.empty() == false)
|
||||
{
|
||||
string Line = "Config-Item: " + Top->FullTag() + "=";
|
||||
Line += QuoteString(Top->Value,"\n") + '\n';
|
||||
Message += Line;
|
||||
}
|
||||
|
||||
if (Top->Child != 0)
|
||||
{
|
||||
Top = Top->Child;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (Top != 0 && Top->Next == 0)
|
||||
Top = Top->Parent;
|
||||
if (Top != 0)
|
||||
Top = Top->Next;
|
||||
}
|
||||
Message += '\n';
|
||||
|
||||
if (Debug == true)
|
||||
clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl;
|
||||
OutQueue += Message;
|
||||
OutReady = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::QueueItem - Add an item to the outbound queue /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Send a URI Acquire message to the method */
|
||||
bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
|
||||
{
|
||||
if (OutFd == -1)
|
||||
return false;
|
||||
|
||||
string Message = "600 URI Acquire\n";
|
||||
Message.reserve(300);
|
||||
Message += "URI: " + Item->URI;
|
||||
Message += "\nFilename: " + Item->Owner->DestFile;
|
||||
Message += Item->Owner->Custom600Headers();
|
||||
Message += "\n\n";
|
||||
|
||||
if (Debug == true)
|
||||
clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl;
|
||||
OutQueue += Message;
|
||||
OutReady = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::OutFdRead - Out bound FD is ready /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgAcquire::Worker::OutFdReady()
|
||||
{
|
||||
int Res;
|
||||
do
|
||||
{
|
||||
Res = write(OutFd,OutQueue.begin(),OutQueue.length());
|
||||
}
|
||||
while (Res < 0 && errno == EINTR);
|
||||
|
||||
if (Res <= 0)
|
||||
return MethodFailure();
|
||||
|
||||
// Hmm.. this should never happen.
|
||||
if (Res < 0)
|
||||
return true;
|
||||
|
||||
OutQueue.erase(0,Res);
|
||||
if (OutQueue.empty() == true)
|
||||
OutReady = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::InFdRead - In bound FD is ready /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgAcquire::Worker::InFdReady()
|
||||
{
|
||||
if (ReadMessages() == false)
|
||||
return false;
|
||||
RunMessages();
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::MethodFailure - Called when the method fails /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called when the method is belived to have failed, probably because
|
||||
read returned -1. */
|
||||
bool pkgAcquire::Worker::MethodFailure()
|
||||
{
|
||||
_error->Error(_("Method %s has died unexpectedly!"),Access.c_str());
|
||||
|
||||
ExecWait(Process,Access.c_str(),true);
|
||||
Process = -1;
|
||||
close(InFd);
|
||||
close(OutFd);
|
||||
InFd = -1;
|
||||
OutFd = -1;
|
||||
OutReady = false;
|
||||
InReady = false;
|
||||
OutQueue = string();
|
||||
MessageQueue.erase(MessageQueue.begin(),MessageQueue.end());
|
||||
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::Pulse - Called periodically /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcquire::Worker::Pulse()
|
||||
{
|
||||
if (CurrentItem == 0)
|
||||
return;
|
||||
|
||||
struct stat Buf;
|
||||
if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0)
|
||||
return;
|
||||
CurrentSize = Buf.st_size;
|
||||
|
||||
// Hmm? Should not happen...
|
||||
if (CurrentSize > TotalSize && TotalSize != 0)
|
||||
TotalSize = CurrentSize;
|
||||
}
|
||||
/*}}}*/
|
||||
// Worker::ItemDone - Called when the current item is finished /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcquire::Worker::ItemDone()
|
||||
{
|
||||
CurrentItem = 0;
|
||||
CurrentSize = 0;
|
||||
TotalSize = 0;
|
||||
Status = string();
|
||||
}
|
||||
/*}}}*/
|
89
apt/apt-pkg/acquire-worker.h
Normal file
89
apt/apt-pkg/acquire-worker.h
Normal file
@ -0,0 +1,89 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: acquire-worker.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Acquire Worker - Worker process manager
|
||||
|
||||
Each worker class is associated with exaclty one subprocess.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_ACQUIRE_WORKER_H
|
||||
#define PKGLIB_ACQUIRE_WORKER_H
|
||||
|
||||
#include <apt-pkg/acquire.h>
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/acquire-worker.h"
|
||||
#endif
|
||||
|
||||
// Interfacing to the method process
|
||||
class pkgAcquire::Worker
|
||||
{
|
||||
friend pkgAcquire;
|
||||
|
||||
protected:
|
||||
friend Queue;
|
||||
|
||||
/* Linked list starting at a Queue and a linked list starting
|
||||
at Acquire */
|
||||
Worker *NextQueue;
|
||||
Worker *NextAcquire;
|
||||
|
||||
// The access association
|
||||
Queue *OwnerQ;
|
||||
pkgAcquireStatus *Log;
|
||||
MethodConfig *Config;
|
||||
string Access;
|
||||
|
||||
// This is the subprocess IPC setup
|
||||
pid_t Process;
|
||||
int InFd;
|
||||
int OutFd;
|
||||
bool InReady;
|
||||
bool OutReady;
|
||||
|
||||
// Various internal things
|
||||
bool Debug;
|
||||
vector<string> MessageQueue;
|
||||
string OutQueue;
|
||||
|
||||
// Private constructor helper
|
||||
void Construct();
|
||||
|
||||
// Message handling things
|
||||
bool ReadMessages();
|
||||
bool RunMessages();
|
||||
bool InFdReady();
|
||||
bool OutFdReady();
|
||||
|
||||
// The message handlers
|
||||
bool Capabilities(string Message);
|
||||
bool SendConfiguration();
|
||||
bool MediaChange(string Message);
|
||||
|
||||
bool MethodFailure();
|
||||
void ItemDone();
|
||||
|
||||
public:
|
||||
|
||||
// The curent method state
|
||||
pkgAcquire::Queue::QItem *CurrentItem;
|
||||
string Status;
|
||||
unsigned long CurrentSize;
|
||||
unsigned long TotalSize;
|
||||
unsigned long ResumePoint;
|
||||
|
||||
// Load the method and do the startup
|
||||
bool QueueItem(pkgAcquire::Queue::QItem *Item);
|
||||
bool Start();
|
||||
void Pulse();
|
||||
inline const MethodConfig *GetConf() const {return Config;};
|
||||
|
||||
Worker(Queue *OwnerQ,MethodConfig *Config,pkgAcquireStatus *Log);
|
||||
Worker(MethodConfig *Config);
|
||||
~Worker();
|
||||
};
|
||||
|
||||
#endif
|
842
apt/apt-pkg/acquire.cc
Normal file
842
apt/apt-pkg/acquire.cc
Normal file
@ -0,0 +1,842 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: acquire.cc,v 1.3 2001/06/16 01:50:22 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Acquire - File Acquiration
|
||||
|
||||
The core element for the schedual system is the concept of a named
|
||||
queue. Each queue is unique and each queue has a name derived from the
|
||||
URI. The degree of paralization can be controled by how the queue
|
||||
name is derived from the URI.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/acquire.h"
|
||||
#endif
|
||||
#include <apt-pkg/acquire.h>
|
||||
#include <apt-pkg/acquire-item.h>
|
||||
#include <apt-pkg/acquire-worker.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <i18n.h>
|
||||
|
||||
/*}}}*/
|
||||
|
||||
// Acquire::pkgAcquire - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We grab some runtime state from the configuration space */
|
||||
pkgAcquire::pkgAcquire(pkgAcquireStatus *Log) : Log(Log)
|
||||
{
|
||||
Queues = 0;
|
||||
Configs = 0;
|
||||
Workers = 0;
|
||||
ToFetch = 0;
|
||||
Running = false;
|
||||
|
||||
string Mode = _config->Find("Acquire::Queue-Mode","host");
|
||||
if (strcasecmp(Mode.c_str(),"host") == 0)
|
||||
QueueMode = QueueHost;
|
||||
if (strcasecmp(Mode.c_str(),"access") == 0)
|
||||
QueueMode = QueueAccess;
|
||||
|
||||
Debug = _config->FindB("Debug::pkgAcquire",false);
|
||||
|
||||
// This is really a stupid place for this
|
||||
struct stat St;
|
||||
if (stat((_config->FindDir("Dir::State::lists") + "partial/").c_str(),&St) != 0 ||
|
||||
S_ISDIR(St.st_mode) == 0)
|
||||
_error->Error(_("Lists directory %spartial is missing."),
|
||||
_config->FindDir("Dir::State::lists").c_str());
|
||||
if (stat((_config->FindDir("Dir::Cache::Archives") + "partial/").c_str(),&St) != 0 ||
|
||||
S_ISDIR(St.st_mode) == 0)
|
||||
_error->Error(_("Archive directory %spartial is missing."),
|
||||
_config->FindDir("Dir::Cache::Archives").c_str());
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::~pkgAcquire - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Free our memory, clean up the queues (destroy the workers) */
|
||||
pkgAcquire::~pkgAcquire()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
while (Configs != 0)
|
||||
{
|
||||
MethodConfig *Jnk = Configs;
|
||||
Configs = Configs->Next;
|
||||
delete Jnk;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Shutdown - Clean out the acquire object /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcquire::Shutdown()
|
||||
{
|
||||
while (Items.size() != 0)
|
||||
delete Items[0];
|
||||
|
||||
while (Queues != 0)
|
||||
{
|
||||
Queue *Jnk = Queues;
|
||||
Queues = Queues->Next;
|
||||
delete Jnk;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Add - Add a new item /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This puts an item on the acquire list. This list is mainly for tracking
|
||||
item status */
|
||||
void pkgAcquire::Add(Item *Itm)
|
||||
{
|
||||
Items.push_back(Itm);
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Remove - Remove a item /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Remove an item from the acquire list. This is usually not used.. */
|
||||
void pkgAcquire::Remove(Item *Itm)
|
||||
{
|
||||
Dequeue(Itm);
|
||||
|
||||
for (vector<Item *>::iterator I = Items.begin(); I < Items.end(); I++)
|
||||
{
|
||||
if (*I == Itm)
|
||||
Items.erase(I);
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Add - Add a worker /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* A list of workers is kept so that the select loop can direct their FD
|
||||
usage. */
|
||||
void pkgAcquire::Add(Worker *Work)
|
||||
{
|
||||
Work->NextAcquire = Workers;
|
||||
Workers = Work;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Remove - Remove a worker /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* A worker has died. This can not be done while the select loop is running
|
||||
as it would require that RunFds could handling a changing list state and
|
||||
it cant.. */
|
||||
void pkgAcquire::Remove(Worker *Work)
|
||||
{
|
||||
if (Running == true)
|
||||
abort();
|
||||
|
||||
Worker **I = &Workers;
|
||||
for (; *I != 0;)
|
||||
{
|
||||
if (*I == Work)
|
||||
*I = (*I)->NextAcquire;
|
||||
else
|
||||
I = &(*I)->NextAcquire;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Enqueue - Queue an URI for fetching /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is the entry point for an item. An item calls this function when
|
||||
it is constructed which creates a queue (based on the current queue
|
||||
mode) and puts the item in that queue. If the system is running then
|
||||
the queue might be started. */
|
||||
void pkgAcquire::Enqueue(ItemDesc &Item)
|
||||
{
|
||||
// Determine which queue to put the item in
|
||||
const MethodConfig *Config;
|
||||
string Name = QueueName(Item.URI,Config);
|
||||
if (Name.empty() == true)
|
||||
return;
|
||||
|
||||
// Find the queue structure
|
||||
Queue *I = Queues;
|
||||
for (; I != 0 && I->Name != Name; I = I->Next);
|
||||
if (I == 0)
|
||||
{
|
||||
I = new Queue(Name,this);
|
||||
I->Next = Queues;
|
||||
Queues = I;
|
||||
|
||||
if (Running == true)
|
||||
I->Startup();
|
||||
}
|
||||
|
||||
// See if this is a local only URI
|
||||
if (Config->LocalOnly == true && Item.Owner->Complete == false)
|
||||
Item.Owner->Local = true;
|
||||
Item.Owner->Status = Item::StatIdle;
|
||||
|
||||
// Queue it into the named queue
|
||||
I->Enqueue(Item);
|
||||
ToFetch++;
|
||||
|
||||
// Some trace stuff
|
||||
if (Debug == true)
|
||||
{
|
||||
clog << "Fetching " << Item.URI << endl;
|
||||
clog << " to " << Item.Owner->DestFile << endl;
|
||||
clog << " Queue is: " << Name << endl;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Dequeue - Remove an item from all queues /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called when an item is finished being fetched. It removes it
|
||||
from all the queues */
|
||||
void pkgAcquire::Dequeue(Item *Itm)
|
||||
{
|
||||
Queue *I = Queues;
|
||||
bool Res = false;
|
||||
for (; I != 0; I = I->Next)
|
||||
Res |= I->Dequeue(Itm);
|
||||
|
||||
if (Debug == true)
|
||||
clog << "Dequeuing " << Itm->DestFile << endl;
|
||||
if (Res == true)
|
||||
ToFetch--;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::QueueName - Return the name of the queue for this URI /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The string returned depends on the configuration settings and the
|
||||
method parameters. Given something like http://foo.org/bar it can
|
||||
return http://foo.org or http */
|
||||
string pkgAcquire::QueueName(string Uri,MethodConfig const *&Config)
|
||||
{
|
||||
URI U(Uri);
|
||||
|
||||
Config = GetConfig(U.Access);
|
||||
if (Config == 0)
|
||||
return string();
|
||||
|
||||
/* Single-Instance methods get exactly one queue per URI. This is
|
||||
also used for the Access queue method */
|
||||
if (Config->SingleInstance == true || QueueMode == QueueAccess)
|
||||
return U.Access;
|
||||
|
||||
return U.Access + ':' + U.Host;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::GetConfig - Fetch the configuration information /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This locates the configuration structure for an access method. If
|
||||
a config structure cannot be found a Worker will be created to
|
||||
retrieve it */
|
||||
pkgAcquire::MethodConfig *pkgAcquire::GetConfig(string Access)
|
||||
{
|
||||
// Search for an existing config
|
||||
MethodConfig *Conf;
|
||||
for (Conf = Configs; Conf != 0; Conf = Conf->Next)
|
||||
if (Conf->Access == Access)
|
||||
return Conf;
|
||||
|
||||
// Create the new config class
|
||||
Conf = new MethodConfig;
|
||||
Conf->Access = Access;
|
||||
Conf->Next = Configs;
|
||||
Configs = Conf;
|
||||
|
||||
// Create the worker to fetch the configuration
|
||||
Worker Work(Conf);
|
||||
if (Work.Start() == false)
|
||||
return 0;
|
||||
|
||||
return Conf;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::SetFds - Deal with readable FDs /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Collect FDs that have activity monitors into the fd sets */
|
||||
void pkgAcquire::SetFds(int &Fd,fd_set *RSet,fd_set *WSet)
|
||||
{
|
||||
for (Worker *I = Workers; I != 0; I = I->NextAcquire)
|
||||
{
|
||||
if (I->InReady == true && I->InFd >= 0)
|
||||
{
|
||||
if (Fd < I->InFd)
|
||||
Fd = I->InFd;
|
||||
FD_SET(I->InFd,RSet);
|
||||
}
|
||||
if (I->OutReady == true && I->OutFd >= 0)
|
||||
{
|
||||
if (Fd < I->OutFd)
|
||||
Fd = I->OutFd;
|
||||
FD_SET(I->OutFd,WSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::RunFds - Deal with active FDs /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Dispatch active FDs over to the proper workers. It is very important
|
||||
that a worker never be erased while this is running! The queue class
|
||||
should never erase a worker except during shutdown processing. */
|
||||
void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet)
|
||||
{
|
||||
for (Worker *I = Workers; I != 0; I = I->NextAcquire)
|
||||
{
|
||||
if (I->InFd >= 0 && FD_ISSET(I->InFd,RSet) != 0)
|
||||
I->InFdReady();
|
||||
if (I->OutFd >= 0 && FD_ISSET(I->OutFd,WSet) != 0)
|
||||
I->OutFdReady();
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Run - Run the fetch sequence /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This runs the queues. It manages a select loop for all of the
|
||||
Worker tasks. The workers interact with the queues and items to
|
||||
manage the actual fetch. */
|
||||
pkgAcquire::RunResult pkgAcquire::Run()
|
||||
{
|
||||
Running = true;
|
||||
|
||||
for (Queue *I = Queues; I != 0; I = I->Next)
|
||||
I->Startup();
|
||||
|
||||
if (Log != 0)
|
||||
Log->Start();
|
||||
|
||||
bool WasCancelled = false;
|
||||
|
||||
// Run till all things have been acquired
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 500000;
|
||||
while (ToFetch > 0)
|
||||
{
|
||||
fd_set RFds;
|
||||
fd_set WFds;
|
||||
int Highest = 0;
|
||||
FD_ZERO(&RFds);
|
||||
FD_ZERO(&WFds);
|
||||
SetFds(Highest,&RFds,&WFds);
|
||||
|
||||
int Res;
|
||||
do
|
||||
{
|
||||
Res = select(Highest+1,&RFds,&WFds,0,&tv);
|
||||
}
|
||||
while (Res < 0 && errno == EINTR);
|
||||
|
||||
if (Res < 0)
|
||||
{
|
||||
_error->Errno("select","Select has failed");
|
||||
break;
|
||||
}
|
||||
|
||||
RunFds(&RFds,&WFds);
|
||||
if (_error->PendingError() == true)
|
||||
break;
|
||||
|
||||
// Timeout, notify the log class
|
||||
if (Res == 0 || (Log != 0 && Log->Update == true))
|
||||
{
|
||||
tv.tv_usec = 500000;
|
||||
for (Worker *I = Workers; I != 0; I = I->NextAcquire)
|
||||
I->Pulse();
|
||||
if (Log != 0 && Log->Pulse(this) == false)
|
||||
{
|
||||
WasCancelled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Log != 0)
|
||||
Log->Stop();
|
||||
|
||||
// Shut down the acquire bits
|
||||
Running = false;
|
||||
for (Queue *I = Queues; I != 0; I = I->Next)
|
||||
I->Shutdown(false);
|
||||
|
||||
// Shut down the items
|
||||
for (Item **I = Items.begin(); I != Items.end(); I++)
|
||||
(*I)->Finished();
|
||||
|
||||
if (_error->PendingError())
|
||||
return Failed;
|
||||
if (WasCancelled)
|
||||
return Cancelled;
|
||||
return Continue;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::Bump - Called when an item is dequeued /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This routine bumps idle queues in hopes that they will be able to fetch
|
||||
the dequeued item */
|
||||
void pkgAcquire::Bump()
|
||||
{
|
||||
for (Queue *I = Queues; I != 0; I = I->Next)
|
||||
I->Bump();
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::WorkerStep - Step to the next worker /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Not inlined to advoid including acquire-worker.h */
|
||||
pkgAcquire::Worker *pkgAcquire::WorkerStep(Worker *I)
|
||||
{
|
||||
return I->NextAcquire;
|
||||
};
|
||||
/*}}}*/
|
||||
// Acquire::Clean - Cleans a directory /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is a bit simplistic, it looks at every file in the dir and sees
|
||||
if it is part of the download set. */
|
||||
bool pkgAcquire::Clean(string Dir)
|
||||
{
|
||||
DIR *D = opendir(Dir.c_str());
|
||||
if (D == 0)
|
||||
return _error->Errno("opendir","Unable to read %s",Dir.c_str());
|
||||
|
||||
string StartDir = SafeGetCWD();
|
||||
if (chdir(Dir.c_str()) != 0)
|
||||
{
|
||||
closedir(D);
|
||||
return _error->Errno("chdir","Unable to change to ",Dir.c_str());
|
||||
}
|
||||
|
||||
for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
|
||||
{
|
||||
// Skip some files..
|
||||
if (strcmp(Dir->d_name,"lock") == 0 ||
|
||||
strcmp(Dir->d_name,"partial") == 0 ||
|
||||
strcmp(Dir->d_name,".") == 0 ||
|
||||
strcmp(Dir->d_name,"..") == 0)
|
||||
continue;
|
||||
|
||||
// Look in the get list
|
||||
vector<Item *>::iterator I = Items.begin();
|
||||
for (; I != Items.end(); I++)
|
||||
if (flNotDir((*I)->DestFile) == Dir->d_name)
|
||||
break;
|
||||
|
||||
// Nothing found, nuke it
|
||||
if (I == Items.end())
|
||||
unlink(Dir->d_name);
|
||||
};
|
||||
|
||||
chdir(StartDir.c_str());
|
||||
closedir(D);
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::TotalNeeded - Number of bytes to fetch /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is the total number of bytes needed */
|
||||
unsigned long pkgAcquire::TotalNeeded()
|
||||
{
|
||||
unsigned long Total = 0;
|
||||
for (pkgAcquire::Item **I = ItemsBegin(); I != ItemsEnd(); I++)
|
||||
Total += (*I)->FileSize;
|
||||
return Total;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::FetchNeeded - Number of bytes needed to get /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is the number of bytes that is not local */
|
||||
unsigned long pkgAcquire::FetchNeeded()
|
||||
{
|
||||
unsigned long Total = 0;
|
||||
for (pkgAcquire::Item **I = ItemsBegin(); I != ItemsEnd(); I++)
|
||||
if ((*I)->Local == false)
|
||||
Total += (*I)->FileSize;
|
||||
return Total;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::PartialPresent - Number of partial bytes we already have /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is the number of bytes that is not local */
|
||||
unsigned long pkgAcquire::PartialPresent()
|
||||
{
|
||||
unsigned long Total = 0;
|
||||
for (pkgAcquire::Item **I = ItemsBegin(); I != ItemsEnd(); I++)
|
||||
if ((*I)->Local == false)
|
||||
Total += (*I)->PartialSize;
|
||||
return Total;
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::UriBegin - Start iterator for the uri list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::UriIterator pkgAcquire::UriBegin()
|
||||
{
|
||||
return UriIterator(Queues);
|
||||
}
|
||||
/*}}}*/
|
||||
// Acquire::UriEnd - End iterator for the uri list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::UriIterator pkgAcquire::UriEnd()
|
||||
{
|
||||
return UriIterator(0);
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// Acquire::MethodConfig::MethodConfig - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::MethodConfig::MethodConfig()
|
||||
{
|
||||
SingleInstance = false;
|
||||
Pipeline = false;
|
||||
SendConfig = false;
|
||||
LocalOnly = false;
|
||||
Removable = false;
|
||||
Next = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// Queue::Queue - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::Queue::Queue(string Name,pkgAcquire *Owner) : Name(Name),
|
||||
Owner(Owner)
|
||||
{
|
||||
Items = 0;
|
||||
Next = 0;
|
||||
Workers = 0;
|
||||
MaxPipeDepth = 1;
|
||||
PipeDepth = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::~Queue - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::Queue::~Queue()
|
||||
{
|
||||
Shutdown(true);
|
||||
|
||||
while (Items != 0)
|
||||
{
|
||||
QItem *Jnk = Items;
|
||||
Items = Items->Next;
|
||||
delete Jnk;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::Enqueue - Queue an item to the queue /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgAcquire::Queue::Enqueue(ItemDesc &Item)
|
||||
{
|
||||
QItem **I = &Items;
|
||||
for (; *I != 0; I = &(*I)->Next);
|
||||
|
||||
// Create a new item
|
||||
QItem *Itm = new QItem;
|
||||
*Itm = Item;
|
||||
Itm->Next = 0;
|
||||
*I = Itm;
|
||||
|
||||
Item.Owner->QueueCounter++;
|
||||
if (Items->Next == 0)
|
||||
Cycle();
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::Dequeue - Remove an item from the queue /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We return true if we hit something */
|
||||
bool pkgAcquire::Queue::Dequeue(Item *Owner)
|
||||
{
|
||||
if (Owner->Status == pkgAcquire::Item::StatFetching)
|
||||
return _error->Error("Tried to dequeue a fetching object");
|
||||
|
||||
bool Res = false;
|
||||
|
||||
QItem **I = &Items;
|
||||
for (; *I != 0;)
|
||||
{
|
||||
if ((*I)->Owner == Owner)
|
||||
{
|
||||
QItem *Jnk= *I;
|
||||
*I = (*I)->Next;
|
||||
Owner->QueueCounter--;
|
||||
delete Jnk;
|
||||
Res = true;
|
||||
}
|
||||
else
|
||||
I = &(*I)->Next;
|
||||
}
|
||||
|
||||
return Res;
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::Startup - Start the worker processes /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* It is possible for this to be called with a pre-existing set of
|
||||
workers. */
|
||||
bool pkgAcquire::Queue::Startup()
|
||||
{
|
||||
if (Workers == 0)
|
||||
{
|
||||
URI U(Name);
|
||||
pkgAcquire::MethodConfig *Cnf = Owner->GetConfig(U.Access);
|
||||
if (Cnf == 0)
|
||||
return false;
|
||||
|
||||
Workers = new Worker(this,Cnf,Owner->Log);
|
||||
Owner->Add(Workers);
|
||||
if (Workers->Start() == false)
|
||||
return false;
|
||||
|
||||
/* When pipelining we commit 10 items. This needs to change when we
|
||||
added other source retry to have cycle maintain a pipeline depth
|
||||
on its own. */
|
||||
if (Cnf->Pipeline == true)
|
||||
MaxPipeDepth = 10;
|
||||
else
|
||||
MaxPipeDepth = 1;
|
||||
}
|
||||
|
||||
return Cycle();
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::Shutdown - Shutdown the worker processes /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* If final is true then all workers are eliminated, otherwise only workers
|
||||
that do not need cleanup are removed */
|
||||
bool pkgAcquire::Queue::Shutdown(bool Final)
|
||||
{
|
||||
// Delete all of the workers
|
||||
pkgAcquire::Worker **Cur = &Workers;
|
||||
while (*Cur != 0)
|
||||
{
|
||||
pkgAcquire::Worker *Jnk = *Cur;
|
||||
if (Final == true || Jnk->GetConf()->NeedsCleanup == false)
|
||||
{
|
||||
*Cur = Jnk->NextQueue;
|
||||
Owner->Remove(Jnk);
|
||||
delete Jnk;
|
||||
}
|
||||
else
|
||||
Cur = &(*Cur)->NextQueue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::FindItem - Find a URI in the item list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquire::Queue::QItem *pkgAcquire::Queue::FindItem(string URI,pkgAcquire::Worker *Owner)
|
||||
{
|
||||
for (QItem *I = Items; I != 0; I = I->Next)
|
||||
if (I->URI == URI && I->Worker == Owner)
|
||||
return I;
|
||||
return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::ItemDone - Item has been completed /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The worker signals this which causes the item to be removed from the
|
||||
queue. If this is the last queue instance then it is removed from the
|
||||
main queue too.*/
|
||||
bool pkgAcquire::Queue::ItemDone(QItem *Itm)
|
||||
{
|
||||
PipeDepth--;
|
||||
if (Itm->Owner->Status == pkgAcquire::Item::StatFetching)
|
||||
Itm->Owner->Status = pkgAcquire::Item::StatDone;
|
||||
|
||||
if (Itm->Owner->QueueCounter <= 1)
|
||||
Owner->Dequeue(Itm->Owner);
|
||||
else
|
||||
{
|
||||
Dequeue(Itm->Owner);
|
||||
Owner->Bump();
|
||||
}
|
||||
|
||||
return Cycle();
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::Cycle - Queue new items into the method /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This locates a new idle item and sends it to the worker. If pipelining
|
||||
is enabled then it keeps the pipe full. */
|
||||
bool pkgAcquire::Queue::Cycle()
|
||||
{
|
||||
if (Items == 0 || Workers == 0)
|
||||
return true;
|
||||
|
||||
if (PipeDepth < 0)
|
||||
return _error->Error("Pipedepth failure");
|
||||
|
||||
// Look for a queable item
|
||||
QItem *I = Items;
|
||||
while (PipeDepth < (signed)MaxPipeDepth)
|
||||
{
|
||||
for (; I != 0; I = I->Next)
|
||||
if (I->Owner->Status == pkgAcquire::Item::StatIdle)
|
||||
break;
|
||||
|
||||
// Nothing to do, queue is idle.
|
||||
if (I == 0)
|
||||
return true;
|
||||
|
||||
I->Worker = Workers;
|
||||
I->Owner->Status = pkgAcquire::Item::StatFetching;
|
||||
PipeDepth++;
|
||||
if (Workers->QueueItem(I) == false)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Queue::Bump - Fetch any pending objects if we are idle /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called when an item in multiple queues is dequeued */
|
||||
void pkgAcquire::Queue::Bump()
|
||||
{
|
||||
Cycle();
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// AcquireStatus::pkgAcquireStatus - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgAcquireStatus::pkgAcquireStatus() : Update(true), MorePulses(false)
|
||||
{
|
||||
Start();
|
||||
}
|
||||
/*}}}*/
|
||||
// AcquireStatus::Pulse - Called periodically /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This computes some internal state variables for the derived classes to
|
||||
use. It generates the current downloaded bytes and total bytes to download
|
||||
as well as the current CPS estimate. */
|
||||
bool pkgAcquireStatus::Pulse(pkgAcquire *Owner)
|
||||
{
|
||||
TotalBytes = 0;
|
||||
CurrentBytes = 0;
|
||||
TotalItems = 0;
|
||||
CurrentItems = 0;
|
||||
|
||||
// Compute the total number of bytes to fetch
|
||||
unsigned int Unknown = 0;
|
||||
unsigned int Count = 0;
|
||||
for (pkgAcquire::Item **I = Owner->ItemsBegin(); I != Owner->ItemsEnd();
|
||||
I++, Count++)
|
||||
{
|
||||
TotalItems++;
|
||||
if ((*I)->Status == pkgAcquire::Item::StatDone)
|
||||
CurrentItems++;
|
||||
|
||||
// Totally ignore local items
|
||||
if ((*I)->Local == true)
|
||||
continue;
|
||||
|
||||
TotalBytes += (*I)->FileSize;
|
||||
if ((*I)->Complete == true)
|
||||
CurrentBytes += (*I)->FileSize;
|
||||
if ((*I)->FileSize == 0 && (*I)->Complete == false)
|
||||
Unknown++;
|
||||
}
|
||||
|
||||
// Compute the current completion
|
||||
unsigned long ResumeSize = 0;
|
||||
for (pkgAcquire::Worker *I = Owner->WorkersBegin(); I != 0;
|
||||
I = Owner->WorkerStep(I))
|
||||
if (I->CurrentItem != 0 && I->CurrentItem->Owner->Complete == false)
|
||||
{
|
||||
CurrentBytes += I->CurrentSize;
|
||||
ResumeSize += I->ResumePoint;
|
||||
|
||||
// Files with unknown size always have 100% completion
|
||||
if (I->CurrentItem->Owner->FileSize == 0 &&
|
||||
I->CurrentItem->Owner->Complete == false)
|
||||
TotalBytes += I->CurrentSize;
|
||||
}
|
||||
|
||||
// Normalize the figures and account for unknown size downloads
|
||||
if (TotalBytes <= 0)
|
||||
TotalBytes = 1;
|
||||
if (Unknown == Count)
|
||||
TotalBytes = Unknown;
|
||||
|
||||
// Wha?! Is not supposed to happen.
|
||||
if (CurrentBytes > TotalBytes)
|
||||
CurrentBytes = TotalBytes;
|
||||
|
||||
// Compute the CPS
|
||||
struct timeval NewTime;
|
||||
gettimeofday(&NewTime,0);
|
||||
if (NewTime.tv_sec - Time.tv_sec == 6 && NewTime.tv_usec > Time.tv_usec ||
|
||||
NewTime.tv_sec - Time.tv_sec > 6)
|
||||
{
|
||||
double Delta = NewTime.tv_sec - Time.tv_sec +
|
||||
(NewTime.tv_usec - Time.tv_usec)/1000000.0;
|
||||
|
||||
// Compute the CPS value
|
||||
if (Delta < 0.01)
|
||||
CurrentCPS = 0;
|
||||
else
|
||||
CurrentCPS = ((CurrentBytes - ResumeSize) - LastBytes)/Delta;
|
||||
LastBytes = CurrentBytes - ResumeSize;
|
||||
ElapsedTime = (unsigned long)Delta;
|
||||
Time = NewTime;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// AcquireStatus::Start - Called when the download is started /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We just reset the counters */
|
||||
void pkgAcquireStatus::Start()
|
||||
{
|
||||
gettimeofday(&Time,0);
|
||||
gettimeofday(&StartTime,0);
|
||||
LastBytes = 0;
|
||||
CurrentCPS = 0;
|
||||
CurrentBytes = 0;
|
||||
TotalBytes = 0;
|
||||
FetchedBytes = 0;
|
||||
ElapsedTime = 0;
|
||||
TotalItems = 0;
|
||||
CurrentItems = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// AcquireStatus::Stop - Finished downloading /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This accurately computes the elapsed time and the total overall CPS. */
|
||||
void pkgAcquireStatus::Stop()
|
||||
{
|
||||
// Compute the CPS and elapsed time
|
||||
struct timeval NewTime;
|
||||
gettimeofday(&NewTime,0);
|
||||
|
||||
double Delta = NewTime.tv_sec - StartTime.tv_sec +
|
||||
(NewTime.tv_usec - StartTime.tv_usec)/1000000.0;
|
||||
|
||||
// Compute the CPS value
|
||||
if (Delta < 0.01)
|
||||
CurrentCPS = 0;
|
||||
else
|
||||
CurrentCPS = FetchedBytes/Delta;
|
||||
LastBytes = CurrentBytes;
|
||||
ElapsedTime = (unsigned int)Delta;
|
||||
}
|
||||
/*}}}*/
|
||||
// AcquireStatus::Fetched - Called when a byte set has been fetched /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is used to get accurate final transfer rate reporting. */
|
||||
void pkgAcquireStatus::Fetched(unsigned long Size,unsigned long Resume)
|
||||
{
|
||||
FetchedBytes += Size - Resume;
|
||||
}
|
||||
/*}}}*/
|
276
apt/apt-pkg/acquire.h
Normal file
276
apt/apt-pkg/acquire.h
Normal file
@ -0,0 +1,276 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: acquire.h,v 1.2 2000/11/06 12:53:49 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Acquire - File Acquiration
|
||||
|
||||
This module contians the Acquire system. It is responsible for bringing
|
||||
files into the local pathname space. It deals with URIs for files and
|
||||
URI handlers responsible for downloading or finding the URIs.
|
||||
|
||||
Each file to download is represented by an Acquire::Item class subclassed
|
||||
into a specialization. The Item class can add itself to several URI
|
||||
acquire queues each prioritized by the download scheduler. When the
|
||||
system is run the proper URI handlers are spawned and the the acquire
|
||||
queues are fed into the handlers by the schedular until the queues are
|
||||
empty. This allows for an Item to be downloaded from an alternate source
|
||||
if the first try turns out to fail. It also alows concurrent downloading
|
||||
of multiple items from multiple sources as well as dynamic balancing
|
||||
of load between the sources.
|
||||
|
||||
Schedualing of downloads is done on a first ask first get basis. This
|
||||
preserves the order of the download as much as possible. And means the
|
||||
fastest source will tend to process the largest number of files.
|
||||
|
||||
Internal methods and queues for performing gzip decompression,
|
||||
md5sum hashing and file copying are provided to allow items to apply
|
||||
a number of transformations to the data files they are working with.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_ACQUIRE_H
|
||||
#define PKGLIB_ACQUIRE_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/acquire.h"
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class pkgAcquireStatus;
|
||||
class pkgAcquire
|
||||
{
|
||||
public:
|
||||
|
||||
class Item;
|
||||
class Queue;
|
||||
class Worker;
|
||||
struct MethodConfig;
|
||||
struct ItemDesc;
|
||||
friend Item;
|
||||
friend Queue;
|
||||
|
||||
protected:
|
||||
|
||||
// List of items to fetch
|
||||
vector<Item *> Items;
|
||||
|
||||
// List of active queues and fetched method configuration parameters
|
||||
Queue *Queues;
|
||||
Worker *Workers;
|
||||
MethodConfig *Configs;
|
||||
pkgAcquireStatus *Log;
|
||||
unsigned long ToFetch;
|
||||
|
||||
// Configurable parameters for the schedular
|
||||
enum {QueueHost,QueueAccess} QueueMode;
|
||||
bool Debug;
|
||||
bool Running;
|
||||
|
||||
void Add(Item *Item);
|
||||
void Remove(Item *Item);
|
||||
void Add(Worker *Work);
|
||||
void Remove(Worker *Work);
|
||||
|
||||
void Enqueue(ItemDesc &Item);
|
||||
void Dequeue(Item *Item);
|
||||
string QueueName(string URI,MethodConfig const *&Config);
|
||||
|
||||
// FDSET managers for derived classes
|
||||
virtual void SetFds(int &Fd,fd_set *RSet,fd_set *WSet);
|
||||
virtual void RunFds(fd_set *RSet,fd_set *WSet);
|
||||
|
||||
// A queue calls this when it dequeues an item
|
||||
void Bump();
|
||||
|
||||
public:
|
||||
|
||||
MethodConfig *GetConfig(string Access);
|
||||
|
||||
enum RunResult {Continue,Failed,Cancelled};
|
||||
|
||||
RunResult Run();
|
||||
void Shutdown();
|
||||
|
||||
// Simple iteration mechanism
|
||||
inline Worker *WorkersBegin() {return Workers;};
|
||||
Worker *WorkerStep(Worker *I);
|
||||
inline Item **ItemsBegin() {return Items.begin();};
|
||||
inline Item **ItemsEnd() {return Items.end();};
|
||||
|
||||
// Iterate over queued Item URIs
|
||||
class UriIterator;
|
||||
UriIterator UriBegin();
|
||||
UriIterator UriEnd();
|
||||
|
||||
// Cleans out the download dir
|
||||
bool Clean(string Dir);
|
||||
|
||||
// Returns the size of the total download set
|
||||
unsigned long TotalNeeded();
|
||||
unsigned long FetchNeeded();
|
||||
unsigned long PartialPresent();
|
||||
|
||||
pkgAcquire(pkgAcquireStatus *Log = 0);
|
||||
virtual ~pkgAcquire();
|
||||
};
|
||||
|
||||
// Description of an Item+URI
|
||||
struct pkgAcquire::ItemDesc
|
||||
{
|
||||
string URI;
|
||||
string Description;
|
||||
string ShortDesc;
|
||||
Item *Owner;
|
||||
};
|
||||
|
||||
// List of possible items queued for download.
|
||||
class pkgAcquire::Queue
|
||||
{
|
||||
friend pkgAcquire;
|
||||
friend pkgAcquire::UriIterator;
|
||||
Queue *Next;
|
||||
|
||||
public:
|
||||
// Queued item
|
||||
struct QItem : pkgAcquire::ItemDesc
|
||||
{
|
||||
QItem *Next;
|
||||
pkgAcquire::Worker *Worker;
|
||||
|
||||
void operator =(pkgAcquire::ItemDesc const &I)
|
||||
{
|
||||
URI = I.URI;
|
||||
Description = I.Description;
|
||||
ShortDesc = I.ShortDesc;
|
||||
Owner = I.Owner;
|
||||
};
|
||||
};
|
||||
protected:
|
||||
// Name of the queue
|
||||
string Name;
|
||||
|
||||
// Items queued into this queue
|
||||
QItem *Items;
|
||||
pkgAcquire::Worker *Workers;
|
||||
pkgAcquire *Owner;
|
||||
signed long PipeDepth;
|
||||
unsigned long MaxPipeDepth;
|
||||
|
||||
public:
|
||||
|
||||
// Put an item into this queue
|
||||
void Enqueue(ItemDesc &Item);
|
||||
bool Dequeue(Item *Owner);
|
||||
|
||||
// Find a Queued item
|
||||
QItem *FindItem(string URI,pkgAcquire::Worker *Owner);
|
||||
bool ItemStart(QItem *Itm,unsigned long Size);
|
||||
bool ItemDone(QItem *Itm);
|
||||
|
||||
bool Startup();
|
||||
bool Shutdown(bool Final);
|
||||
bool Cycle();
|
||||
void Bump();
|
||||
|
||||
Queue(string Name,pkgAcquire *Owner);
|
||||
~Queue();
|
||||
};
|
||||
|
||||
class pkgAcquire::UriIterator
|
||||
{
|
||||
pkgAcquire::Queue *CurQ;
|
||||
pkgAcquire::Queue::QItem *CurItem;
|
||||
|
||||
public:
|
||||
|
||||
// Advance to the next item
|
||||
inline void operator ++() {operator ++();};
|
||||
void operator ++(int)
|
||||
{
|
||||
CurItem = CurItem->Next;
|
||||
while (CurItem == 0 && CurQ != 0)
|
||||
{
|
||||
CurItem = CurQ->Items;
|
||||
CurQ = CurQ->Next;
|
||||
}
|
||||
};
|
||||
|
||||
// Accessors
|
||||
inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;};
|
||||
inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;};
|
||||
inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;};
|
||||
|
||||
UriIterator(pkgAcquire::Queue *Q) : CurQ(Q), CurItem(0)
|
||||
{
|
||||
while (CurItem == 0 && CurQ != 0)
|
||||
{
|
||||
CurItem = CurQ->Items;
|
||||
CurQ = CurQ->Next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Configuration information from each method
|
||||
struct pkgAcquire::MethodConfig
|
||||
{
|
||||
MethodConfig *Next;
|
||||
|
||||
string Access;
|
||||
|
||||
string Version;
|
||||
bool SingleInstance;
|
||||
bool Pipeline;
|
||||
bool SendConfig;
|
||||
bool LocalOnly;
|
||||
bool NeedsCleanup;
|
||||
bool Removable;
|
||||
|
||||
MethodConfig();
|
||||
};
|
||||
|
||||
class pkgAcquireStatus
|
||||
{
|
||||
protected:
|
||||
|
||||
struct timeval Time;
|
||||
struct timeval StartTime;
|
||||
unsigned long LastBytes;
|
||||
double CurrentCPS;
|
||||
unsigned long CurrentBytes;
|
||||
unsigned long TotalBytes;
|
||||
unsigned long FetchedBytes;
|
||||
unsigned long ElapsedTime;
|
||||
unsigned long TotalItems;
|
||||
unsigned long CurrentItems;
|
||||
|
||||
public:
|
||||
|
||||
bool Update;
|
||||
bool MorePulses;
|
||||
|
||||
// Called by items when they have finished a real download
|
||||
virtual void Fetched(unsigned long Size,unsigned long ResumePoint);
|
||||
|
||||
// Called to change media
|
||||
virtual bool MediaChange(string Media,string Drive) = 0;
|
||||
|
||||
// Each of these is called by the workers when an event occures
|
||||
virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) {};
|
||||
virtual void Fetch(pkgAcquire::ItemDesc &/*Itm*/) {};
|
||||
virtual void Done(pkgAcquire::ItemDesc &/*Itm*/) {};
|
||||
virtual void Fail(pkgAcquire::ItemDesc &/*Itm*/) {};
|
||||
virtual bool Pulse(pkgAcquire *Owner); // returns false on user cancel
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
|
||||
pkgAcquireStatus();
|
||||
virtual ~pkgAcquireStatus() {};
|
||||
};
|
||||
|
||||
#endif
|
1177
apt/apt-pkg/algorithms.cc
Normal file
1177
apt/apt-pkg/algorithms.cc
Normal file
File diff suppressed because it is too large
Load Diff
113
apt/apt-pkg/algorithms.h
Normal file
113
apt/apt-pkg/algorithms.h
Normal file
@ -0,0 +1,113 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: algorithms.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Algorithms - A set of misc algorithms
|
||||
|
||||
This simulate class displays what the ordering code has done and
|
||||
analyses it with a fresh new dependency cache. In this way we can
|
||||
see all of the effects of an upgrade run.
|
||||
|
||||
pkgDistUpgrade computes an upgrade that causes as many packages as
|
||||
possible to move to the newest verison.
|
||||
|
||||
pkgApplyStatus sets the target state based on the content of the status
|
||||
field in the status file. It is important to get proper crash recovery.
|
||||
|
||||
pkgFixBroken corrects a broken system so that it is in a sane state.
|
||||
|
||||
pkgAllUpgrade attempts to upgade as many packages as possible but
|
||||
without installing new packages.
|
||||
|
||||
The problem resolver class contains a number of complex algorithms
|
||||
to try to best-guess an upgrade state. It solves the problem of
|
||||
maximizing the number of install state packages while having no broken
|
||||
packages.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_ALGORITHMS_H
|
||||
#define PKGLIB_ALGORITHMS_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/algorithms.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/packagemanager.h>
|
||||
#include <apt-pkg/depcache.h>
|
||||
|
||||
class pkgSimulate : public pkgPackageManager
|
||||
{
|
||||
protected:
|
||||
|
||||
unsigned char *Flags;
|
||||
|
||||
pkgDepCache Sim;
|
||||
|
||||
// The Actuall installation implementation
|
||||
virtual bool Install(PkgIterator Pkg,string File);
|
||||
virtual bool Configure(PkgIterator Pkg);
|
||||
virtual bool Remove(PkgIterator Pkg,bool Purge);
|
||||
void ShortBreaks();
|
||||
|
||||
public:
|
||||
|
||||
pkgSimulate(pkgDepCache &Cache);
|
||||
};
|
||||
|
||||
class pkgProblemResolver
|
||||
{
|
||||
pkgDepCache &Cache;
|
||||
typedef pkgCache::PkgIterator PkgIterator;
|
||||
typedef pkgCache::VerIterator VerIterator;
|
||||
typedef pkgCache::DepIterator DepIterator;
|
||||
typedef pkgCache::PrvIterator PrvIterator;
|
||||
typedef pkgCache::Version Version;
|
||||
typedef pkgCache::Package Package;
|
||||
|
||||
enum Flags {Protected = (1 << 0), PreInstalled = (1 << 1),
|
||||
Upgradable = (1 << 2), ReInstateTried = (1 << 3),
|
||||
ToRemove = (1 << 4)};
|
||||
signed short *Scores;
|
||||
unsigned char *Flags;
|
||||
bool Debug;
|
||||
|
||||
// Sort stuff
|
||||
static pkgProblemResolver *This;
|
||||
static int ScoreSort(const void *a,const void *b);
|
||||
|
||||
struct PackageKill
|
||||
{
|
||||
PkgIterator Pkg;
|
||||
DepIterator Dep;
|
||||
};
|
||||
|
||||
void MakeScores();
|
||||
bool DoUpgrade(pkgCache::PkgIterator Pkg);
|
||||
|
||||
public:
|
||||
|
||||
inline void Protect(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= Protected;};
|
||||
inline void Remove(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= ToRemove;};
|
||||
inline void Clear(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] &= ~(Protected | ToRemove);};
|
||||
|
||||
// Try to intelligently resolve problems by installing and removing packages
|
||||
bool Resolve(bool BrokenFix = false);
|
||||
|
||||
// Try to resolve problems only by using keep
|
||||
bool ResolveByKeep();
|
||||
|
||||
void InstallProtect();
|
||||
|
||||
pkgProblemResolver(pkgDepCache &Cache);
|
||||
};
|
||||
|
||||
bool pkgDistUpgrade(pkgDepCache &Cache);
|
||||
bool pkgApplyStatus(pkgDepCache &Cache);
|
||||
bool pkgFixBroken(pkgDepCache &Cache);
|
||||
bool pkgAllUpgrade(pkgDepCache &Cache);
|
||||
bool pkgMinimizeUpgrade(pkgDepCache &Cache);
|
||||
|
||||
#endif
|
123
apt/apt-pkg/cachefile.cc
Normal file
123
apt/apt-pkg/cachefile.cc
Normal file
@ -0,0 +1,123 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: cachefile.cc,v 1.8 2001/07/12 21:47:32 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
CacheFile - Simple wrapper class for opening, generating and whatnot
|
||||
|
||||
This class implements a simple 2 line mechanism to open various sorts
|
||||
of caches. It can operate as root, as not root, show progress and so on,
|
||||
it transparently handles everything necessary.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/cachefile.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <apt-pkg/cachefile.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/sourcelist.h>
|
||||
#include <apt-pkg/pkgcachegen.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/systemfactory.h>
|
||||
|
||||
#include <i18n.h>
|
||||
|
||||
/*}}}*/
|
||||
|
||||
// CacheFile::CacheFile - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgCacheFile::pkgCacheFile() : Map(0), Cache(0),
|
||||
#if 0//akk
|
||||
Lock(0),
|
||||
#endif
|
||||
RPM(0)
|
||||
{
|
||||
}
|
||||
/*}}}*/
|
||||
// CacheFile::~CacheFile - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgCacheFile::~pkgCacheFile()
|
||||
{
|
||||
delete Cache;
|
||||
delete Map;
|
||||
#if 0//akk
|
||||
if (Lock)
|
||||
delete Lock;
|
||||
#endif
|
||||
if (RPM)
|
||||
delete RPM;
|
||||
}
|
||||
/*}}}*/
|
||||
// CacheFile::Open - Open the cache files, creating if necessary /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgCacheFile::Open(OpProgress &Progress,bool WithLock)
|
||||
{
|
||||
if (WithLock == true)
|
||||
{
|
||||
#if 0 //akk
|
||||
if (0)//akk
|
||||
{
|
||||
Lock = new pkgDpkgLock;
|
||||
} else
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (1) {
|
||||
RPM = new pkgRpmLock(WithLock);
|
||||
}
|
||||
|
||||
if (_error->PendingError() == true)
|
||||
return false;
|
||||
|
||||
// Read the source list
|
||||
pkgSourceList List;
|
||||
if (List.ReadMainList() == false)
|
||||
return _error->Error(_("The list of sources could not be read."));
|
||||
|
||||
/* Build all of the caches, using the cache files if we are locking
|
||||
(ie as root) */
|
||||
if (WithLock == true)
|
||||
{
|
||||
_system->makeStatusCache(List, Progress);
|
||||
|
||||
Progress.Done();
|
||||
if (_error->PendingError() == true)
|
||||
return _error->Error(_("The package lists or status file could not be parsed or opened."));
|
||||
if (_error->empty() == false)
|
||||
_error->Warning(_("You may want to run apt-get update to correct these missing files"));
|
||||
|
||||
// Open the cache file
|
||||
FileFd File(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
|
||||
if (_error->PendingError() == true)
|
||||
return false;
|
||||
|
||||
Map = new MMap(File,MMap::Public | MMap::ReadOnly);
|
||||
if (_error->PendingError() == true)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Map = _system->makeStatusCacheMem(List,Progress);
|
||||
Progress.Done();
|
||||
if (Map == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the dependency cache
|
||||
Cache = new pkgDepCache(*Map,Progress);
|
||||
Progress.Done();
|
||||
if (_error->PendingError() == true)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
63
apt/apt-pkg/cachefile.h
Normal file
63
apt/apt-pkg/cachefile.h
Normal file
@ -0,0 +1,63 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: cachefile.h,v 1.4 2001/07/12 21:47:32 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
CacheFile - Simple wrapper class for opening, generating and whatnot
|
||||
|
||||
This class implements a simple 2 line mechanism to open various sorts
|
||||
of caches. It can operate as root, as not root, show progress and so on,
|
||||
it transparently handles everything necessary.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_CACHEFILE_H
|
||||
#define PKGLIB_CACHEFILE_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/cachefile.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <apt-pkg/depcache.h>
|
||||
#include <apt-pkg/dpkginit.h>
|
||||
#include <apt-pkg/rpminit.h>
|
||||
|
||||
class pkgCacheFile
|
||||
{
|
||||
protected:
|
||||
|
||||
MMap *Map;
|
||||
pkgDepCache *Cache;
|
||||
#if 0//akk
|
||||
pkgDpkgLock *Lock;
|
||||
#endif
|
||||
pkgRpmLock *RPM;
|
||||
|
||||
public:
|
||||
|
||||
// We look pretty much exactly like a pointer to a dep cache
|
||||
inline operator pkgDepCache &() {return *Cache;};
|
||||
inline operator pkgDepCache *() {return Cache;};
|
||||
inline pkgDepCache *operator ->() {return Cache;};
|
||||
inline pkgDepCache &operator *() {return *Cache;};
|
||||
inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*Cache)[I];};
|
||||
inline unsigned char &operator [](pkgCache::DepIterator const &I) {return (*Cache)[I];};
|
||||
|
||||
// Release the dpkg status lock
|
||||
inline void ReleaseLock() {
|
||||
#if 0//akk
|
||||
if (0)
|
||||
Lock->Close();
|
||||
else
|
||||
#endif
|
||||
RPM->Close();
|
||||
};//akk
|
||||
|
||||
bool Open(OpProgress &Progress,bool WithLock = true);
|
||||
|
||||
pkgCacheFile();
|
||||
~pkgCacheFile();
|
||||
};
|
||||
|
||||
#endif
|
350
apt/apt-pkg/cacheiterators.h
Normal file
350
apt/apt-pkg/cacheiterators.h
Normal file
@ -0,0 +1,350 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: cacheiterators.h,v 1.2 2000/09/20 15:20:06 kojima 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. The provide iterator has the
|
||||
same system.
|
||||
|
||||
This header is not user includable, please use apt-pkg/pkgcache.h
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_CACHEITERATORS_H
|
||||
#define PKGLIB_CACHEITERATORS_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/cacheiterators.h"
|
||||
#endif
|
||||
|
||||
// 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 bool Purge() const {return Pkg->CurrentState == pkgCache::State::Purge ||
|
||||
(Pkg->CurrentVer == 0 && Pkg->CurrentState == pkgCache::State::NotInstalled);};
|
||||
inline VerIterator VersionList() const;
|
||||
inline VerIterator TargetVer() const;
|
||||
inline VerIterator CurrentVer() const;
|
||||
inline DepIterator RevDependsList() const;
|
||||
inline PrvIterator ProvidesList() const;
|
||||
inline unsigned long Index() const {return Pkg - Owner->PkgP;};
|
||||
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; Owner = B.Owner;};
|
||||
|
||||
// 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 const char *Arch() const {return Ver->Arch == 0?0:Owner->StrP + Ver->Arch;};
|
||||
inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Ver->ParentPkg);};
|
||||
inline DepIterator DependsList() const;
|
||||
inline PrvIterator ProvidesList() const;
|
||||
inline VerFileIterator FileList() const;
|
||||
inline unsigned long Index() const {return Ver - Owner->VerP;};
|
||||
bool Downloadable() const;
|
||||
const char *PriorityType();
|
||||
|
||||
bool Automatic() const;
|
||||
VerFileIterator NewestFile() const;
|
||||
|
||||
inline VerIterator() : Ver(0), Owner(0) {};
|
||||
inline VerIterator(pkgCache &Owner,Version *Trg = 0) : 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);};
|
||||
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);};
|
||||
inline bool Reverse() {return Type == DepRev;};
|
||||
inline unsigned long Index() const {return Dep - Owner->DepP;};
|
||||
bool IsCritical();
|
||||
void GlobOr(DepIterator &Start,DepIterator &End);
|
||||
Version **AllTargets();
|
||||
bool SmartTargetPkg(PkgIterator &Result);
|
||||
const char *CompType();
|
||||
const char *DepType();
|
||||
|
||||
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 unsigned long Index() const {return Prv - Owner->ProvideP;};
|
||||
|
||||
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 *Archive() const {return File->Archive == 0?0:Owner->StrP + File->Archive;};
|
||||
inline const char *Component() const {return File->Component == 0?0:Owner->StrP + File->Component;};
|
||||
inline const char *Version() const {return File->Version == 0?0:Owner->StrP + File->Version;};
|
||||
inline const char *Origin() const {return File->Origin == 0?0:Owner->StrP + File->Origin;};
|
||||
inline const char *Label() const {return File->Origin == 0?0:Owner->StrP + File->Label;};
|
||||
inline const char *Architecture() const {return File->Origin == 0?0:Owner->StrP + File->Architecture;};
|
||||
|
||||
inline unsigned long Index() const {return File - Owner->PkgFileP;};
|
||||
|
||||
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) {};
|
||||
};
|
||||
|
||||
// Version File
|
||||
class pkgCache::VerFileIterator
|
||||
{
|
||||
pkgCache *Owner;
|
||||
VerFile *FileP;
|
||||
|
||||
public:
|
||||
|
||||
// Iteration
|
||||
void operator ++(int) {if (FileP != Owner->VerFileP) FileP = Owner->VerFileP + FileP->NextFile;};
|
||||
inline void operator ++() {operator ++(0);};
|
||||
inline bool end() const {return FileP == Owner->VerFileP?true:false;};
|
||||
|
||||
// Comparison
|
||||
inline bool operator ==(const VerFileIterator &B) const {return FileP == B.FileP;};
|
||||
inline bool operator !=(const VerFileIterator &B) const {return FileP != B.FileP;};
|
||||
|
||||
// Accessors
|
||||
inline VerFile *operator ->() {return FileP;};
|
||||
inline VerFile const *operator ->() const {return FileP;};
|
||||
inline VerFile const &operator *() const {return *FileP;};
|
||||
inline operator VerFile *() {return FileP == Owner->VerFileP?0:FileP;};
|
||||
inline operator VerFile const *() const {return FileP == Owner->VerFileP?0:FileP;};
|
||||
|
||||
inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
|
||||
inline unsigned long Index() const {return FileP - Owner->VerFileP;};
|
||||
|
||||
inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(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::VerFileIterator pkgCache::VerIterator::FileList() const
|
||||
{return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);};
|
||||
|
||||
#endif
|
117
apt/apt-pkg/clean.cc
Normal file
117
apt/apt-pkg/clean.cc
Normal file
@ -0,0 +1,117 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: clean.cc,v 1.2 2001/01/11 02:03:26 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Clean - Clean out downloaded directories
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Includes /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/clean.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/clean.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <i18n.h>
|
||||
|
||||
/*}}}*/
|
||||
|
||||
// ArchiveCleaner::Go - Perform smart cleanup of the archive /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Scan the directory for files to erase, we check the version information
|
||||
against our database to see if it is interesting */
|
||||
bool pkgArchiveCleaner::Go(string Dir,pkgCache &Cache)
|
||||
{
|
||||
bool CleanInstalled = _config->FindB("APT::Clean-Installed",true);
|
||||
|
||||
DIR *D = opendir(Dir.c_str());
|
||||
if (D == 0)
|
||||
return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
|
||||
|
||||
string StartDir = SafeGetCWD();
|
||||
if (chdir(Dir.c_str()) != 0)
|
||||
{
|
||||
closedir(D);
|
||||
return _error->Errno("chdir",_("Unable to change to "),Dir.c_str());
|
||||
}
|
||||
|
||||
for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
|
||||
{
|
||||
// Skip some files..
|
||||
if (strcmp(Dir->d_name,"lock") == 0 ||
|
||||
strcmp(Dir->d_name,"partial") == 0 ||
|
||||
strcmp(Dir->d_name,".") == 0 ||
|
||||
strcmp(Dir->d_name,"..") == 0)
|
||||
continue;
|
||||
|
||||
struct stat St;
|
||||
if (stat(Dir->d_name,&St) != 0)
|
||||
return _error->Errno("stat",_("Unable to stat %s."),Dir->d_name);
|
||||
|
||||
// Grab the package name
|
||||
const char *I = Dir->d_name;
|
||||
for (; *I != 0 && *I != '_';I++);
|
||||
if (*I != '_')
|
||||
continue;
|
||||
string Pkg = DeQuoteString(string(Dir->d_name,I-Dir->d_name));
|
||||
|
||||
// Grab the version
|
||||
const char *Start = I + 1;
|
||||
for (I = Start; *I != 0 && *I != '_';I++);
|
||||
if (*I != '_')
|
||||
continue;
|
||||
string Ver = DeQuoteString(string(Start,I-Start));
|
||||
|
||||
// Grab the arch
|
||||
Start = I + 1;
|
||||
for (I = Start; *I != 0 && *I != '.' ;I++);
|
||||
if (*I != '.')
|
||||
continue;
|
||||
string Arch = DeQuoteString(string(Start,I-Start));
|
||||
|
||||
// Lookup the package
|
||||
pkgCache::PkgIterator P = Cache.FindPkg(Pkg);
|
||||
if (P.end() != true)
|
||||
{
|
||||
pkgCache::VerIterator V = P.VersionList();
|
||||
for (; V.end() == false; V++)
|
||||
{
|
||||
// See if we can fetch this version at all
|
||||
bool IsFetchable = false;
|
||||
for (pkgCache::VerFileIterator J = V.FileList();
|
||||
J.end() == false; J++)
|
||||
{
|
||||
if (CleanInstalled == true &&
|
||||
(J.File()->Flags & pkgCache::Flag::NotSource) != 0)
|
||||
continue;
|
||||
IsFetchable = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// See if this verison matches the file
|
||||
if (IsFetchable == true && Ver == V.VerStr())
|
||||
break;
|
||||
}
|
||||
|
||||
// We found a match, keep the file
|
||||
if (V.end() == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
Erase(Dir->d_name,Pkg,Ver,St);
|
||||
};
|
||||
|
||||
chdir(StartDir.c_str());
|
||||
closedir(D);
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
30
apt/apt-pkg/clean.h
Normal file
30
apt/apt-pkg/clean.h
Normal file
@ -0,0 +1,30 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: clean.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Clean - Clean out downloaded directories
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef APTPKG_CLEAN_H
|
||||
#define APTPKG_CLEAN_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/clean.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/pkgcache.h>
|
||||
|
||||
class pkgArchiveCleaner
|
||||
{
|
||||
protected:
|
||||
|
||||
virtual void Erase(const char * /*File*/,string /*Pkg*/,string /*Ver*/,struct stat & /*St*/) {};
|
||||
|
||||
public:
|
||||
|
||||
bool Go(string Dir,pkgCache &Cache);
|
||||
};
|
||||
|
||||
#endif
|
1
apt/apt-pkg/cnc/CVS/Entries
Normal file
1
apt/apt-pkg/cnc/CVS/Entries
Normal file
@ -0,0 +1 @@
|
||||
D
|
1
apt/apt-pkg/cnc/CVS/Repository
Normal file
1
apt/apt-pkg/cnc/CVS/Repository
Normal file
@ -0,0 +1 @@
|
||||
rapt/apt-pkg/cnc
|
1
apt/apt-pkg/cnc/CVS/Root
Normal file
1
apt/apt-pkg/cnc/CVS/Root
Normal file
@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs
|
24
apt/apt-pkg/contrib/CVS/Entries
Normal file
24
apt/apt-pkg/contrib/CVS/Entries
Normal file
@ -0,0 +1,24 @@
|
||||
/cdromutl.cc/1.1.1.1/Fri Aug 10 14:00:24 2001//
|
||||
/cdromutl.h/1.1.1.1/Fri Aug 10 14:00:24 2001//
|
||||
/cmndline.cc/1.1.1.1/Fri Aug 10 14:00:24 2001//
|
||||
/cmndline.h/1.1.1.1/Fri Aug 10 14:00:28 2001//
|
||||
/configuration.cc/1.2/Fri Aug 10 14:00:30 2001//
|
||||
/configuration.h/1.2/Fri Aug 10 14:00:30 2001//
|
||||
/crc-16.cc/1.1.1.1/Fri Aug 10 14:00:30 2001//
|
||||
/crc-16.h/1.1.1.1/Fri Aug 10 14:00:30 2001//
|
||||
/error.h/1.1.1.1/Fri Aug 10 14:00:30 2001//
|
||||
/fileutl.cc/1.3/Fri Aug 10 14:00:30 2001//
|
||||
/fileutl.h/1.2/Fri Aug 10 14:00:30 2001//
|
||||
/md5.cc/1.1.1.1/Fri Aug 10 14:00:32 2001//
|
||||
/md5.h/1.1.1.1/Fri Aug 10 14:00:32 2001//
|
||||
/mmap.cc/1.1.1.1/Fri Aug 10 14:00:32 2001//
|
||||
/mmap.h/1.1.1.1/Fri Aug 10 14:00:32 2001//
|
||||
/progress.h/1.1.1.1/Fri Aug 10 14:00:32 2001//
|
||||
/sptr.h/1.1/Fri Aug 10 14:00:34 2001//
|
||||
/strutl.cc/1.3/Fri Aug 10 14:00:34 2001//
|
||||
/strutl.h/1.3/Fri Aug 10 14:00:34 2001//
|
||||
/system.h/1.1.1.1/Fri Aug 10 14:00:34 2001//
|
||||
/error.cc/1.4/Tue Nov 13 14:24:16 2001//
|
||||
/i18n.h/1.2/Fri Nov 16 01:13:06 2001//
|
||||
/progress.cc/1.3/Fri Nov 16 01:13:06 2001//
|
||||
D
|
1
apt/apt-pkg/contrib/CVS/Repository
Normal file
1
apt/apt-pkg/contrib/CVS/Repository
Normal file
@ -0,0 +1 @@
|
||||
rapt/apt-pkg/contrib
|
1
apt/apt-pkg/contrib/CVS/Root
Normal file
1
apt/apt-pkg/contrib/CVS/Root
Normal file
@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs
|
202
apt/apt-pkg/contrib/cdromutl.cc
Normal file
202
apt/apt-pkg/contrib/cdromutl.cc
Normal file
@ -0,0 +1,202 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: cdromutl.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
CDROM Utilities - Some functions to manipulate CDROM mounts.
|
||||
|
||||
These are here for the cdrom method and apt-cdrom.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/cdromutl.h"
|
||||
#endif
|
||||
#include <apt-pkg/cdromutl.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/md5.h>
|
||||
#include <apt-pkg/fileutl.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
/*}}}*/
|
||||
|
||||
// IsMounted - Returns true if the mount point is mounted /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is a simple algorithm that should always work, we stat the mount point
|
||||
and the '..' file in the mount point and see if they are on the same device.
|
||||
By definition if they are the same then it is not mounted. This should
|
||||
account for symlinked mount points as well. */
|
||||
bool IsMounted(string &Path)
|
||||
{
|
||||
if (Path.empty() == true)
|
||||
return false;
|
||||
|
||||
// Need that trailing slash for directories
|
||||
if (Path[Path.length() - 1] != '/')
|
||||
Path += '/';
|
||||
|
||||
/* First we check if the path is actualy mounted, we do this by
|
||||
stating the path and the previous directory (carefull of links!)
|
||||
and comparing their device fields. */
|
||||
struct stat Buf,Buf2;
|
||||
if (stat(Path.c_str(),&Buf) != 0 ||
|
||||
stat((Path + "../").c_str(),&Buf2) != 0)
|
||||
return _error->Errno("stat","Unable to stat the mount point %s",Path.c_str());
|
||||
|
||||
if (Buf.st_dev == Buf2.st_dev)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// UnmountCdrom - Unmount a cdrom /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Forking umount works much better than the umount syscall which can
|
||||
leave /etc/mtab inconsitant. We drop all messages this produces. */
|
||||
bool UnmountCdrom(string Path)
|
||||
{
|
||||
if (IsMounted(Path) == false)
|
||||
return true;
|
||||
|
||||
int Child = ExecFork();
|
||||
|
||||
// The child
|
||||
if (Child == 0)
|
||||
{
|
||||
// Make all the fds /dev/null
|
||||
for (int I = 0; I != 3; I++)
|
||||
dup2(open("/dev/null",O_RDWR),I);
|
||||
|
||||
if (_config->Exists("Acquire::cdrom::"+Path+"::UMount") == true)
|
||||
{
|
||||
if (system(_config->Find("Acquire::cdrom::"+Path+"::UMount").c_str()) != 0)
|
||||
_exit(100);
|
||||
_exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *Args[10];
|
||||
Args[0] = "umount";
|
||||
Args[1] = Path.c_str();
|
||||
Args[2] = 0;
|
||||
execvp(Args[0],(char **)Args);
|
||||
_exit(100);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for mount
|
||||
return ExecWait(Child,"mount",true);
|
||||
}
|
||||
/*}}}*/
|
||||
// MountCdrom - Mount a cdrom /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We fork mount and drop all messages */
|
||||
bool MountCdrom(string Path)
|
||||
{
|
||||
if (IsMounted(Path) == true)
|
||||
return true;
|
||||
|
||||
int Child = ExecFork();
|
||||
|
||||
// The child
|
||||
if (Child == 0)
|
||||
{
|
||||
// Make all the fds /dev/null
|
||||
for (int I = 0; I != 3; I++)
|
||||
dup2(open("/dev/null",O_RDWR),I);
|
||||
|
||||
if (_config->Exists("Acquire::cdrom::"+Path+"::Mount") == true)
|
||||
{
|
||||
if (system(_config->Find("Acquire::cdrom::"+Path+"::Mount").c_str()) != 0)
|
||||
_exit(100);
|
||||
_exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *Args[10];
|
||||
Args[0] = "mount";
|
||||
Args[1] = Path.c_str();
|
||||
Args[2] = 0;
|
||||
execvp(Args[0],(char **)Args);
|
||||
_exit(100);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for mount
|
||||
return ExecWait(Child,"mount",true);
|
||||
}
|
||||
/*}}}*/
|
||||
// IdentCdrom - Generate a unique string for this CD /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We convert everything we hash into a string, this prevents byte size/order
|
||||
from effecting the outcome. */
|
||||
bool IdentCdrom(string CD,string &Res,unsigned int Version)
|
||||
{
|
||||
MD5Summation Hash;
|
||||
|
||||
string StartDir = SafeGetCWD();
|
||||
if (chdir(CD.c_str()) != 0)
|
||||
return _error->Errno("chdir","Unable to change to %s",CD.c_str());
|
||||
|
||||
DIR *D = opendir(".");
|
||||
if (D == 0)
|
||||
return _error->Errno("opendir","Unable to read %s",CD.c_str());
|
||||
|
||||
/* Run over the directory, we assume that the reader order will never
|
||||
change as the media is read-only. In theory if the kernel did
|
||||
some sort of wacked caching this might not be true.. */
|
||||
char S[300];
|
||||
for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
|
||||
{
|
||||
// Skip some files..
|
||||
if (strcmp(Dir->d_name,".") == 0 ||
|
||||
strcmp(Dir->d_name,"..") == 0)
|
||||
continue;
|
||||
|
||||
if (Version <= 1)
|
||||
{
|
||||
sprintf(S,"%lu",(unsigned long)Dir->d_ino);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stat Buf;
|
||||
if (stat(Dir->d_name,&Buf) != 0)
|
||||
continue;
|
||||
sprintf(S,"%lu",(unsigned long)Buf.st_mtime);
|
||||
}
|
||||
|
||||
Hash.Add(S);
|
||||
Hash.Add(Dir->d_name);
|
||||
};
|
||||
|
||||
chdir(StartDir.c_str());
|
||||
closedir(D);
|
||||
|
||||
// Some stats from the fsys
|
||||
if (_config->FindB("Debug::identcdrom",false) == false)
|
||||
{
|
||||
struct statvfs Buf;
|
||||
if (statvfs(CD.c_str(),&Buf) != 0)
|
||||
return _error->Errno("statfs","Failed to stat the cdrom");
|
||||
|
||||
// We use a kilobyte block size to advoid overflow
|
||||
sprintf(S,"%lu %lu",(long)(Buf.f_blocks*(Buf.f_bsize/1024)),
|
||||
(long)(Buf.f_bfree*(Buf.f_bsize/1024)));
|
||||
Hash.Add(S);
|
||||
sprintf(S,"-%u",Version);
|
||||
}
|
||||
else
|
||||
sprintf(S,"-%u.debug",Version);
|
||||
|
||||
Res = Hash.Result().Value() + S;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
23
apt/apt-pkg/contrib/cdromutl.h
Normal file
23
apt/apt-pkg/contrib/cdromutl.h
Normal file
@ -0,0 +1,23 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: cdromutl.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
CDROM Utilities - Some functions to manipulate CDROM mounts.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_CDROMUTL_H
|
||||
#define PKGLIB_ACQUIRE_METHOD_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/cdromutl.h"
|
||||
#endif
|
||||
|
||||
bool MountCdrom(string Path);
|
||||
bool UnmountCdrom(string Path);
|
||||
bool IdentCdrom(string CD,string &Res,unsigned int Version = 2);
|
||||
|
||||
#endif
|
347
apt/apt-pkg/contrib/cmndline.cc
Normal file
347
apt/apt-pkg/contrib/cmndline.cc
Normal file
@ -0,0 +1,347 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: cmndline.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Command Line Class - Sophisticated command line parser
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/cmndline.h"
|
||||
#endif
|
||||
#include <apt-pkg/cmndline.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
/*}}}*/
|
||||
|
||||
// CommandLine::CommandLine - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
CommandLine::CommandLine(Args *AList,Configuration *Conf) : ArgList(AList),
|
||||
Conf(Conf), FileList(0)
|
||||
{
|
||||
}
|
||||
/*}}}*/
|
||||
// CommandLine::~CommandLine - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
CommandLine::~CommandLine()
|
||||
{
|
||||
delete [] FileList;
|
||||
}
|
||||
/*}}}*/
|
||||
// CommandLine::Parse - Main action member /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool CommandLine::Parse(int argc,const char **argv)
|
||||
{
|
||||
delete [] FileList;
|
||||
FileList = new const char *[argc];
|
||||
const char **Files = FileList;
|
||||
int I;
|
||||
for (I = 1; I != argc; I++)
|
||||
{
|
||||
const char *Opt = argv[I];
|
||||
|
||||
// It is not an option
|
||||
if (*Opt != '-')
|
||||
{
|
||||
*Files++ = Opt;
|
||||
continue;
|
||||
}
|
||||
|
||||
Opt++;
|
||||
|
||||
// Double dash signifies the end of option processing
|
||||
if (*Opt == '-' && Opt[1] == 0)
|
||||
break;
|
||||
|
||||
// Single dash is a short option
|
||||
if (*Opt != '-')
|
||||
{
|
||||
// Iterate over each letter
|
||||
while (*Opt != 0)
|
||||
{
|
||||
// Search for the option
|
||||
Args *A;
|
||||
for (A = ArgList; A->end() == false && A->ShortOpt != *Opt; A++);
|
||||
if (A->end() == true)
|
||||
return _error->Error("Command line option '%c' [from %s] is not known.",*Opt,argv[I]);
|
||||
|
||||
if (HandleOpt(I,argc,argv,Opt,A) == false)
|
||||
return false;
|
||||
if (*Opt != 0)
|
||||
Opt++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Opt++;
|
||||
|
||||
// Match up to a = against the list
|
||||
const char *OptEnd = Opt;
|
||||
Args *A;
|
||||
for (; *OptEnd != 0 && *OptEnd != '='; OptEnd++);
|
||||
for (A = ArgList; A->end() == false &&
|
||||
stringcasecmp(Opt,OptEnd,A->LongOpt) != 0; A++);
|
||||
|
||||
// Failed, look for a word after the first - (no-foo)
|
||||
bool PreceedMatch = false;
|
||||
if (A->end() == true)
|
||||
{
|
||||
for (; Opt != OptEnd && *Opt != '-'; Opt++);
|
||||
|
||||
if (Opt == OptEnd)
|
||||
return _error->Error("Command line option %s is not understood",argv[I]);
|
||||
Opt++;
|
||||
|
||||
for (A = ArgList; A->end() == false &&
|
||||
stringcasecmp(Opt,OptEnd,A->LongOpt) != 0; A++);
|
||||
|
||||
// Failed again..
|
||||
if (A->end() == true && OptEnd - Opt != 1)
|
||||
return _error->Error("Command line option %s is not understood",argv[I]);
|
||||
|
||||
// The option could be a single letter option prefixed by a no-..
|
||||
if (A->end() == true)
|
||||
{
|
||||
for (A = ArgList; A->end() == false && A->ShortOpt != *Opt; A++);
|
||||
|
||||
if (A->end() == true)
|
||||
return _error->Error("Command line option %s is not understood",argv[I]);
|
||||
}
|
||||
|
||||
// The option is not boolean
|
||||
if (A->IsBoolean() == false)
|
||||
return _error->Error("Command line option %s is not boolean",argv[I]);
|
||||
PreceedMatch = true;
|
||||
}
|
||||
|
||||
// Deal with it.
|
||||
OptEnd--;
|
||||
if (HandleOpt(I,argc,argv,OptEnd,A,PreceedMatch) == false)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy any remaining file names over
|
||||
for (; I != argc; I++)
|
||||
*Files++ = argv[I];
|
||||
*Files = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// CommandLine::HandleOpt - Handle a single option including all flags /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is a helper function for parser, it looks at a given argument
|
||||
and looks for specific patterns in the string, it gets tokanized
|
||||
-ruffly- like -*[yes|true|enable]-(o|longopt)[=][ ][argument] */
|
||||
bool CommandLine::HandleOpt(int &I,int argc,const char *argv[],
|
||||
const char *&Opt,Args *A,bool PreceedMatch)
|
||||
{
|
||||
const char *Argument = 0;
|
||||
bool CertainArg = false;
|
||||
int IncI = 0;
|
||||
|
||||
/* Determine the possible location of an option or 0 if their is
|
||||
no option */
|
||||
if (Opt[1] == 0 || (Opt[1] == '=' && Opt[2] == 0))
|
||||
{
|
||||
if (I + 1 < argc && argv[I+1][0] != '-')
|
||||
Argument = argv[I+1];
|
||||
|
||||
// Equals was specified but we fell off the end!
|
||||
if (Opt[1] == '=' && Argument == 0)
|
||||
return _error->Error("Option %s requires an argument.",argv[I]);
|
||||
if (Opt[1] == '=')
|
||||
CertainArg = true;
|
||||
|
||||
IncI = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Opt[1] == '=')
|
||||
{
|
||||
CertainArg = true;
|
||||
Argument = Opt + 2;
|
||||
}
|
||||
else
|
||||
Argument = Opt + 1;
|
||||
}
|
||||
|
||||
// Option is an argument set
|
||||
if ((A->Flags & HasArg) == HasArg)
|
||||
{
|
||||
if (Argument == 0)
|
||||
return _error->Error("Option %s requires an argument.",argv[I]);
|
||||
Opt += strlen(Opt);
|
||||
I += IncI;
|
||||
|
||||
// Parse a configuration file
|
||||
if ((A->Flags & ConfigFile) == ConfigFile)
|
||||
return ReadConfigFile(*Conf,Argument);
|
||||
|
||||
// Arbitary item specification
|
||||
if ((A->Flags & ArbItem) == ArbItem)
|
||||
{
|
||||
const char *J;
|
||||
for (J = Argument; *J != 0 && *J != '='; J++);
|
||||
if (*J == 0)
|
||||
return _error->Error("Option %s: Configuration item sepecification must have an =<val>.",argv[I]);
|
||||
|
||||
// = is trailing
|
||||
if (J[1] == 0)
|
||||
{
|
||||
if (I+1 >= argc)
|
||||
return _error->Error("Option %s: Configuration item sepecification must have an =<val>.",argv[I]);
|
||||
Conf->Set(string(Argument,J-Argument),string(argv[I++ +1]));
|
||||
}
|
||||
else
|
||||
Conf->Set(string(Argument,J-Argument),string(J+1));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *I = A->ConfName;
|
||||
for (; *I != 0 && *I != ' '; I++);
|
||||
if (*I == ' ')
|
||||
Conf->Set(string(A->ConfName,0,I-A->ConfName),string(I+1) + Argument);
|
||||
else
|
||||
Conf->Set(A->ConfName,string(I) + Argument);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Option is an integer level
|
||||
if ((A->Flags & IntLevel) == IntLevel)
|
||||
{
|
||||
// There might be an argument
|
||||
if (Argument != 0)
|
||||
{
|
||||
char *EndPtr;
|
||||
unsigned long Value = strtol(Argument,&EndPtr,10);
|
||||
|
||||
// Conversion failed and the argument was specified with an =s
|
||||
if (EndPtr == Argument && CertainArg == true)
|
||||
return _error->Error("Option %s requires an integer argument, not '%s'",argv[I],Argument);
|
||||
|
||||
// Conversion was ok, set the value and return
|
||||
if (EndPtr != 0 && EndPtr != Argument && *EndPtr == 0)
|
||||
{
|
||||
Conf->Set(A->ConfName,Value);
|
||||
Opt += strlen(Opt);
|
||||
I += IncI;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Increase the level
|
||||
Conf->Set(A->ConfName,Conf->FindI(A->ConfName)+1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Option is a boolean
|
||||
int Sense = -1; // -1 is unspecified, 0 is yes 1 is no
|
||||
|
||||
// Look for an argument.
|
||||
while (1)
|
||||
{
|
||||
// Look at preceeding text
|
||||
char Buffer[300];
|
||||
if (Argument == 0)
|
||||
{
|
||||
if (PreceedMatch == false)
|
||||
break;
|
||||
|
||||
if (strlen(argv[I]) >= sizeof(Buffer))
|
||||
return _error->Error("Option '%s' is too long",argv[I]);
|
||||
|
||||
// Skip the leading dash
|
||||
const char *J = argv[I];
|
||||
for (; *J != 0 && *J == '-'; J++);
|
||||
|
||||
const char *JEnd = J;
|
||||
for (; *JEnd != 0 && *JEnd != '-'; JEnd++);
|
||||
if (*JEnd != 0)
|
||||
{
|
||||
strncpy(Buffer,J,JEnd - J);
|
||||
Buffer[JEnd - J] = 0;
|
||||
Argument = Buffer;
|
||||
CertainArg = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for boolean
|
||||
Sense = StringToBool(Argument);
|
||||
if (Sense >= 0)
|
||||
{
|
||||
// Eat the argument
|
||||
if (Argument != Buffer)
|
||||
{
|
||||
Opt += strlen(Opt);
|
||||
I += IncI;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (CertainArg == true)
|
||||
return _error->Error("Sense %s is not understood, try true or false.",Argument);
|
||||
|
||||
Argument = 0;
|
||||
}
|
||||
|
||||
// Indeterminate sense depends on the flag
|
||||
if (Sense == -1)
|
||||
{
|
||||
if ((A->Flags & InvBoolean) == InvBoolean)
|
||||
Sense = 0;
|
||||
else
|
||||
Sense = 1;
|
||||
}
|
||||
|
||||
Conf->Set(A->ConfName,Sense);
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// CommandLine::FileSize - Count the number of filenames /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
unsigned int CommandLine::FileSize() const
|
||||
{
|
||||
unsigned int Count = 0;
|
||||
for (const char **I = FileList; I != 0 && *I != 0; I++)
|
||||
Count++;
|
||||
return Count;
|
||||
}
|
||||
/*}}}*/
|
||||
// CommandLine::DispatchArg - Do something with the first arg /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch)
|
||||
{
|
||||
int I;
|
||||
for (I = 0; Map[I].Match != 0; I++)
|
||||
{
|
||||
if (strcmp(FileList[0],Map[I].Match) == 0)
|
||||
{
|
||||
bool Res = Map[I].Handler(*this);
|
||||
if (Res == false && _error->PendingError() == false)
|
||||
_error->Error("Handler silently failed");
|
||||
return Res;
|
||||
}
|
||||
}
|
||||
|
||||
// No matching name
|
||||
if (Map[I].Match == 0)
|
||||
{
|
||||
if (NoMatch == true)
|
||||
_error->Error("Invalid operation %s",FileList[0]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
106
apt/apt-pkg/contrib/cmndline.h
Normal file
106
apt/apt-pkg/contrib/cmndline.h
Normal file
@ -0,0 +1,106 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: cmndline.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Command Line Class - Sophisticated command line parser
|
||||
|
||||
This class provides a unified command line parser/option handliner/
|
||||
configuration mechanism. It allows the caller to specify the option
|
||||
set and map the option set into the configuration class or other
|
||||
special functioning.
|
||||
|
||||
Filenames are stripped from the option stream and put into their
|
||||
own array.
|
||||
|
||||
The argument descriptor array can be initialized as:
|
||||
|
||||
CommandLine::Args Args[] =
|
||||
{{'q',"quiet","apt::get::quiet",CommandLine::IntLevel},
|
||||
{0,0,0,0}};
|
||||
|
||||
The flags mean,
|
||||
HasArg - Means the argument has a value
|
||||
IntLevel - Means the argument is an integer level indication, the
|
||||
following -qqqq (+3) -q5 (=5) -q=5 (=5) are valid
|
||||
Boolean - Means it is true/false or yes/no.
|
||||
-d (true) --no-d (false) --yes-d (true)
|
||||
--long (true) --no-long (false) --yes-long (true)
|
||||
-d=yes (true) -d=no (false) Words like enable, disable,
|
||||
true false, yes no and on off are recognized in logical
|
||||
places.
|
||||
InvBoolean - Same as boolean but the case with no specified sense
|
||||
(first case) is set to false.
|
||||
ConfigFile - Means this flag should be interprited as the name of
|
||||
a config file to read in at this point in option processing.
|
||||
Implies HasArg.
|
||||
ArbItem - Means the item is an arbitary configuration string of
|
||||
the form item=value, where item is passed directly
|
||||
to the configuration class.
|
||||
The default, if the flags are 0 is to use Boolean
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_CMNDLINE_H
|
||||
#define PKGLIB_CMNDLINE_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/cmndline.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/configuration.h>
|
||||
|
||||
class CommandLine
|
||||
{
|
||||
public:
|
||||
struct Args;
|
||||
struct Dispatch;
|
||||
|
||||
protected:
|
||||
|
||||
Args *ArgList;
|
||||
Configuration *Conf;
|
||||
bool HandleOpt(int &I,int argc,const char *argv[],
|
||||
const char *&Opt,Args *A,bool PreceedeMatch = false);
|
||||
|
||||
public:
|
||||
|
||||
enum AFlags
|
||||
{
|
||||
HasArg = (1 << 0),
|
||||
IntLevel = (1 << 1),
|
||||
Boolean = (1 << 2),
|
||||
InvBoolean = (1 << 3),
|
||||
ConfigFile = (1 << 4) | HasArg,
|
||||
ArbItem = (1 << 5) | HasArg
|
||||
};
|
||||
|
||||
const char **FileList;
|
||||
|
||||
bool Parse(int argc,const char **argv);
|
||||
void ShowHelp();
|
||||
unsigned int FileSize() const;
|
||||
bool DispatchArg(Dispatch *List,bool NoMatch = true);
|
||||
|
||||
CommandLine(Args *AList,Configuration *Conf);
|
||||
~CommandLine();
|
||||
};
|
||||
|
||||
struct CommandLine::Args
|
||||
{
|
||||
char ShortOpt;
|
||||
const char *LongOpt;
|
||||
const char *ConfName;
|
||||
unsigned long Flags;
|
||||
|
||||
inline bool end() {return ShortOpt == 0 && LongOpt == 0;};
|
||||
inline bool IsBoolean() {return Flags == 0 || (Flags & (Boolean|InvBoolean)) != 0;};
|
||||
};
|
||||
|
||||
struct CommandLine::Dispatch
|
||||
{
|
||||
const char *Match;
|
||||
bool (*Handler)(CommandLine &);
|
||||
};
|
||||
|
||||
#endif
|
665
apt/apt-pkg/contrib/configuration.cc
Normal file
665
apt/apt-pkg/contrib/configuration.cc
Normal file
@ -0,0 +1,665 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: configuration.cc,v 1.2 2000/10/30 18:49:49 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Configuration Class
|
||||
|
||||
This class provides a configuration file and command line parser
|
||||
for a tree-oriented configuration environment. All runtime configuration
|
||||
is stored in here.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/configuration.h"
|
||||
#endif
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fstream.h>
|
||||
/*}}}*/
|
||||
|
||||
Configuration *_config = new Configuration;
|
||||
|
||||
// Configuration::Configuration - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
Configuration::Configuration() : ToFree(true)
|
||||
{
|
||||
Root = new Item;
|
||||
}
|
||||
Configuration::Configuration(const Item *Root) : Root((Item *)Root), ToFree(false)
|
||||
{
|
||||
};
|
||||
|
||||
/*}}}*/
|
||||
// Configuration::~Configuration - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
Configuration::~Configuration()
|
||||
{
|
||||
if (ToFree == false)
|
||||
return;
|
||||
|
||||
Item *Top = Root;
|
||||
for (; Top != 0;)
|
||||
{
|
||||
if (Top->Child != 0)
|
||||
{
|
||||
Top = Top->Child;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (Top != 0 && Top->Next == 0)
|
||||
{
|
||||
Item *Parent = Top->Parent;
|
||||
delete Top;
|
||||
Top = Parent;
|
||||
}
|
||||
if (Top != 0)
|
||||
{
|
||||
Item *Next = Top->Next;
|
||||
delete Top;
|
||||
Top = Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Lookup - Lookup a single item /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This will lookup a single item by name below another item. It is a
|
||||
helper function for the main lookup function */
|
||||
Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
|
||||
unsigned long Len,bool Create)
|
||||
{
|
||||
int Res = 1;
|
||||
Item *I = Head->Child;
|
||||
Item **Last = &Head->Child;
|
||||
|
||||
// Empty strings match nothing. They are used for lists.
|
||||
if (Len != 0)
|
||||
{
|
||||
for (; I != 0; Last = &I->Next, I = I->Next)
|
||||
if ((Res = stringcasecmp(I->Tag.begin(),I->Tag.end(),S,S + Len)) == 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
for (; I != 0; Last = &I->Next, I = I->Next);
|
||||
|
||||
if (Res == 0)
|
||||
return I;
|
||||
if (Create == false)
|
||||
return 0;
|
||||
|
||||
I = new Item;
|
||||
I->Tag = string(S,Len);
|
||||
I->Next = *Last;
|
||||
I->Parent = Head;
|
||||
*Last = I;
|
||||
return I;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Lookup - Lookup a fully scoped item /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This performs a fully scoped lookup of a given name, possibly creating
|
||||
new items */
|
||||
Configuration::Item *Configuration::Lookup(const char *Name,bool Create)
|
||||
{
|
||||
if (Name == 0)
|
||||
return Root->Child;
|
||||
|
||||
const char *Start = Name;
|
||||
const char *End = Start + strlen(Name);
|
||||
const char *TagEnd = Name;
|
||||
Item *Itm = Root;
|
||||
for (; End - TagEnd >= 2; TagEnd++)
|
||||
{
|
||||
if (TagEnd[0] == ':' && TagEnd[1] == ':')
|
||||
{
|
||||
Itm = Lookup(Itm,Start,TagEnd - Start,Create);
|
||||
if (Itm == 0)
|
||||
return 0;
|
||||
TagEnd = Start = TagEnd + 2;
|
||||
}
|
||||
}
|
||||
|
||||
// This must be a trailing ::, we create unique items in a list
|
||||
if (End - Start == 0)
|
||||
{
|
||||
if (Create == false)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Itm = Lookup(Itm,Start,End - Start,Create);
|
||||
return Itm;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Find - Find a value /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string Configuration::Find(const char *Name,const char *Default) const
|
||||
{
|
||||
const Item *Itm = Lookup(Name);
|
||||
if (Itm == 0 || Itm->Value.empty() == true)
|
||||
{
|
||||
if (Default == 0)
|
||||
return string();
|
||||
else
|
||||
return Default;
|
||||
}
|
||||
|
||||
return Itm->Value;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::FindFile - Find a Filename /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Directories are stored as the base dir in the Parent node and the
|
||||
sub directory in sub nodes with the final node being the end filename
|
||||
*/
|
||||
string Configuration::FindFile(const char *Name,const char *Default) const
|
||||
{
|
||||
const Item *Itm = Lookup(Name);
|
||||
if (Itm == 0 || Itm->Value.empty() == true)
|
||||
{
|
||||
if (Default == 0)
|
||||
return string();
|
||||
else
|
||||
return Default;
|
||||
}
|
||||
|
||||
string val = Itm->Value;
|
||||
while (Itm->Parent != 0 && Itm->Parent->Value.empty() == false)
|
||||
{
|
||||
// Absolute
|
||||
if (val[0] == '/')
|
||||
break;
|
||||
|
||||
// ~/foo or ./foo
|
||||
if ((val[0] == '~' || val[0] == '.') && val[1] == '/')
|
||||
break;
|
||||
|
||||
// ../foo
|
||||
if (val[0] == '.' && val[1] == '.' && val[2] == '/')
|
||||
break;
|
||||
|
||||
if (Itm->Parent->Value.end()[-1] != '/')
|
||||
val.insert(0, "/");
|
||||
|
||||
val.insert(0, Itm->Parent->Value);
|
||||
Itm = Itm->Parent;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::FindDir - Find a directory name /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is like findfile execept the result is terminated in a / */
|
||||
string Configuration::FindDir(const char *Name,const char *Default) const
|
||||
{
|
||||
string Res = FindFile(Name,Default);
|
||||
if (Res.end()[-1] != '/')
|
||||
return Res + '/';
|
||||
return Res;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::FindI - Find an integer value /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
int Configuration::FindI(const char *Name,int Default) const
|
||||
{
|
||||
const Item *Itm = Lookup(Name);
|
||||
if (Itm == 0 || Itm->Value.empty() == true)
|
||||
return Default;
|
||||
|
||||
char *End;
|
||||
int Res = strtol(Itm->Value.c_str(),&End,0);
|
||||
if (End == Itm->Value.c_str())
|
||||
return Default;
|
||||
|
||||
return Res;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::FindB - Find a boolean type /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool Configuration::FindB(const char *Name,bool Default) const
|
||||
{
|
||||
const Item *Itm = Lookup(Name);
|
||||
if (Itm == 0 || Itm->Value.empty() == true)
|
||||
return Default;
|
||||
|
||||
return StringToBool(Itm->Value,Default);
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::FindAny - Find an arbitrary type /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* a key suffix of /f, /d, /b or /i calls Find{File,Dir,B,I} */
|
||||
string Configuration::FindAny(const char *Name,const char *Default) const
|
||||
{
|
||||
string key = Name;
|
||||
char type = 0;
|
||||
|
||||
if (key.size() > 2 && key.end()[-2] == '/')
|
||||
{
|
||||
type = key.end()[-1];
|
||||
key.resize(key.size() - 2);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// file
|
||||
case 'f':
|
||||
return FindFile(key.c_str(), Default);
|
||||
|
||||
// directory
|
||||
case 'd':
|
||||
return FindDir(key.c_str(), Default);
|
||||
|
||||
// bool
|
||||
case 'b':
|
||||
return FindB(key, Default) ? "true" : "false";
|
||||
|
||||
// int
|
||||
case 'i':
|
||||
{
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf)-1, "%d", FindI(key, Default));
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback
|
||||
return Find(Name, Default);
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::CndSet - Conditinal Set a value /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This will not overwrite */
|
||||
void Configuration::CndSet(const char *Name,string Value)
|
||||
{
|
||||
Item *Itm = Lookup(Name,true);
|
||||
if (Itm == 0)
|
||||
return;
|
||||
if (Itm->Value.empty() == true)
|
||||
Itm->Value = Value;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Set - Set a value /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void Configuration::Set(const char *Name,string Value)
|
||||
{
|
||||
Item *Itm = Lookup(Name,true);
|
||||
if (Itm == 0)
|
||||
return;
|
||||
Itm->Value = Value;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Set - Set an integer value /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void Configuration::Set(const char *Name,int Value)
|
||||
{
|
||||
Item *Itm = Lookup(Name,true);
|
||||
if (Itm == 0)
|
||||
return;
|
||||
char S[300];
|
||||
snprintf(S,sizeof(S),"%i",Value);
|
||||
Itm->Value = S;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Clear - Clear an entire tree /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void Configuration::Clear(string Name)
|
||||
{
|
||||
Item *Top = Lookup(Name.c_str(),false);
|
||||
if (Top == 0)
|
||||
return;
|
||||
|
||||
Top->Value = string();
|
||||
Item *Stop = Top;
|
||||
Top = Top->Child;
|
||||
Stop->Child = 0;
|
||||
for (; Top != 0;)
|
||||
{
|
||||
if (Top->Child != 0)
|
||||
{
|
||||
Top = Top->Child;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (Top != 0 && Top->Next == 0)
|
||||
{
|
||||
if (Top == Stop)
|
||||
return;
|
||||
Item *Tmp = Top;
|
||||
Top = Top->Parent;
|
||||
delete Tmp;
|
||||
}
|
||||
|
||||
Item *Tmp = Top;
|
||||
if (Top != 0)
|
||||
Top = Top->Next;
|
||||
delete Tmp;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Exists - Returns true if the Name exists /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool Configuration::Exists(const char *Name) const
|
||||
{
|
||||
const Item *Itm = Lookup(Name);
|
||||
if (Itm == 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::ExistsAny - Returns true if the Name, possibly /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* qualified by /[fdbi] exists */
|
||||
bool Configuration::ExistsAny(const char *Name) const
|
||||
{
|
||||
string key = Name;
|
||||
|
||||
if (key.size() > 2 && key.end()[-2] == '/' &&
|
||||
key.find_first_of("fdbi",key.size()-1) < key.size())
|
||||
{
|
||||
key.resize(key.size() - 2);
|
||||
if (Exists(key.c_str()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return Exists(Name);
|
||||
}
|
||||
/*}}}*/
|
||||
// Configuration::Dump - Dump the config /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Dump the entire configuration space */
|
||||
void Configuration::Dump()
|
||||
{
|
||||
/* Write out all of the configuration directives by walking the
|
||||
configuration tree */
|
||||
const Configuration::Item *Top = Tree(0);
|
||||
for (; Top != 0;)
|
||||
{
|
||||
clog << Top->FullTag() << " \"" << Top->Value << "\";" << endl;
|
||||
|
||||
if (Top->Child != 0)
|
||||
{
|
||||
Top = Top->Child;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (Top != 0 && Top->Next == 0)
|
||||
Top = Top->Parent;
|
||||
if (Top != 0)
|
||||
Top = Top->Next;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// Configuration::Item::FullTag - Return the fully scoped tag /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Stop sets an optional max recursion depth if this item is being viewed as
|
||||
part of a sub tree. */
|
||||
string Configuration::Item::FullTag(const Item *Stop) const
|
||||
{
|
||||
if (Parent == 0 || Parent->Parent == 0 || Parent == Stop)
|
||||
return Tag;
|
||||
return Parent->FullTag(Stop) + "::" + Tag;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// ReadConfigFile - Read a configuration file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The configuration format is very much like the named.conf format
|
||||
used in bind8, in fact this routine can parse most named.conf files.
|
||||
Sectional config files are like bind's named.conf where there are
|
||||
sections like 'zone "foo.org" { .. };' This causes each section to be
|
||||
added in with a tag like "zone::foo.org" instead of being split
|
||||
tag/value. */
|
||||
bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional,
|
||||
unsigned Depth)
|
||||
{
|
||||
// Open the stream for reading
|
||||
ifstream F(FName.c_str(),ios::in | ios::nocreate);
|
||||
if (!F != 0)
|
||||
return _error->Errno("ifstream::ifstream","Opening configuration file %s",FName.c_str());
|
||||
|
||||
char Buffer[300];
|
||||
string LineBuffer;
|
||||
string Stack[100];
|
||||
unsigned int StackPos = 0;
|
||||
|
||||
// Parser state
|
||||
string ParentTag;
|
||||
|
||||
int CurLine = 0;
|
||||
bool InComment = false;
|
||||
while (F.eof() == false)
|
||||
{
|
||||
F.getline(Buffer,sizeof(Buffer));
|
||||
CurLine++;
|
||||
_strtabexpand(Buffer,sizeof(Buffer));
|
||||
_strstrip(Buffer);
|
||||
|
||||
// Multi line comment
|
||||
if (InComment == true)
|
||||
{
|
||||
for (const char *I = Buffer; *I != 0; I++)
|
||||
{
|
||||
if (*I == '*' && I[1] == '/')
|
||||
{
|
||||
memmove(Buffer,I+2,strlen(I+2) + 1);
|
||||
InComment = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (InComment == true)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Discard single line comments
|
||||
bool InQuote = false;
|
||||
for (char *I = Buffer; *I != 0; I++)
|
||||
{
|
||||
if (*I == '"')
|
||||
InQuote = !InQuote;
|
||||
if (InQuote == true)
|
||||
continue;
|
||||
|
||||
if (*I == '/' && I[1] == '/')
|
||||
{
|
||||
*I = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for multi line comments
|
||||
InQuote = false;
|
||||
for (char *I = Buffer; *I != 0; I++)
|
||||
{
|
||||
if (*I == '"')
|
||||
InQuote = !InQuote;
|
||||
if (InQuote == true)
|
||||
continue;
|
||||
|
||||
if (*I == '/' && I[1] == '*')
|
||||
{
|
||||
InComment = true;
|
||||
for (char *J = Buffer; *J != 0; J++)
|
||||
{
|
||||
if (*J == '*' && J[1] == '/')
|
||||
{
|
||||
memmove(I,J+2,strlen(J+2) + 1);
|
||||
InComment = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (InComment == true)
|
||||
{
|
||||
*I = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Blank
|
||||
if (Buffer[0] == 0)
|
||||
continue;
|
||||
|
||||
// We now have a valid line fragment
|
||||
InQuote = false;
|
||||
for (char *I = Buffer; *I != 0;)
|
||||
{
|
||||
if (*I == '"')
|
||||
InQuote = !InQuote;
|
||||
|
||||
if (InQuote == false && (*I == '{' || *I == ';' || *I == '}'))
|
||||
{
|
||||
// Put the last fragment into the buffer
|
||||
char *Start = Buffer;
|
||||
char *Stop = I;
|
||||
for (; Start != I && isspace(*Start) != 0; Start++);
|
||||
for (; Stop != Start && isspace(Stop[-1]) != 0; Stop--);
|
||||
if (LineBuffer.empty() == false && Stop - Start != 0)
|
||||
LineBuffer += ' ';
|
||||
LineBuffer += string(Start,Stop - Start);
|
||||
|
||||
// Remove the fragment
|
||||
char TermChar = *I;
|
||||
memmove(Buffer,I + 1,strlen(I + 1) + 1);
|
||||
I = Buffer;
|
||||
|
||||
// Syntax Error
|
||||
if (TermChar == '{' && LineBuffer.empty() == true)
|
||||
return _error->Error("Syntax error %s:%u: Block starts with no name.",FName.c_str(),CurLine);
|
||||
|
||||
// No string on this line
|
||||
if (LineBuffer.empty() == true)
|
||||
{
|
||||
if (TermChar == '}')
|
||||
{
|
||||
if (StackPos == 0)
|
||||
ParentTag = string();
|
||||
else
|
||||
ParentTag = Stack[--StackPos];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse off the tag
|
||||
string Tag;
|
||||
const char *Pos = LineBuffer.c_str();
|
||||
if (ParseQuoteWord(Pos,Tag) == false)
|
||||
return _error->Error("Syntax error %s:%u: Malformed Tag",FName.c_str(),CurLine);
|
||||
|
||||
// Parse off the word
|
||||
string Word;
|
||||
if (ParseCWord(Pos,Word) == false &&
|
||||
ParseQuoteWord(Pos,Word) == false)
|
||||
{
|
||||
if (TermChar != '{')
|
||||
{
|
||||
Word = Tag;
|
||||
Tag = "";
|
||||
}
|
||||
}
|
||||
if (strlen(Pos) != 0)
|
||||
return _error->Error("Syntax error %s:%u: Extra junk after value",FName.c_str(),CurLine);
|
||||
|
||||
// Go down a level
|
||||
if (TermChar == '{')
|
||||
{
|
||||
if (StackPos <= 100)
|
||||
Stack[StackPos++] = ParentTag;
|
||||
|
||||
/* Make sectional tags incorperate the section into the
|
||||
tag string */
|
||||
if (AsSectional == true && Word.empty() == false)
|
||||
{
|
||||
Tag += "::" ;
|
||||
Tag += Word;
|
||||
Word = "";
|
||||
}
|
||||
|
||||
if (ParentTag.empty() == true)
|
||||
ParentTag = Tag;
|
||||
else
|
||||
ParentTag += string("::") + Tag;
|
||||
Tag = string();
|
||||
}
|
||||
|
||||
// Generate the item name
|
||||
string Item;
|
||||
if (ParentTag.empty() == true)
|
||||
Item = Tag;
|
||||
else
|
||||
{
|
||||
if (TermChar != '{' || Tag.empty() == false)
|
||||
Item = ParentTag + "::" + Tag;
|
||||
else
|
||||
Item = ParentTag;
|
||||
}
|
||||
|
||||
// Specials
|
||||
if (Tag[0] == '#')
|
||||
{
|
||||
if (ParentTag.empty() == false)
|
||||
return _error->Error("Syntax error %s:%u: Directives can only be done at the top level",FName.c_str(),CurLine);
|
||||
Tag.erase(Tag.begin());
|
||||
if (Tag == "clear")
|
||||
Conf.Clear(Word);
|
||||
else if (Tag == "include")
|
||||
{
|
||||
if (Depth > 10)
|
||||
return _error->Error("Syntax error %s:%u: Too many nested includes",FName.c_str(),CurLine);
|
||||
if (ReadConfigFile(Conf,Word,AsSectional,Depth+1) == false)
|
||||
return _error->Error("Syntax error %s:%u: Included from here",FName.c_str(),CurLine);
|
||||
}
|
||||
else
|
||||
return _error->Error("Syntax error %s:%u: Unsupported directive '%s'",FName.c_str(),CurLine,Tag.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the item in the configuration class
|
||||
Conf.Set(Item,Word);
|
||||
}
|
||||
|
||||
// Empty the buffer
|
||||
LineBuffer = string();
|
||||
|
||||
// Move up a tag, but only if there is no bit to parse
|
||||
if (TermChar == '}')
|
||||
{
|
||||
if (StackPos == 0)
|
||||
ParentTag = string();
|
||||
else
|
||||
ParentTag = Stack[--StackPos];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
I++;
|
||||
}
|
||||
|
||||
// Store the fragment
|
||||
const char *Stripd = _strstrip(Buffer);
|
||||
if (*Stripd != 0 && LineBuffer.empty() == false)
|
||||
LineBuffer += " ";
|
||||
LineBuffer += Stripd;
|
||||
}
|
||||
|
||||
if (LineBuffer.empty() == false)
|
||||
return _error->Error("Syntax error %s:%u: Extra junk at end of file",FName.c_str(),CurLine);
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
103
apt/apt-pkg/contrib/configuration.h
Normal file
103
apt/apt-pkg/contrib/configuration.h
Normal file
@ -0,0 +1,103 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: configuration.h,v 1.2 2000/10/30 18:49:49 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Configuration Class
|
||||
|
||||
This class provides a configuration file and command line parser
|
||||
for a tree-oriented configuration environment. All runtime configuration
|
||||
is stored in here.
|
||||
|
||||
Each configuration name is given as a fully scoped string such as
|
||||
Foo::Bar
|
||||
And has associated with it a text string. The Configuration class only
|
||||
provides storage and lookup for this tree, other classes provide
|
||||
configuration file formats (and parsers/emitters if needed).
|
||||
|
||||
Most things can get by quite happily with,
|
||||
cout << _config->Find("Foo::Bar") << endl;
|
||||
|
||||
A special extension, support for ordered lists is provided by using the
|
||||
special syntax, "block::list::" the trailing :: designates the
|
||||
item as a list. To access the list you must use the tree function on
|
||||
"block::list".
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_CONFIGURATION_H
|
||||
#define PKGLIB_CONFIGURATION_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/configuration.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
class Configuration
|
||||
{
|
||||
public:
|
||||
|
||||
struct Item
|
||||
{
|
||||
string Value;
|
||||
string Tag;
|
||||
Item *Parent;
|
||||
Item *Child;
|
||||
Item *Next;
|
||||
|
||||
string FullTag(const Item *Stop = 0) const;
|
||||
|
||||
Item() : Parent(0), Child(0), Next(0) {};
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Item *Root;
|
||||
bool ToFree;
|
||||
|
||||
Item *Lookup(Item *Head,const char *S,unsigned long Len,bool Create);
|
||||
Item *Lookup(const char *Name,bool Create);
|
||||
inline const Item *Lookup(const char *Name) const
|
||||
{
|
||||
return ((Configuration *)this)->Lookup(Name,false);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
string Find(const char *Name,const char *Default = 0) const;
|
||||
string Find(string Name,const char *Default = 0) const {return Find(Name.c_str(),Default);};
|
||||
string FindFile(const char *Name,const char *Default = 0) const;
|
||||
string FindDir(const char *Name,const char *Default = 0) const;
|
||||
int FindI(const char *Name,int Default = 0) const;
|
||||
int FindI(string Name,bool Default = 0) const {return FindI(Name.c_str(),Default);};
|
||||
bool FindB(const char *Name,bool Default = false) const;
|
||||
bool FindB(string Name,bool Default = false) const {return FindB(Name.c_str(),Default);};
|
||||
string FindAny(const char *Name,const char *Default = 0) const;
|
||||
|
||||
inline void Set(string Name,string Value) {Set(Name.c_str(),Value);};
|
||||
void CndSet(const char *Name,string Value);
|
||||
void Set(const char *Name,string Value);
|
||||
void Set(const char *Name,int Value);
|
||||
|
||||
inline bool Exists(string Name) const {return Exists(Name.c_str());};
|
||||
bool Exists(const char *Name) const;
|
||||
bool ExistsAny(const char *Name) const;
|
||||
|
||||
void Clear(string Name);
|
||||
|
||||
inline const Item *Tree(const char *Name) const {return Lookup(Name);};
|
||||
|
||||
void Dump();
|
||||
|
||||
Configuration(const Item *Root);
|
||||
Configuration();
|
||||
~Configuration();
|
||||
};
|
||||
|
||||
extern Configuration *_config;
|
||||
|
||||
bool ReadConfigFile(Configuration &Conf,string FName,bool AsSectional = false,
|
||||
unsigned Depth = 0);
|
||||
|
||||
#endif
|
76
apt/apt-pkg/contrib/crc-16.cc
Normal file
76
apt/apt-pkg/contrib/crc-16.cc
Normal file
@ -0,0 +1,76 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: crc-16.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
CRC16 - Compute a 16bit crc very quickly
|
||||
|
||||
This was ripped out of the linux 2.2 kernel source (irda/crc.c) and
|
||||
is credited to ppp.c by Michael Callahan <callahan@maths.ox.ac.uk> and
|
||||
Al Longyear <longyear@netcom.com>
|
||||
|
||||
Modified by Jason Gunthorpe <jgg@debian.org> to fit the local coding
|
||||
style, this code is belived to be in the Public Domain.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/crc-16.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/crc-16.h>
|
||||
/*}}}*/
|
||||
|
||||
/*
|
||||
* This mysterious table is just the CRC of each possible byte. It can be
|
||||
* computed using the standard bit-at-a-time methods. The polynomial can
|
||||
* be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12.
|
||||
* Add the implicit x^16, and you have the standard CRC-CCITT.
|
||||
*/
|
||||
static unsigned short const crc16_table[256] =
|
||||
{
|
||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
||||
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
||||
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
||||
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
||||
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
||||
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
||||
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
||||
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
||||
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
||||
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
||||
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
||||
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
||||
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
||||
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
||||
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
||||
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
||||
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
||||
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
||||
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
||||
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
||||
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
||||
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
||||
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
||||
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
||||
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
||||
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
||||
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
||||
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
||||
};
|
||||
|
||||
/* Recompute the FCS with one more character appended. */
|
||||
#define CalcFCS(fcs, c) (((fcs) >> 8) ^ crc16_table[((fcs) ^ (c)) & 0xff])
|
||||
unsigned short AddCRC16(unsigned short fcs, void const *Buf,
|
||||
unsigned long len)
|
||||
{
|
||||
unsigned char const *buf = (unsigned char const *)Buf;
|
||||
while (len--)
|
||||
fcs = CalcFCS(fcs, *buf++);
|
||||
return fcs;
|
||||
}
|
21
apt/apt-pkg/contrib/crc-16.h
Normal file
21
apt/apt-pkg/contrib/crc-16.h
Normal file
@ -0,0 +1,21 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: crc-16.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
CRC16 - Compute a 16bit crc very quickly
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef APTPKG_CRC16_H
|
||||
#define APTPKG_CRC16_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/crc-16.h"
|
||||
#endif
|
||||
|
||||
#define INIT_FCS 0xffff
|
||||
unsigned short AddCRC16(unsigned short fcs, void const *buf,
|
||||
unsigned long len);
|
||||
|
||||
#endif
|
239
apt/apt-pkg/contrib/error.cc
Normal file
239
apt/apt-pkg/contrib/error.cc
Normal file
@ -0,0 +1,239 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: error.cc,v 1.4 2001/11/12 16:04:37 kojima 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 /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/error.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/error.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
/*}}}*/
|
||||
|
||||
// Global Error Object /*{{{*/
|
||||
/* If the implementation supports posix threads then the accessor function
|
||||
is compiled to be thread safe otherwise a non-safe version is used. A
|
||||
Per-Thread error object is maintained in much the same manner as libc
|
||||
manages errno */
|
||||
#if _POSIX_THREADS == 1 && defined(HAVE_PTHREAD)
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_key_t ErrorKey;
|
||||
static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
|
||||
static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
|
||||
|
||||
GlobalError *_GetErrorObj()
|
||||
{
|
||||
static pthread_once_t Once = PTHREAD_ONCE_INIT;
|
||||
pthread_once(&Once,KeyAlloc);
|
||||
|
||||
void *Res = pthread_getspecific(ErrorKey);
|
||||
if (Res == 0)
|
||||
pthread_setspecific(ErrorKey,Res = new GlobalError);
|
||||
return (GlobalError *)Res;
|
||||
}
|
||||
#else
|
||||
GlobalError *_GetErrorObj()
|
||||
{
|
||||
static GlobalError *Obj = new GlobalError;
|
||||
return Obj;
|
||||
}
|
||||
#endif
|
||||
/*}}}*/
|
||||
|
||||
// GlobalError::GlobalError - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
GlobalError::GlobalError() : List(0), 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];
|
||||
vsnprintf(S,sizeof(S),Description,args);
|
||||
snprintf(S + strlen(S),sizeof(S) - strlen(S),
|
||||
" - %s (%i %s)",Function,errno,strerror(errno));
|
||||
|
||||
// Put it on the list
|
||||
Item *Itm = new Item;
|
||||
Itm->Text = S;
|
||||
Itm->Error = true;
|
||||
Insert(Itm);
|
||||
|
||||
PendingFlag = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// GlobalError::WarningE - Get part of the warn 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::WarningE(const char *Function,const char *Description,...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args,Description);
|
||||
|
||||
// sprintf the description
|
||||
char S[400];
|
||||
vsnprintf(S,sizeof(S),Description,args);
|
||||
snprintf(S + strlen(S),sizeof(S) - strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
|
||||
|
||||
// Put it on the list
|
||||
Item *Itm = new Item;
|
||||
Itm->Text = S;
|
||||
Itm->Error = false;
|
||||
Insert(Itm);
|
||||
|
||||
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];
|
||||
vsnprintf(S,sizeof(S),Description,args);
|
||||
|
||||
// Put it on the list
|
||||
Item *Itm = new Item;
|
||||
Itm->Text = S;
|
||||
Itm->Error = true;
|
||||
Insert(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];
|
||||
vsnprintf(S,sizeof(S),Description,args);
|
||||
|
||||
// Put it on the list
|
||||
Item *Itm = new Item;
|
||||
Itm->Text = S;
|
||||
Itm->Error = false;
|
||||
Insert(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)
|
||||
{
|
||||
if (List == 0)
|
||||
return false;
|
||||
|
||||
bool Ret = List->Error;
|
||||
Text = List->Text;
|
||||
Item *Old = List;
|
||||
List = List->Next;
|
||||
delete Old;
|
||||
|
||||
// This really should check the list to see if only warnings are left..
|
||||
if (List == 0)
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// GlobalError::Discard - Discard /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void GlobalError::Discard()
|
||||
{
|
||||
while (List != 0)
|
||||
{
|
||||
Item *Old = List;
|
||||
List = List->Next;
|
||||
delete Old;
|
||||
}
|
||||
|
||||
PendingFlag = false;
|
||||
};
|
||||
/*}}}*/
|
||||
// GlobalError::Insert - Insert a new item at the end /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void GlobalError::Insert(Item *Itm)
|
||||
{
|
||||
if (0) {//akk don't leave this here or it will have evil side effects
|
||||
// on acquire methods
|
||||
cerr << Itm->Text.c_str() << endl;
|
||||
return;
|
||||
}
|
||||
Item **End = &List;
|
||||
for (Item *I = List; I != 0; I = I->Next)
|
||||
End = &I->Next;
|
||||
Itm->Next = *End;
|
||||
*End = Itm;
|
||||
}
|
||||
/*}}}*/
|
89
apt/apt-pkg/contrib/error.h
Normal file
89
apt/apt-pkg/contrib/error.h
Normal file
@ -0,0 +1,89 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: error.h,v 1.1.1.1 2000/08/10 12:42:39 kojima 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.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_ERROR_H
|
||||
#define PKGLIB_ERROR_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/error.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
class GlobalError
|
||||
{
|
||||
struct Item
|
||||
{
|
||||
string Text;
|
||||
bool Error;
|
||||
Item *Next;
|
||||
};
|
||||
|
||||
Item *List;
|
||||
bool PendingFlag;
|
||||
void Insert(Item *I);
|
||||
|
||||
public:
|
||||
|
||||
// Call to generate an error from a library call.
|
||||
bool Errno(const char *Function,const char *Description,...);
|
||||
bool WarningE(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 == 0;};
|
||||
bool PopMessage(string &Text);
|
||||
void Discard();
|
||||
|
||||
// Usefull routine to dump to cerr
|
||||
void DumpErrors();
|
||||
|
||||
GlobalError();
|
||||
};
|
||||
|
||||
// The 'extra-ansi' syntax is used to help with collisions.
|
||||
GlobalError *_GetErrorObj();
|
||||
#define _error _GetErrorObj()
|
||||
|
||||
#endif
|
569
apt/apt-pkg/contrib/fileutl.cc
Normal file
569
apt/apt-pkg/contrib/fileutl.cc
Normal file
@ -0,0 +1,569 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: fileutl.cc,v 1.3 2000/09/26 14:22:14 kojima 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 /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/fileutl.h"
|
||||
#endif
|
||||
#include <apt-pkg/fileutl.h>
|
||||
#include <apt-pkg/error.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
/*}}}*/
|
||||
|
||||
// CopyFile - Buffered copy of a file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The caller is expected to set things so that failure causes erasure */
|
||||
bool CopyFile(FileFd &From,FileFd &To)
|
||||
{
|
||||
if (From.IsOpen() == false || To.IsOpen() == false)
|
||||
return false;
|
||||
|
||||
// Buffered copy between fds
|
||||
unsigned char *Buf = new unsigned char[64000];
|
||||
unsigned long Size = From.Size();
|
||||
while (Size != 0)
|
||||
{
|
||||
unsigned long ToRead = Size;
|
||||
if (Size > 64000)
|
||||
ToRead = 64000;
|
||||
|
||||
if (From.Read(Buf,ToRead) == false ||
|
||||
To.Write(Buf,ToRead) == false)
|
||||
{
|
||||
delete [] Buf;
|
||||
return false;
|
||||
}
|
||||
|
||||
Size -= ToRead;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// Read only .. cant have locking problems there.
|
||||
if (errno == EROFS)
|
||||
{
|
||||
_error->Warning("Not using locking for read only lock file %s",File.c_str());
|
||||
return dup(0); // Need something for the caller to close
|
||||
}
|
||||
|
||||
if (Errors == true)
|
||||
_error->Errno("open","Could not open lock file %s",File.c_str());
|
||||
return -1;
|
||||
}
|
||||
SetCloseExec(FD,true);
|
||||
|
||||
// Aquire a write lock
|
||||
struct flock fl;
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
if (fcntl(FD,F_SETLK,&fl) == -1)
|
||||
{
|
||||
if (errno == ENOLCK)
|
||||
{
|
||||
_error->Warning("Not using locking for nfs mounted lock file %s",File.c_str());
|
||||
return true;
|
||||
}
|
||||
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)-2) == 0)
|
||||
return "/";
|
||||
unsigned int Len = strlen(S);
|
||||
S[Len] = '/';
|
||||
S[Len+1] = 0;
|
||||
return S;
|
||||
}
|
||||
/*}}}*/
|
||||
// flNotDir - Strip the directory from the filename /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string flNotDir(string File)
|
||||
{
|
||||
string::size_type Res = File.rfind('/');
|
||||
if (Res == string::npos)
|
||||
return File;
|
||||
Res++;
|
||||
return string(File,Res,Res - File.length());
|
||||
}
|
||||
/*}}}*/
|
||||
// flNotFile - Strip the file from the directory name /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string flNotFile(string File)
|
||||
{
|
||||
string::size_type Res = File.rfind('/');
|
||||
if (Res == string::npos)
|
||||
return File;
|
||||
Res++;
|
||||
return string(File,0,Res);
|
||||
}
|
||||
/*}}}*/
|
||||
// flExtension - Return the extension for the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string flExtension(string File)
|
||||
{
|
||||
string::size_type Res = File.rfind('.');
|
||||
if (Res == string::npos)
|
||||
return File;
|
||||
Res++;
|
||||
return string(File,Res,Res - File.length());
|
||||
}
|
||||
/*}}}*/
|
||||
// flNoLink - If file is a symlink then deref it /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* If the name is not a link then the returned path is the input. */
|
||||
string flNoLink(string File)
|
||||
{
|
||||
struct stat St;
|
||||
if (lstat(File.c_str(),&St) != 0 || S_ISLNK(St.st_mode) == 0)
|
||||
return File;
|
||||
if (stat(File.c_str(),&St) != 0)
|
||||
return File;
|
||||
|
||||
/* Loop resolving the link. There is no need to limit the number of
|
||||
loops because the stat call above ensures that the symlink is not
|
||||
circular */
|
||||
char Buffer[1024];
|
||||
string NFile = File;
|
||||
while (1)
|
||||
{
|
||||
// Read the link
|
||||
int Res;
|
||||
if ((Res = readlink(NFile.c_str(),Buffer,sizeof(Buffer))) <= 0 ||
|
||||
(unsigned)Res >= sizeof(Buffer))
|
||||
return File;
|
||||
|
||||
// Append or replace the previous path
|
||||
Buffer[Res] = 0;
|
||||
if (Buffer[0] == '/')
|
||||
NFile = Buffer;
|
||||
else
|
||||
NFile = flNotFile(NFile) + Buffer;
|
||||
|
||||
// See if we are done
|
||||
if (lstat(NFile.c_str(),&St) != 0)
|
||||
return File;
|
||||
if (S_ISLNK(St.st_mode) == 0)
|
||||
return NFile;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// flCombine - Combine a file and a directory /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* If the file is an absolute path then it is just returned, otherwise
|
||||
the directory is pre-pended to it. */
|
||||
string flCombine(string Dir,string File)
|
||||
{
|
||||
if (File.empty() == true)
|
||||
return string();
|
||||
|
||||
if (File[0] == '/' || Dir.empty() == true)
|
||||
return File;
|
||||
if (File.length() >= 2 && File[0] == '.' && File[1] == '/')
|
||||
return File;
|
||||
if (Dir[Dir.length()-1] == '/')
|
||||
return Dir + File;
|
||||
return Dir + '/' + File;
|
||||
}
|
||||
/*}}}*/
|
||||
// SetCloseExec - Set the close on exec flag /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void SetCloseExec(int Fd,bool Close)
|
||||
{
|
||||
if (fcntl(Fd,F_SETFD,(Close == false)?0:FD_CLOEXEC) != 0)
|
||||
{
|
||||
cerr << "FATAL -> Could not set close on exec " << strerror(errno) << endl;
|
||||
exit(100);
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// SetNonBlock - Set the nonblocking flag /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void SetNonBlock(int Fd,bool Block)
|
||||
{
|
||||
int Flags = fcntl(Fd,F_GETFL) & (~O_NONBLOCK);
|
||||
if (fcntl(Fd,F_SETFL,Flags | ((Block == false)?0:O_NONBLOCK)) != 0)
|
||||
{
|
||||
cerr << "FATAL -> Could not set non-blocking flag " << strerror(errno) << endl;
|
||||
exit(100);
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// WaitFd - Wait for a FD to become readable /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This waits for a FD to become readable using select. It is useful for
|
||||
applications making use of non-blocking sockets. The timeout is
|
||||
in seconds. */
|
||||
bool WaitFd(int Fd,bool write,unsigned long timeout)
|
||||
{
|
||||
fd_set Set;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&Set);
|
||||
FD_SET(Fd,&Set);
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
if (write == true)
|
||||
{
|
||||
int Res;
|
||||
do
|
||||
{
|
||||
Res = select(Fd+1,0,&Set,0,(timeout != 0?&tv:0));
|
||||
}
|
||||
while (Res < 0 && errno == EINTR);
|
||||
|
||||
if (Res <= 0)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int Res;
|
||||
do
|
||||
{
|
||||
Res = select(Fd+1,&Set,0,0,(timeout != 0?&tv:0));
|
||||
}
|
||||
while (Res < 0 && errno == EINTR);
|
||||
|
||||
if (Res <= 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// ExecFork - Magical fork that sanitizes the context before execing /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is used if you want to cleanse the environment for the forked
|
||||
child, it fixes up the important signals and nukes all of the fds,
|
||||
otherwise acts like normal fork. */
|
||||
int ExecFork()
|
||||
{
|
||||
// Fork off the process
|
||||
pid_t Process = fork();
|
||||
if (Process < 0)
|
||||
{
|
||||
cerr << "FATAL -> Failed to fork." << endl;
|
||||
exit(100);
|
||||
}
|
||||
|
||||
// Spawn the subprocess
|
||||
if (Process == 0)
|
||||
{
|
||||
// Setup the signals
|
||||
signal(SIGPIPE,SIG_DFL);
|
||||
signal(SIGQUIT,SIG_DFL);
|
||||
signal(SIGINT,SIG_DFL);
|
||||
signal(SIGWINCH,SIG_DFL);
|
||||
signal(SIGCONT,SIG_DFL);
|
||||
signal(SIGTSTP,SIG_DFL);
|
||||
|
||||
// Close all of our FDs - just in case
|
||||
for (int K = 3; K != 40; K++)
|
||||
fcntl(K,F_SETFD,FD_CLOEXEC);
|
||||
}
|
||||
|
||||
return Process;
|
||||
}
|
||||
/*}}}*/
|
||||
// ExecWait - Fancy waitpid /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Waits for the given sub process. If Reap is set the no errors are
|
||||
generated. Otherwise a failed subprocess will generate a proper descriptive
|
||||
message */
|
||||
bool ExecWait(int Pid,const char *Name,bool Reap)
|
||||
{
|
||||
if (Pid <= 1)
|
||||
return true;
|
||||
|
||||
// Wait and collect the error code
|
||||
int Status;
|
||||
while (waitpid(Pid,&Status,0) != Pid)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (Reap == true)
|
||||
return false;
|
||||
|
||||
return _error->Error("Waited, for %s but it wasn't there",Name);
|
||||
}
|
||||
|
||||
|
||||
// Check for an error code.
|
||||
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
|
||||
{
|
||||
if (Reap == true)
|
||||
return false;
|
||||
if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
|
||||
return _error->Error("Sub-process %s recieved a segmentation fault.",Name);
|
||||
|
||||
if (WIFEXITED(Status) != 0)
|
||||
return _error->Error("Sub-process %s returned an error code (%u)",Name,WEXITSTATUS(Status));
|
||||
|
||||
return _error->Error("Sub-process %s exited unexpectedly",Name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// FileFd::Open - Open a file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The most commonly used open mode combinations are given with Mode */
|
||||
bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms)
|
||||
{
|
||||
Close();
|
||||
Flags = AutoClose;
|
||||
switch (Mode)
|
||||
{
|
||||
case ReadOnly:
|
||||
iFd = open(FileName.c_str(),O_RDONLY);
|
||||
break;
|
||||
|
||||
case WriteEmpty:
|
||||
{
|
||||
struct stat Buf;
|
||||
if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode))
|
||||
unlink(FileName.c_str());
|
||||
iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms);
|
||||
break;
|
||||
}
|
||||
|
||||
case WriteExists:
|
||||
iFd = open(FileName.c_str(),O_RDWR);
|
||||
break;
|
||||
|
||||
case WriteAny:
|
||||
iFd = open(FileName.c_str(),O_RDWR | O_CREAT,Perms);
|
||||
break;
|
||||
}
|
||||
|
||||
if (iFd < 0)
|
||||
return _error->Errno("open","Could not open file %s",FileName.c_str());
|
||||
|
||||
this->FileName = FileName;
|
||||
SetCloseExec(iFd,true);
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::~File - Closes the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* If the proper modes are selected then we close the Fd and possibly
|
||||
unlink the file on error. */
|
||||
FileFd::~FileFd()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Read - Read a bit of the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We are carefull to handle interruption by a signal while reading
|
||||
gracefully. */
|
||||
bool FileFd::Read(void *To,unsigned long Size,bool AllowEof)
|
||||
{
|
||||
int Res;
|
||||
errno = 0;
|
||||
do
|
||||
{
|
||||
Res = read(iFd,To,Size);
|
||||
if (Res < 0 && errno == EINTR)
|
||||
continue;
|
||||
if (Res < 0)
|
||||
{
|
||||
Flags |= Fail;
|
||||
return _error->Errno("read","Read error");
|
||||
}
|
||||
|
||||
To = (char *)To + Res;
|
||||
Size -= Res;
|
||||
}
|
||||
while (Res > 0 && Size > 0);
|
||||
|
||||
if (Size == 0)
|
||||
return true;
|
||||
|
||||
// Eof handling
|
||||
if (AllowEof == true)
|
||||
{
|
||||
Flags |= HitEof;
|
||||
return true;
|
||||
}
|
||||
|
||||
Flags |= Fail;
|
||||
return _error->Error("read, still have %u to read but none left",Size);
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Write - Write to the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool FileFd::Write(const void *From,unsigned long Size)
|
||||
{
|
||||
int Res;
|
||||
errno = 0;
|
||||
do
|
||||
{
|
||||
Res = write(iFd,From,Size);
|
||||
if (Res < 0 && errno == EINTR)
|
||||
continue;
|
||||
if (Res < 0)
|
||||
{
|
||||
Flags |= Fail;
|
||||
return _error->Errno("write","Write error");
|
||||
}
|
||||
|
||||
From = (char *)From + Res;
|
||||
Size -= Res;
|
||||
}
|
||||
while (Res > 0 && Size > 0);
|
||||
|
||||
if (Size == 0)
|
||||
return true;
|
||||
|
||||
Flags |= Fail;
|
||||
return _error->Error("write, still have %u to write but couldn't",Size);
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Seek - Seek in the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool FileFd::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;
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Skip - Seek in the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool FileFd::Skip(unsigned long Over)
|
||||
{
|
||||
if (lseek(iFd,Over,SEEK_CUR) < 0)
|
||||
{
|
||||
Flags |= Fail;
|
||||
return _error->Error("Unable to seek ahead %u",Over);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Truncate - Truncate the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool FileFd::Truncate(unsigned long To)
|
||||
{
|
||||
if (ftruncate(iFd,To) != 0)
|
||||
{
|
||||
Flags |= Fail;
|
||||
return _error->Error("Unable to truncate to %u",To);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Tell - Current seek position /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
unsigned long FileFd::Tell()
|
||||
{
|
||||
off_t Res = lseek(iFd,0,SEEK_CUR);
|
||||
if (Res == (off_t)-1)
|
||||
_error->Errno("lseek","Failed to determine the current file position");
|
||||
return Res;
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Size - Return the size of the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
unsigned long FileFd::Size()
|
||||
{
|
||||
struct stat Buf;
|
||||
if (fstat(iFd,&Buf) != 0)
|
||||
return _error->Errno("fstat","Unable to determine the file size");
|
||||
return Buf.st_size;
|
||||
}
|
||||
/*}}}*/
|
||||
// FileFd::Close - Close the file if the close flag is set /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool FileFd::Close()
|
||||
{
|
||||
bool Res = true;
|
||||
if ((Flags & AutoClose) == AutoClose)
|
||||
if (iFd >= 0 && close(iFd) != 0)
|
||||
Res &= _error->Errno("close","Problem closing the file");
|
||||
iFd = -1;
|
||||
|
||||
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;
|
||||
}
|
||||
/*}}}*/
|
90
apt/apt-pkg/contrib/fileutl.h
Normal file
90
apt/apt-pkg/contrib/fileutl.h
Normal file
@ -0,0 +1,90 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: fileutl.h,v 1.2 2000/09/26 14:22:14 kojima 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.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_FILEUTL_H
|
||||
#define PKGLIB_FILEUTL_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/fileutl.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
class FileFd
|
||||
{
|
||||
protected:
|
||||
int iFd;
|
||||
|
||||
enum LocalFlags {AutoClose = (1<<0),Fail = (1<<1),DelOnFail = (1<<2),
|
||||
HitEof = (1<<3)};
|
||||
unsigned long Flags;
|
||||
string FileName;
|
||||
|
||||
public:
|
||||
enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny};
|
||||
|
||||
bool Read(void *To,unsigned long Size,bool AllowEof = false);
|
||||
bool Write(const void *From,unsigned long Size);
|
||||
bool Seek(unsigned long To);
|
||||
bool Skip(unsigned long To);
|
||||
bool Truncate(unsigned long To);
|
||||
unsigned long Tell();
|
||||
unsigned long Size();
|
||||
bool Open(string FileName,OpenMode Mode,unsigned long Perms = 0666);
|
||||
bool Close();
|
||||
|
||||
// Simple manipulators
|
||||
inline int Fd() {return iFd;};
|
||||
inline void Fd(int fd) {iFd = fd;};
|
||||
inline bool IsOpen() {return iFd >= 0;};
|
||||
inline bool Failed() {return (Flags & Fail) == Fail;};
|
||||
inline void EraseOnFailure() {Flags |= DelOnFail;};
|
||||
inline void OpFail() {Flags |= Fail;};
|
||||
inline bool Eof() {return (Flags & HitEof) == HitEof;};
|
||||
inline string &Name() {return FileName;};
|
||||
|
||||
FileFd(string FileName,OpenMode Mode,unsigned long Perms = 0666) : iFd(-1),
|
||||
Flags(0)
|
||||
{
|
||||
Open(FileName,Mode,Perms);
|
||||
};
|
||||
FileFd(int Fd = -1) : iFd(Fd), Flags(AutoClose) {};
|
||||
FileFd(int Fd,bool) : iFd(Fd), Flags(0) {};
|
||||
virtual ~FileFd();
|
||||
};
|
||||
|
||||
bool CopyFile(FileFd &From,FileFd &To);
|
||||
int GetLock(string File,bool Errors = true);
|
||||
bool FileExists(string File);
|
||||
string SafeGetCWD();
|
||||
void SetCloseExec(int Fd,bool Close);
|
||||
void SetNonBlock(int Fd,bool Block);
|
||||
bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0);
|
||||
int ExecFork();
|
||||
bool ExecWait(int Pid,const char *Name,bool Reap = false);
|
||||
|
||||
// File string manipulators
|
||||
string flNotDir(string File);
|
||||
string flNotFile(string File);
|
||||
string flNoLink(string File);
|
||||
string flExtension(string File);
|
||||
string flCombine(string Dir,string File);
|
||||
|
||||
#endif
|
54
apt/apt-pkg/contrib/i18n.h
Normal file
54
apt/apt-pkg/contrib/i18n.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* i18n.h -- Internationalization stuff (ripped from bash)
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Modified 9/2000 by Alfredo K. Kojima for apt
|
||||
|
||||
Bash is free software; you can 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.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#if !defined (_I18N_H_)
|
||||
#define _I18N_H_
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LIBINTL_H)
|
||||
# include <libintl.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LOCALE_H)
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_SETLOCALE) && !defined (LC_ALL)
|
||||
# undef HAVE_SETLOCALE
|
||||
#endif
|
||||
|
||||
#if ENABLE_NLS
|
||||
# define _(a) (const char*)gettext(a)
|
||||
#else
|
||||
# undef bindtextdomain
|
||||
# define bindtextdomain(Domain, Directory) /* empty */
|
||||
# undef textdomain
|
||||
# define textdomain(Domain) /* empty */
|
||||
# undef setlocale
|
||||
# define setlocale(cat, log)
|
||||
# define _(a) a
|
||||
#endif
|
||||
|
||||
#endif /* !_I18N_H_ */
|
358
apt/apt-pkg/contrib/md5.cc
Normal file
358
apt/apt-pkg/contrib/md5.cc
Normal file
@ -0,0 +1,358 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: md5.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
MD5Sum - MD5 Message Digest Algorithm.
|
||||
|
||||
This code implements the MD5 message-digest algorithm. The algorithm is
|
||||
due to Ron Rivest. This code was written by Colin Plumb in 1993, no
|
||||
copyright is claimed. This code is in the public domain; do with it what
|
||||
you wish.
|
||||
|
||||
Equivalent code is available from RSA Data Security, Inc. This code has
|
||||
been tested against that, and is equivalent, except that you don't need to
|
||||
include two pages of legalese with every copy.
|
||||
|
||||
To compute the message digest of a chunk of bytes, instantiate the class,
|
||||
and repeatedly call one of the Add() members. When finished the Result
|
||||
method will return the Hash and finalize the value.
|
||||
|
||||
Changed so as no longer to depend on Colin Plumb's `usual.h' header
|
||||
definitions; now uses stuff from dpkg's config.h.
|
||||
- Ian Jackson <ijackson@nyx.cs.du.edu>.
|
||||
|
||||
Changed into a C++ interface and made work with APT's config.h.
|
||||
- Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
|
||||
|
||||
Still in the public domain.
|
||||
|
||||
The classes use arrays of char that are a specific size. We cast those
|
||||
arrays to uint8_t's and go from there. This allows us to advoid using
|
||||
the uncommon inttypes.h in a public header or internally newing memory.
|
||||
In theory if C9x becomes nicely accepted
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/md5.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/md5.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h> // For htonl
|
||||
#include <inttypes.h>
|
||||
#include <config.h>
|
||||
#include <system.h>
|
||||
/*}}}*/
|
||||
|
||||
// byteSwap - Swap bytes in a buffer /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Swap n 32 bit longs in given buffer */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
static void byteSwap(uint32_t *buf, unsigned words)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)buf;
|
||||
|
||||
do
|
||||
{
|
||||
*buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
|
||||
((unsigned)p[1] << 8 | p[0]);
|
||||
p += 4;
|
||||
} while (--words);
|
||||
}
|
||||
#else
|
||||
#define byteSwap(buf,words)
|
||||
#endif
|
||||
/*}}}*/
|
||||
// MD5Transform - Alters an existing MD5 hash /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
reflect the addition of 16 longwords of new data. Add blocks
|
||||
the data and converts bytes into longwords for this routine. */
|
||||
|
||||
// The four core functions - F1 is optimized somewhat
|
||||
// #define F1(x, y, z) (x & y | ~x & z)
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
// This is the central step in the MD5 algorithm.
|
||||
#define MD5STEP(f,w,x,y,z,in,s) \
|
||||
(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||
|
||||
static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
|
||||
{
|
||||
register uint32_t a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5SumValue::MD5SumValue - Constructs the summation from a string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The string form of a MD5 is a 32 character hex number */
|
||||
MD5SumValue::MD5SumValue(string Str)
|
||||
{
|
||||
memset(Sum,0,sizeof(Sum));
|
||||
Set(Str);
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5SumValue::MD5SumValue - Default constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Sets the value to 0 */
|
||||
MD5SumValue::MD5SumValue()
|
||||
{
|
||||
memset(Sum,0,sizeof(Sum));
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5SumValue::Set - Set the sum from a string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Converts the hex string into a set of chars */
|
||||
bool MD5SumValue::Set(string Str)
|
||||
{
|
||||
return Hex2Num(Str.begin(),Str.end(),Sum,sizeof(Sum));
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5SumValue::Value - Convert the number into a string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Converts the set of chars into a hex string in lower case */
|
||||
string MD5SumValue::Value() const
|
||||
{
|
||||
char Conv[16] = {'0','1','2','3','4','5','6','7','8','9','a','b',
|
||||
'c','d','e','f'};
|
||||
char Result[33];
|
||||
Result[32] = 0;
|
||||
|
||||
// Convert each char into two letters
|
||||
int J = 0;
|
||||
int I = 0;
|
||||
for (; I != 32; J++, I += 2)
|
||||
{
|
||||
Result[I] = Conv[Sum[J] >> 4];
|
||||
Result[I + 1] = Conv[Sum[J] & 0xF];
|
||||
}
|
||||
|
||||
return string(Result);
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5SumValue::operator == - Comparitor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Call memcmp on the buffer */
|
||||
bool MD5SumValue::operator ==(const MD5SumValue &rhs) const
|
||||
{
|
||||
return memcmp(Sum,rhs.Sum,sizeof(Sum)) == 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5Summation::MD5Summation - Initialize the summer /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This assigns the deep magic initial values */
|
||||
MD5Summation::MD5Summation()
|
||||
{
|
||||
uint32_t *buf = (uint32_t *)Buf;
|
||||
uint32_t *bytes = (uint32_t *)Bytes;
|
||||
|
||||
buf[0] = 0x67452301;
|
||||
buf[1] = 0xefcdab89;
|
||||
buf[2] = 0x98badcfe;
|
||||
buf[3] = 0x10325476;
|
||||
|
||||
bytes[0] = 0;
|
||||
bytes[1] = 0;
|
||||
Done = false;
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5Summation::Add - 'Add' a data set to the hash /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool MD5Summation::Add(const unsigned char *data,unsigned long len)
|
||||
{
|
||||
if (Done == true)
|
||||
return false;
|
||||
|
||||
uint32_t *buf = (uint32_t *)Buf;
|
||||
uint32_t *bytes = (uint32_t *)Bytes;
|
||||
uint32_t *in = (uint32_t *)In;
|
||||
|
||||
// Update byte count and carry (this could be done with a long long?)
|
||||
uint32_t t = bytes[0];
|
||||
if ((bytes[0] = t + len) < t)
|
||||
bytes[1]++;
|
||||
|
||||
// Space available (at least 1)
|
||||
t = 64 - (t & 0x3f);
|
||||
if (t > len)
|
||||
{
|
||||
memcpy((unsigned char *)in + 64 - t,data,len);
|
||||
return true;
|
||||
}
|
||||
|
||||
// First chunk is an odd size
|
||||
memcpy((unsigned char *)in + 64 - t,data,t);
|
||||
byteSwap(in, 16);
|
||||
MD5Transform(buf,in);
|
||||
data += t;
|
||||
len -= t;
|
||||
|
||||
// Process data in 64-byte chunks
|
||||
while (len >= 64)
|
||||
{
|
||||
memcpy(in,data,64);
|
||||
byteSwap(in,16);
|
||||
MD5Transform(buf,in);
|
||||
data += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
// Handle any remaining bytes of data.
|
||||
memcpy(in,data,len);
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5Summation::AddFD - Add the contents of a FD to the hash /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool MD5Summation::AddFD(int Fd,unsigned long Size)
|
||||
{
|
||||
unsigned char Buf[64*64];
|
||||
int Res = 0;
|
||||
while (Size != 0)
|
||||
{
|
||||
Res = read(Fd,Buf,MIN(Size,sizeof(Buf)));
|
||||
if (Res < 0 || (unsigned)Res != MIN(Size,sizeof(Buf)))
|
||||
return false;
|
||||
Size -= Res;
|
||||
Add(Buf,Res);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// MD5Summation::Result - Returns the value of the sum /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Because this must add in the last bytes of the series it prevents anyone
|
||||
from calling add after. */
|
||||
MD5SumValue MD5Summation::Result()
|
||||
{
|
||||
uint32_t *buf = (uint32_t *)Buf;
|
||||
uint32_t *bytes = (uint32_t *)Bytes;
|
||||
uint32_t *in = (uint32_t *)In;
|
||||
|
||||
if (Done == false)
|
||||
{
|
||||
// Number of bytes in In
|
||||
int count = bytes[0] & 0x3f;
|
||||
unsigned char *p = (unsigned char *)in + count;
|
||||
|
||||
// Set the first char of padding to 0x80. There is always room.
|
||||
*p++ = 0x80;
|
||||
|
||||
// Bytes of padding needed to make 56 bytes (-8..55)
|
||||
count = 56 - 1 - count;
|
||||
|
||||
// Padding forces an extra block
|
||||
if (count < 0)
|
||||
{
|
||||
memset(p,0,count + 8);
|
||||
byteSwap(in, 16);
|
||||
MD5Transform(buf,in);
|
||||
p = (unsigned char *)in;
|
||||
count = 56;
|
||||
}
|
||||
|
||||
memset(p, 0, count);
|
||||
byteSwap(in, 14);
|
||||
|
||||
// Append length in bits and transform
|
||||
in[14] = bytes[0] << 3;
|
||||
in[15] = bytes[1] << 3 | bytes[0] >> 29;
|
||||
MD5Transform(buf,in);
|
||||
byteSwap(buf,4);
|
||||
Done = true;
|
||||
}
|
||||
|
||||
MD5SumValue V;
|
||||
memcpy(V.Sum,buf,16);
|
||||
return V;
|
||||
}
|
||||
/*}}}*/
|
74
apt/apt-pkg/contrib/md5.h
Normal file
74
apt/apt-pkg/contrib/md5.h
Normal file
@ -0,0 +1,74 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: md5.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
MD5SumValue - Storage for a MD5Sum
|
||||
MD5Summation - MD5 Message Digest Algorithm.
|
||||
|
||||
This is a C++ interface to a set of MD5Sum functions. The class can
|
||||
store a MD5Sum in 16 bytes of memory.
|
||||
|
||||
A MD5Sum is used to generate a (hopefully) unique 16 byte number for a
|
||||
block of data. This can be used to gaurd against corruption of a file.
|
||||
MD5 should not be used for tamper protection, use SHA or something more
|
||||
secure.
|
||||
|
||||
There are two classes because computing a MD5 is not a continual
|
||||
operation unless 64 byte blocks are used. Also the summation requires an
|
||||
extra 18*4 bytes to operate.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef APTPKG_MD5_H
|
||||
#define APTPKG_MD5_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/md5.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
class MD5Summation;
|
||||
|
||||
class MD5SumValue
|
||||
{
|
||||
friend MD5Summation;
|
||||
unsigned char Sum[4*4];
|
||||
|
||||
public:
|
||||
|
||||
// Accessors
|
||||
bool operator ==(const MD5SumValue &rhs) const;
|
||||
string Value() const;
|
||||
inline void Value(unsigned char S[16])
|
||||
{for (int I = 0; I != sizeof(Sum); I++) S[I] = Sum[I];};
|
||||
inline operator string() const {return Value();};
|
||||
bool Set(string Str);
|
||||
inline void Set(unsigned char S[16])
|
||||
{for (int I = 0; I != sizeof(Sum); I++) Sum[I] = S[I];};
|
||||
|
||||
MD5SumValue(string Str);
|
||||
MD5SumValue();
|
||||
};
|
||||
|
||||
class MD5Summation
|
||||
{
|
||||
unsigned char Buf[4*4];
|
||||
unsigned char Bytes[2*4];
|
||||
unsigned char In[16*4];
|
||||
bool Done;
|
||||
|
||||
public:
|
||||
|
||||
bool Add(const unsigned char *Data,unsigned long Size);
|
||||
inline bool Add(const char *Data) {return Add((unsigned char *)Data,strlen(Data));};
|
||||
bool AddFD(int Fd,unsigned long Size);
|
||||
inline bool Add(const unsigned char *Beg,const unsigned char *End)
|
||||
{return Add(Beg,End-Beg);};
|
||||
MD5SumValue Result();
|
||||
|
||||
MD5Summation();
|
||||
};
|
||||
|
||||
#endif
|
279
apt/apt-pkg/contrib/mmap.cc
Normal file
279
apt/apt-pkg/contrib/mmap.cc
Normal file
@ -0,0 +1,279 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: mmap.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima 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 /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/mmap.h"
|
||||
#endif
|
||||
|
||||
#define _BSD_SOURCE
|
||||
#include <apt-pkg/mmap.h>
|
||||
#include <apt-pkg/error.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
/*}}}*/
|
||||
|
||||
// MMap::MMap - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0),
|
||||
Base(0)
|
||||
{
|
||||
if ((Flags & NoImmMap) != NoImmMap)
|
||||
Map(F);
|
||||
}
|
||||
/*}}}*/
|
||||
// MMap::MMap - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0),
|
||||
Base(0)
|
||||
{
|
||||
}
|
||||
/*}}}*/
|
||||
// MMap::~MMap - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
MMap::~MMap()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
/*}}}*/
|
||||
// MMap::Map - Perform the mapping /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool MMap::Map(FileFd &Fd)
|
||||
{
|
||||
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;
|
||||
|
||||
if (iSize == 0)
|
||||
return _error->Error("Can't mmap an empty file");
|
||||
|
||||
// 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 DoSync)
|
||||
{
|
||||
if ((Flags & UnMapped) == UnMapped || Base == 0 || iSize == 0)
|
||||
return true;
|
||||
|
||||
if (DoSync == true)
|
||||
Sync();
|
||||
|
||||
if (munmap((char *)Base,iSize) != 0)
|
||||
_error->Warning("Unable to munmap");
|
||||
|
||||
iSize = 0;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// MMap::Sync - Syncronize the map with the disk /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is done in syncronous mode - the docs indicate that this will
|
||||
not return till all IO is complete */
|
||||
bool MMap::Sync()
|
||||
{
|
||||
if ((Flags & UnMapped) == UnMapped)
|
||||
return true;
|
||||
|
||||
#ifdef _POSIX_SYNCHRONIZED_IO
|
||||
if ((Flags & ReadOnly) != ReadOnly)
|
||||
if (msync((char *)Base,iSize,MS_SYNC) != 0)
|
||||
return _error->Errno("msync","Unable to write mmap");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// MMap::Sync - Syncronize a section of the file to disk /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool MMap::Sync(unsigned long Start,unsigned long Stop)
|
||||
{
|
||||
if ((Flags & UnMapped) == UnMapped)
|
||||
return true;
|
||||
|
||||
#ifdef _POSIX_SYNCHRONIZED_IO
|
||||
unsigned long PSize = sysconf(_SC_PAGESIZE);
|
||||
if ((Flags & ReadOnly) != ReadOnly)
|
||||
if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) != 0)
|
||||
return _error->Errno("msync","Unable to write mmap");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// DynamicMMap::DynamicMMap - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) :
|
||||
MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace)
|
||||
{
|
||||
if (_error->PendingError() == true)
|
||||
return;
|
||||
|
||||
unsigned long EndOfFile = Fd->Size();
|
||||
Fd->Seek(WorkSpace);
|
||||
char C = 0;
|
||||
Fd->Write(&C,sizeof(C));
|
||||
Map(F);
|
||||
iSize = EndOfFile;
|
||||
}
|
||||
/*}}}*/
|
||||
// DynamicMMap::DynamicMMap - Constructor for a non-file backed map /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is just a fancy malloc really.. */
|
||||
DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
|
||||
MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
|
||||
{
|
||||
if (_error->PendingError() == true)
|
||||
return;
|
||||
|
||||
Base = new unsigned char[WorkSpace];
|
||||
iSize = 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// DynamicMMap::~DynamicMMap - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We truncate the file to the size of the memory data set */
|
||||
DynamicMMap::~DynamicMMap()
|
||||
{
|
||||
if (Fd == 0)
|
||||
{
|
||||
delete [] (unsigned char *)Base;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long EndOfFile = iSize;
|
||||
Sync();
|
||||
iSize = WorkSpace;
|
||||
Close(false);
|
||||
ftruncate(Fd->Fd(),EndOfFile);
|
||||
Fd->Close();
|
||||
}
|
||||
/*}}}*/
|
||||
// DynamicMMap::RawAllocate - Allocate a raw chunk of unaligned space /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This allocates a block of memory aligned to the given size */
|
||||
unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
|
||||
{
|
||||
unsigned long Result = iSize;
|
||||
if (Aln != 0)
|
||||
Result += Aln - (iSize%Aln);
|
||||
|
||||
iSize = Result + Size;
|
||||
|
||||
// Just in case error check
|
||||
if (Result + Size > 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,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 + Len > WorkSpace)
|
||||
{
|
||||
_error->Error("Dynamic MMap ran out of room");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Len == (unsigned long)-1)
|
||||
Len = strlen(String);
|
||||
iSize += Len + 1;
|
||||
memcpy((char *)Base + Result,String,Len);
|
||||
((char *)Base)[Result + Len] = 0;
|
||||
return Result;
|
||||
}
|
||||
/*}}}*/
|
103
apt/apt-pkg/contrib/mmap.h
Normal file
103
apt/apt-pkg/contrib/mmap.h
Normal file
@ -0,0 +1,103 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: mmap.h,v 1.1.1.1 2000/08/10 12:42:39 kojima 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.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_MMAP_H
|
||||
#define PKGLIB_MMAP_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/mmap.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <apt-pkg/fileutl.h>
|
||||
|
||||
/* This should be a 32 bit type, larger tyes use too much ram and smaller
|
||||
types are too small. Where ever possible 'unsigned long' should be used
|
||||
instead of this internal type */
|
||||
typedef unsigned int map_ptrloc;
|
||||
|
||||
class MMap
|
||||
{
|
||||
protected:
|
||||
|
||||
unsigned long Flags;
|
||||
unsigned long iSize;
|
||||
void *Base;
|
||||
|
||||
bool Map(FileFd &Fd);
|
||||
bool Close(bool DoSync = true);
|
||||
|
||||
public:
|
||||
|
||||
enum OpenFlags {NoImmMap = (1<<0),Public = (1<<1),ReadOnly = (1<<2),
|
||||
UnMapped = (1<<3)};
|
||||
|
||||
// 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(FileFd &F,unsigned long Flags);
|
||||
MMap(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:
|
||||
|
||||
FileFd *Fd;
|
||||
unsigned long WorkSpace;
|
||||
Pool *Pools;
|
||||
unsigned int PoolCount;
|
||||
|
||||
public:
|
||||
|
||||
// Allocation
|
||||
unsigned long RawAllocate(unsigned long Size,unsigned long Aln = 0);
|
||||
unsigned long Allocate(unsigned long ItemSize);
|
||||
unsigned long WriteString(const char *String,unsigned long Len = (unsigned long)-1);
|
||||
inline unsigned long WriteString(string S) {return WriteString(S.begin(),S.size());};
|
||||
void UsePools(Pool &P,unsigned int Count) {Pools = &P; PoolCount = Count;};
|
||||
|
||||
DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace = 2*1024*1024);
|
||||
DynamicMMap(unsigned long Flags,unsigned long WorkSpace = 2*1024*1024);
|
||||
virtual ~DynamicMMap();
|
||||
};
|
||||
|
||||
#endif
|
200
apt/apt-pkg/contrib/progress.cc
Normal file
200
apt/apt-pkg/contrib/progress.cc
Normal file
@ -0,0 +1,200 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: progress.cc,v 1.3 2001/11/13 17:32:08 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
OpProgress - Operation Progress
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/progress.h"
|
||||
#endif
|
||||
#include <apt-pkg/progress.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <stdio.h>
|
||||
/*}}}*/
|
||||
#include <i18n.h>
|
||||
|
||||
// OpProgress::OpProgress - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
OpProgress::OpProgress() : Current(0), Total(0), Size(0), SubTotal(1),
|
||||
LastPercent(0), Percent(0)
|
||||
{
|
||||
memset(&LastTime,0,sizeof(LastTime));
|
||||
}
|
||||
/*}}}*/
|
||||
// OpProgress::Progress - Sub progress with no state change /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Current is the Base Overall progress in units of Total. Cur is the sub
|
||||
progress in units of SubTotal. Size is a scaling factor that says what
|
||||
percent of Total SubTotal is. */
|
||||
void OpProgress::Progress(unsigned long Cur)
|
||||
{
|
||||
Percent = (Current + Cur/((float)SubTotal)*Size)*100.0/Total;
|
||||
Update();
|
||||
}
|
||||
/*}}}*/
|
||||
// OpProgress::OverallProgress - Set the overall progress /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void OpProgress::OverallProgress(unsigned long Current, unsigned long Total,
|
||||
unsigned long Size,string Op)
|
||||
{
|
||||
this->Current = Current;
|
||||
this->Total = Total;
|
||||
this->Size = Size;
|
||||
this->Op = Op;
|
||||
SubOp = string();
|
||||
Percent = Current*100.0/Total;
|
||||
Update();
|
||||
}
|
||||
/*}}}*/
|
||||
// OpProgress::SubProgress - Set the sub progress state /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void OpProgress::SubProgress(unsigned long SubTotal,string Op)
|
||||
{
|
||||
this->SubTotal = SubTotal;
|
||||
SubOp = Op;
|
||||
Percent = Current*100.0/Total;
|
||||
Update();
|
||||
}
|
||||
/*}}}*/
|
||||
// OpProgress::SubProgress - Set the sub progress state /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void OpProgress::SubProgress(unsigned long SubTotal)
|
||||
{
|
||||
this->SubTotal = SubTotal;
|
||||
Percent = Current*100.0/Total;
|
||||
Update();
|
||||
}
|
||||
/*}}}*/
|
||||
// OpProgress::CheckChange - See if the display should be updated /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Progress calls are made so frequently that if every one resulted in
|
||||
an update the display would be swamped and the system much slower.
|
||||
This provides an upper bound on the update rate. */
|
||||
bool OpProgress::CheckChange(float Interval)
|
||||
{
|
||||
// New major progress indication
|
||||
if (Op != LastOp)
|
||||
{
|
||||
MajorChange = true;
|
||||
LastOp = Op;
|
||||
return true;
|
||||
}
|
||||
MajorChange = false;
|
||||
|
||||
if (SubOp != LastSubOp)
|
||||
{
|
||||
LastSubOp = SubOp;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((int)LastPercent == (int)Percent)
|
||||
return false;
|
||||
|
||||
// Check time delta
|
||||
struct timeval Now;
|
||||
gettimeofday(&Now,0);
|
||||
double Diff = Now.tv_sec - LastTime.tv_sec + (Now.tv_usec - LastTime.tv_usec)/1000000.0;
|
||||
if (Diff < Interval)
|
||||
return false;
|
||||
LastTime = Now;
|
||||
LastPercent = Percent;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OpTextProgress::OpTextProgress - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
OpTextProgress::OpTextProgress(Configuration &Config) :
|
||||
NoUpdate(false), NoDisplay(false), LastLen(0)
|
||||
{
|
||||
if (Config.FindI("quiet",0) >= 1)
|
||||
NoUpdate = true;
|
||||
if (Config.FindI("quiet",0) >= 2)
|
||||
NoDisplay = true;
|
||||
};
|
||||
/*}}}*/
|
||||
// OpTextProgress::Done - Clean up the display /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void OpTextProgress::Done()
|
||||
{
|
||||
if (NoUpdate == false && OldOp.empty() == false)
|
||||
{
|
||||
char S[300];
|
||||
if (_error->PendingError() == true)
|
||||
snprintf(S,sizeof(S),"\r%s... %s",OldOp.c_str(),_("Error!"));
|
||||
else
|
||||
snprintf(S,sizeof(S),"\r%s... %s",OldOp.c_str(),_("Done"));
|
||||
Write(S);
|
||||
cout << endl;
|
||||
OldOp = string();
|
||||
}
|
||||
|
||||
if (NoUpdate == true && NoDisplay == false && OldOp.empty() == false)
|
||||
{
|
||||
OldOp = string();
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// OpTextProgress::Update - Simple text spinner /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void OpTextProgress::Update()
|
||||
{
|
||||
if (CheckChange(0.1) == false)
|
||||
return;
|
||||
|
||||
// No percent spinner
|
||||
if (NoUpdate == true)
|
||||
{
|
||||
if (MajorChange == false)
|
||||
return;
|
||||
if (NoDisplay == false)
|
||||
{
|
||||
if (OldOp.empty() == false)
|
||||
cout << endl;
|
||||
OldOp = "a";
|
||||
cout << Op << "..." << flush;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Erase the old text and 'log' the event
|
||||
char S[300];
|
||||
if (MajorChange == true && OldOp.empty() == false)
|
||||
{
|
||||
snprintf(S,sizeof(S),"\r%s",OldOp.c_str());
|
||||
Write(S);
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
// Print the spinner
|
||||
snprintf(S,sizeof(S),"\r%s... %u%%",Op.c_str(),(unsigned int)Percent);
|
||||
Write(S);
|
||||
|
||||
OldOp = Op;
|
||||
}
|
||||
/*}}}*/
|
||||
// OpTextProgress::Write - Write the progress string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This space fills the end to overwrite the previous text */
|
||||
void OpTextProgress::Write(const char *S)
|
||||
{
|
||||
cout << S;
|
||||
for (unsigned int I = strlen(S); I < LastLen; I++)
|
||||
cout << ' ';
|
||||
cout << '\r' << flush;
|
||||
LastLen = strlen(S);
|
||||
}
|
||||
/*}}}*/
|
90
apt/apt-pkg/contrib/progress.h
Normal file
90
apt/apt-pkg/contrib/progress.h
Normal file
@ -0,0 +1,90 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: progress.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
OpProgress - Operation Progress
|
||||
|
||||
This class allows lengthy operations to communicate their progress
|
||||
to the GUI. The progress model is simple and is not designed to handle
|
||||
the complex case of the multi-activity aquire class.
|
||||
|
||||
The model is based on the concept of an overall operation consisting
|
||||
of a series of small sub operations. Each sub operation has it's own
|
||||
completion status and the overall operation has it's completion status.
|
||||
The units of the two are not mixed and are completely independent.
|
||||
|
||||
The UI is expected to subclass this to provide the visuals to the user.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_PROGRESS_H
|
||||
#define PKGLIB_PROGRESS_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/progress.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <sys/time.h>
|
||||
|
||||
class Configuration;
|
||||
class OpProgress
|
||||
{
|
||||
unsigned long Current;
|
||||
unsigned long Total;
|
||||
unsigned long Size;
|
||||
unsigned long SubTotal;
|
||||
float LastPercent;
|
||||
|
||||
// Change reduction code
|
||||
struct timeval LastTime;
|
||||
string LastOp;
|
||||
string LastSubOp;
|
||||
|
||||
protected:
|
||||
|
||||
string Op;
|
||||
string SubOp;
|
||||
float Percent;
|
||||
|
||||
bool MajorChange;
|
||||
|
||||
bool CheckChange(float Interval = 0.7);
|
||||
virtual void Update() {};
|
||||
|
||||
public:
|
||||
|
||||
void Progress(unsigned long Current);
|
||||
void SubProgress(unsigned long SubTotal);
|
||||
void SubProgress(unsigned long SubTotal,string Op);
|
||||
void OverallProgress(unsigned long Current,unsigned long Total,
|
||||
unsigned long Size,string Op);
|
||||
virtual void Done() {};
|
||||
|
||||
OpProgress();
|
||||
virtual ~OpProgress() {};
|
||||
};
|
||||
|
||||
class OpTextProgress : public OpProgress
|
||||
{
|
||||
protected:
|
||||
|
||||
string OldOp;
|
||||
bool NoUpdate;
|
||||
bool NoDisplay;
|
||||
unsigned long LastLen;
|
||||
virtual void Update();
|
||||
void Write(const char *S);
|
||||
|
||||
public:
|
||||
|
||||
virtual void Done();
|
||||
|
||||
OpTextProgress(bool NoUpdate = false) : NoUpdate(NoUpdate),
|
||||
NoDisplay(false), LastLen(0) {};
|
||||
OpTextProgress(Configuration &Config);
|
||||
virtual ~OpTextProgress() {Done();};
|
||||
};
|
||||
|
||||
#endif
|
66
apt/apt-pkg/contrib/sptr.h
Normal file
66
apt/apt-pkg/contrib/sptr.h
Normal file
@ -0,0 +1,66 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: sptr.h,v 1.1 2001/03/27 21:18:18 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Trivial non-ref counted 'smart pointer'
|
||||
|
||||
This is really only good to eliminate
|
||||
{
|
||||
delete Foo;
|
||||
return;
|
||||
}
|
||||
|
||||
Blocks from functions.
|
||||
|
||||
I think G++ has become good enough that doing this won't have much
|
||||
code size implications.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef SMART_POINTER_H
|
||||
#define SMART_POINTER_H
|
||||
|
||||
template <class T>
|
||||
class SPtr
|
||||
{
|
||||
public:
|
||||
T *Ptr;
|
||||
|
||||
inline T *operator ->() {return Ptr;};
|
||||
inline T &operator *() {return *Ptr;};
|
||||
inline operator T *() {return Ptr;};
|
||||
inline operator void *() {return Ptr;};
|
||||
inline T *UnGuard() {T *Tmp = Ptr; Ptr = 0; return Tmp;};
|
||||
inline void operator =(T *N) {Ptr = N;};
|
||||
inline bool operator ==(T *lhs) const {return Ptr == lhs;};
|
||||
inline bool operator !=(T *lhs) const {return Ptr != lhs;};
|
||||
inline T*Get() {return Ptr;};
|
||||
|
||||
inline SPtr(T *Ptr) : Ptr(Ptr) {};
|
||||
inline SPtr() : Ptr(0) {};
|
||||
inline ~SPtr() {delete Ptr;};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class SPtrArray
|
||||
{
|
||||
public:
|
||||
T *Ptr;
|
||||
|
||||
//inline T &operator *() {return *Ptr;};
|
||||
inline operator T *() {return Ptr;};
|
||||
inline operator void *() {return Ptr;};
|
||||
inline T *UnGuard() {T *Tmp = Ptr; Ptr = 0; return Tmp;};
|
||||
//inline T &operator [](signed long I) {return Ptr[I];};
|
||||
inline void operator =(T *N) {Ptr = N;};
|
||||
inline bool operator ==(T *lhs) const {return Ptr == lhs;};
|
||||
inline bool operator !=(T *lhs) const {return Ptr != lhs;};
|
||||
inline T *Get() {return Ptr;};
|
||||
|
||||
inline SPtrArray(T *Ptr) : Ptr(Ptr) {};
|
||||
inline SPtrArray() : Ptr(0) {};
|
||||
inline ~SPtrArray() {delete [] Ptr;};
|
||||
};
|
||||
|
||||
#endif
|
1039
apt/apt-pkg/contrib/strutl.cc
Normal file
1039
apt/apt-pkg/contrib/strutl.cc
Normal file
File diff suppressed because it is too large
Load Diff
96
apt/apt-pkg/contrib/strutl.h
Normal file
96
apt/apt-pkg/contrib/strutl.h
Normal file
@ -0,0 +1,96 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: strutl.h,v 1.3 2000/10/30 18:49:49 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
String Util - These are some useful string functions
|
||||
|
||||
_strstrip is a function to remove whitespace from the front and end
|
||||
of a string.
|
||||
|
||||
This source is placed in the Public Domain, do with it what you will
|
||||
It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef STRUTL_H
|
||||
#define STRUTL_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/strutl.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
char *_strstrip(char *String);
|
||||
char *_strtabexpand(char *String,size_t Len);
|
||||
bool ParseQuoteWord(const char *&String,string &Res);
|
||||
bool ParseCWord(const char *&String,string &Res);
|
||||
string QuoteString(string Str,const char *Bad);
|
||||
string DeQuoteString(string Str);
|
||||
string SizeToStr(double Bytes);
|
||||
string TimeToStr(unsigned long Sec);
|
||||
string Base64Encode(string Str);
|
||||
string URItoFileName(string URI);
|
||||
string TimeRFC1123(time_t Date);
|
||||
bool StrToTime(string Val,time_t &Result);
|
||||
string LookupTag(string Message,const char *Tag,const char *Default = 0);
|
||||
int StringToBool(string Text,int Default = -1);
|
||||
bool ReadMessages(int Fd, vector<string> &List);
|
||||
bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0);
|
||||
bool Hex2Num(const char *Start,const char *End,unsigned char *Num,
|
||||
unsigned int Length);
|
||||
bool TokSplitString(char Tok,char *Input,char **List,
|
||||
unsigned long ListMax);
|
||||
|
||||
int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
|
||||
inline int stringcmp(const char *A,const char *AEnd,const char *B) {return stringcmp(A,AEnd,B,B+strlen(B));};
|
||||
inline int stringcmp(string A,const char *B) {return stringcmp(A.begin(),A.end(),B,B+strlen(B));};
|
||||
int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
|
||||
inline int stringcasecmp(const char *A,const char *AEnd,const char *B) {return stringcasecmp(A,AEnd,B,B+strlen(B));};
|
||||
inline int stringcasecmp(string A,const char *B) {return stringcasecmp(A.begin(),A.end(),B,B+strlen(B));};
|
||||
inline int stringcasecmp(string A,string B) {return stringcasecmp(A.begin(),A.end(),B.begin(),B.end());};
|
||||
|
||||
class URI
|
||||
{
|
||||
void CopyFrom(string From);
|
||||
|
||||
public:
|
||||
|
||||
string Access;
|
||||
string User;
|
||||
string Password;
|
||||
string Host;
|
||||
string Path;
|
||||
unsigned int Port;
|
||||
|
||||
operator string();
|
||||
inline void operator =(string From) {CopyFrom(From);};
|
||||
inline bool empty() {return Access.empty();};
|
||||
static string SiteOnly(string URI);
|
||||
|
||||
URI(string Path) {CopyFrom(Path);};
|
||||
URI() : Port(0) {};
|
||||
};
|
||||
|
||||
struct SubstVar
|
||||
{
|
||||
const char *Subst;
|
||||
const string *Contents;
|
||||
};
|
||||
string SubstVar(string Str,const struct SubstVar *Vars);
|
||||
string SubstVar(string Str,string Subst,string Contents);
|
||||
|
||||
struct RxChoiceList
|
||||
{
|
||||
void *UserData;
|
||||
const char *Str;
|
||||
bool Hit;
|
||||
};
|
||||
unsigned long RegexChoice(RxChoiceList *Rxs,const char **ListBegin,
|
||||
const char **ListEnd);
|
||||
|
||||
#endif
|
58
apt/apt-pkg/contrib/system.h
Normal file
58
apt/apt-pkg/contrib/system.h
Normal file
@ -0,0 +1,58 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: system.h,v 1.1.1.1 2000/08/10 12:42:39 kojima 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
|
||||
#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(MIN)
|
||||
#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
|
||||
#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
|
13
apt/apt-pkg/deb/CVS/Entries
Normal file
13
apt/apt-pkg/deb/CVS/Entries
Normal file
@ -0,0 +1,13 @@
|
||||
/debfactory.cc/1.6/Fri Aug 10 14:00:34 2001//
|
||||
/debfactory.h/1.6/Fri Aug 10 14:00:34 2001//
|
||||
/deblistparser.cc/1.1.1.1/Fri Aug 10 14:00:36 2001//
|
||||
/deblistparser.h/1.1.1.1/Fri Aug 10 14:00:36 2001//
|
||||
/debrecords.cc/1.1.1.1/Fri Aug 10 14:00:36 2001//
|
||||
/debrecords.h/1.1.1.1/Fri Aug 10 14:00:37 2001//
|
||||
/debsrcrecords.cc/1.2/Fri Aug 10 14:00:37 2001//
|
||||
/debsrcrecords.h/1.1.1.1/Fri Aug 10 14:00:37 2001//
|
||||
/dpkginit.cc/1.1.1.1/Fri Aug 10 14:00:37 2001//
|
||||
/dpkginit.h/1.1.1.1/Fri Aug 10 14:00:37 2001//
|
||||
/dpkgpm.cc/1.1.1.1/Fri Aug 10 14:00:37 2001//
|
||||
/dpkgpm.h/1.1.1.1/Fri Aug 10 14:00:37 2001//
|
||||
D
|
1
apt/apt-pkg/deb/CVS/Repository
Normal file
1
apt/apt-pkg/deb/CVS/Repository
Normal file
@ -0,0 +1 @@
|
||||
rapt/apt-pkg/deb
|
1
apt/apt-pkg/deb/CVS/Root
Normal file
1
apt/apt-pkg/deb/CVS/Root
Normal file
@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs
|
197
apt/apt-pkg/deb/debfactory.cc
Normal file
197
apt/apt-pkg/deb/debfactory.cc
Normal file
@ -0,0 +1,197 @@
|
||||
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/deblistparser.h>
|
||||
#include <apt-pkg/dpkgpm.h>
|
||||
#include <apt-pkg/debfactory.h>
|
||||
#include <apt-pkg/sourcelist.h>
|
||||
#include <apt-pkg/progress.h>
|
||||
#include <apt-pkg/debrecords.h>
|
||||
#include <apt-pkg/debsrcrecords.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <system.h>
|
||||
|
||||
|
||||
|
||||
pkgPackageManager *DebianFactory::CreatePackageManager(pkgDepCache &Cache)
|
||||
{
|
||||
return new pkgDPkgPM(Cache);
|
||||
}
|
||||
|
||||
|
||||
pkgRecords::Parser *DebianFactory::CreateRecordParser(string File, pkgCache &Cache)
|
||||
{
|
||||
FileFd f;
|
||||
|
||||
f = FileFd(File, FileFd::ReadOnly);
|
||||
if (_error->PendingError())
|
||||
return NULL;
|
||||
|
||||
return new debRecordParser(f, Cache);
|
||||
}
|
||||
|
||||
|
||||
pkgSrcRecords::Parser *DebianFactory::CreateSrcRecordParser(string File,
|
||||
pkgSourceList::const_iterator SrcItem)
|
||||
{
|
||||
FileFd *f;
|
||||
|
||||
f = new FileFd(File, FileFd::ReadOnly);
|
||||
if (_error->PendingError()) {
|
||||
delete f;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new debSrcRecordParser(f, SrcItem);
|
||||
}
|
||||
|
||||
|
||||
bool DebianFactory::checkSourceType(int type, bool binary)
|
||||
{
|
||||
if (binary)
|
||||
return (type == pkgSourceList::Deb);
|
||||
else
|
||||
return (type == pkgSourceList::DebSrc);
|
||||
}
|
||||
|
||||
|
||||
pkgCacheGenerator::ListParser *DebianFactory::CreateListParser(FileFd &File)
|
||||
{
|
||||
return new debListParser(File);
|
||||
}
|
||||
|
||||
|
||||
/*}}}*/
|
||||
// PkgCacheCheck - Check if the package cache is uptodate /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This does a simple check of all files used to compose the cache */
|
||||
bool DebianFactory::packageCacheCheck(string CacheFile)
|
||||
{
|
||||
if (_error->PendingError() == true)
|
||||
return false;
|
||||
|
||||
// Open the source package cache
|
||||
if (FileExists(CacheFile) == false)
|
||||
return false;
|
||||
|
||||
FileFd CacheF(CacheFile,FileFd::ReadOnly);
|
||||
if (_error->PendingError() == true)
|
||||
{
|
||||
_error->Discard();
|
||||
return false;
|
||||
}
|
||||
|
||||
MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
|
||||
if (_error->PendingError() == true || Map.Size() == 0)
|
||||
{
|
||||
_error->Discard();
|
||||
return false;
|
||||
}
|
||||
|
||||
pkgCache Cache(Map);
|
||||
if (_error->PendingError() == true)
|
||||
{
|
||||
_error->Discard();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Status files that must be in the cache
|
||||
string Status[3];
|
||||
Status[0] = _config->FindFile("Dir::State::xstatus");
|
||||
Status[1]= _config->FindFile("Dir::State::userstatus");
|
||||
Status[2] = _config->FindFile("Dir::State::status");
|
||||
|
||||
// Cheack each file
|
||||
for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
|
||||
{
|
||||
if (F.IsOk() == false)
|
||||
return false;
|
||||
|
||||
// See if this is one of the status files
|
||||
for (int I = 0; I != 3; I++)
|
||||
if (F.FileName() == Status[I])
|
||||
Status[I] = string();
|
||||
}
|
||||
|
||||
// Make sure all the status files are loaded.
|
||||
for (int I = 0; I != 3; I++)
|
||||
{
|
||||
if (Status[I].empty() == false && FileExists(Status[I]) == true)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// AddStatusSize - Add the size of the status files /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This adds the size of all the status files to the size counter */
|
||||
bool DebianFactory::addStatusSize(unsigned long &TotalSize)
|
||||
{
|
||||
// Grab the file names
|
||||
string xstatus = _config->FindFile("Dir::State::xstatus");
|
||||
string userstatus = _config->FindFile("Dir::State::userstatus");
|
||||
string status = _config->FindFile("Dir::State::status");
|
||||
|
||||
// Grab the sizes
|
||||
struct stat Buf;
|
||||
if (stat(xstatus.c_str(),&Buf) == 0)
|
||||
TotalSize += Buf.st_size;
|
||||
if (stat(userstatus.c_str(),&Buf) == 0)
|
||||
TotalSize += Buf.st_size;
|
||||
if (stat(status.c_str(),&Buf) != 0)
|
||||
return _error->Errno("stat","Couldn't stat the status file %s",status.c_str());
|
||||
TotalSize += Buf.st_size;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// MergeInstalledPackages (was MergeStatus) - Add the status files to the cache /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This adds the status files to the map */
|
||||
bool DebianFactory::mergeInstalledPackages(OpProgress &Progress,
|
||||
pkgCacheGenerator &Gen,
|
||||
unsigned long &CurrentSize,
|
||||
unsigned long TotalSize)
|
||||
{
|
||||
// Grab the file names
|
||||
string Status[3];
|
||||
Status[0] = _config->FindFile("Dir::State::xstatus");
|
||||
Status[1]= _config->FindFile("Dir::State::userstatus");
|
||||
Status[2] = _config->FindFile("Dir::State::status");
|
||||
|
||||
for (int I = 0; I != 3; I++)
|
||||
{
|
||||
pkgCacheGenerator::ListParser *Parser;
|
||||
|
||||
// Check if the file exists and it is not the primary status file.
|
||||
string File = Status[I];
|
||||
if (I != 2 && FileExists(File) == false)
|
||||
continue;
|
||||
|
||||
FileFd Pkg(File,FileFd::ReadOnly);
|
||||
Parser = new debListParser(Pkg);
|
||||
|
||||
Progress.OverallProgress(CurrentSize,TotalSize,Pkg.Size(),"Reading Package Lists");
|
||||
if (_error->PendingError() == true)
|
||||
return _error->Error("Problem opening %s",File.c_str());
|
||||
CurrentSize += Pkg.Size();
|
||||
|
||||
Progress.SubProgress(0,"Local Package State - " + flNotDir(File));
|
||||
if (Gen.SelectFile(File,pkgCache::Flag::NotSource) == false)
|
||||
return _error->Error("Problem with SelectFile %s",File.c_str());
|
||||
|
||||
if (Gen.MergeList(*Parser) == false)
|
||||
return _error->Error("Problem with MergeList %s",File.c_str());
|
||||
Progress.Progress(Pkg.Size());
|
||||
|
||||
delete Parser;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
31
apt/apt-pkg/deb/debfactory.h
Normal file
31
apt/apt-pkg/deb/debfactory.h
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef _DEBIANFACTORY_H_
|
||||
#define _DEBIANFACTORY_H_
|
||||
|
||||
#include <apt-pkg/systemfactory.h>
|
||||
|
||||
|
||||
class DebianFactory : public SystemFactory
|
||||
{
|
||||
// for cache generation
|
||||
protected:
|
||||
bool addStatusSize(unsigned long &TotalSize);
|
||||
|
||||
bool mergeInstalledPackages(OpProgress &Progress,pkgCacheGenerator &Gen,
|
||||
unsigned long &CurrentSize,
|
||||
unsigned long TotalSize);
|
||||
|
||||
protected:
|
||||
bool packageCacheCheck(string CacheFile);
|
||||
|
||||
bool checkSourceType(int type, bool binary=true);
|
||||
|
||||
public:
|
||||
// other stuffs
|
||||
pkgCacheGenerator::ListParser *CreateListParser(FileFd &File);
|
||||
pkgRecords::Parser *CreateRecordParser(string File, pkgCache &Cache);
|
||||
pkgSrcRecords::Parser *CreateSrcRecordParser(string File, pkgSourceList::const_iterator SrcItem);
|
||||
pkgPackageManager *CreatePackageManager(pkgDepCache &Cache);
|
||||
};
|
||||
|
||||
#endif
|
529
apt/apt-pkg/deb/deblistparser.cc
Normal file
529
apt/apt-pkg/deb/deblistparser.cc
Normal file
@ -0,0 +1,529 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: deblistparser.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Package Cache Generator - Generator for the cache structure.
|
||||
|
||||
This builds the cache structure from the abstract package list parser.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#include <apt-pkg/deblistparser.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
#include <apt-pkg/crc-16.h>
|
||||
|
||||
#include <system.h>
|
||||
/*}}}*/
|
||||
|
||||
// ListParser::debListParser - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
debListParser::debListParser(FileFd &File) : Tags(File)
|
||||
{
|
||||
Arch = _config->Find("APT::architecture");
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
unsigned long debListParser::UniqFindTagWrite(const char *Tag)
|
||||
{
|
||||
const char *Start;
|
||||
const char *Stop;
|
||||
if (Section.Find(Tag,Start,Stop) == false)
|
||||
return 0;
|
||||
return WriteUniqString(Start,Stop - Start);
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::Package - Return the package name /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is to return the name of the package this section describes */
|
||||
string debListParser::Package()
|
||||
{
|
||||
string Result = Section.FindS("Package");
|
||||
if (Result.empty() == true)
|
||||
_error->Error("Encountered a section with no Package: header");
|
||||
return Result;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::Version - Return the version string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is to return the string describing the version in debian form,
|
||||
epoch:upstream-release. If this returns the blank string then the
|
||||
entry is assumed to only describe package properties */
|
||||
string debListParser::Version()
|
||||
{
|
||||
return Section.FindS("Version");
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::NewVersion - Fill in the version structure /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool debListParser::NewVersion(pkgCache::VerIterator Ver)
|
||||
{
|
||||
// Parse the section
|
||||
Ver->Section = UniqFindTagWrite("Section");
|
||||
Ver->Arch = UniqFindTagWrite("Architecture");
|
||||
|
||||
// Archive Size
|
||||
Ver->Size = (unsigned)Section.FindI("Size");
|
||||
|
||||
// Unpacked Size (in K)
|
||||
Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
|
||||
Ver->InstalledSize *= 1024;
|
||||
|
||||
// Priority
|
||||
const char *Start;
|
||||
const char *Stop;
|
||||
if (Section.Find("Priority",Start,Stop) == true)
|
||||
{
|
||||
WordList PrioList[] = {{"important",pkgCache::State::Important},
|
||||
{"required",pkgCache::State::Required},
|
||||
{"standard",pkgCache::State::Standard},
|
||||
{"optional",pkgCache::State::Optional},
|
||||
{"extra",pkgCache::State::Extra}};
|
||||
if (GrabWord(string(Start,Stop-Start),PrioList,
|
||||
_count(PrioList),Ver->Priority) == false)
|
||||
Ver->Priority = pkgCache::State::Extra;
|
||||
}
|
||||
|
||||
if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
|
||||
return false;
|
||||
if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
|
||||
return false;
|
||||
if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
|
||||
return false;
|
||||
if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
|
||||
return false;
|
||||
if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
|
||||
return false;
|
||||
if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
|
||||
return false;
|
||||
|
||||
if (ParseProvides(Ver) == false)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::UsePackage - Update a package structure /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called to update the package with any new information
|
||||
that might be found in the section */
|
||||
bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
|
||||
pkgCache::VerIterator Ver)
|
||||
{
|
||||
if (Pkg->Section == 0)
|
||||
Pkg->Section = UniqFindTagWrite("Section");
|
||||
if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
|
||||
return false;
|
||||
if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
|
||||
return false;
|
||||
|
||||
if (strcmp(Pkg.Name(),"apt") == 0)
|
||||
Pkg->Flags |= pkgCache::Flag::Important;
|
||||
|
||||
if (ParseStatus(Pkg,Ver) == false)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
unsigned short debListParser::VersionHash()
|
||||
{
|
||||
const char *Sections[] ={"Installed-Size",
|
||||
"Depends",
|
||||
"Pre-Depends",
|
||||
// "Suggests",
|
||||
// "Recommends",
|
||||
"Conflicts",
|
||||
"Replaces",0};
|
||||
unsigned long Result = INIT_FCS;
|
||||
char S[300];
|
||||
for (const char **I = Sections; *I != 0; I++)
|
||||
{
|
||||
const char *Start;
|
||||
const char *End;
|
||||
if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
|
||||
continue;
|
||||
|
||||
/* Strip out any spaces from the text, this undoes dpkgs reformatting
|
||||
of certain fields. dpkg also has the rather interesting notion of
|
||||
reformatting depends operators < -> <= */
|
||||
char *I = S;
|
||||
for (; Start != End; Start++)
|
||||
{
|
||||
if (isspace(*Start) == 0)
|
||||
*I++ = tolower(*Start);
|
||||
if (*Start == '<' && Start[1] != '<' && Start[1] != '=')
|
||||
*I++ = '=';
|
||||
if (*Start == '>' && Start[1] != '>' && Start[1] != '=')
|
||||
*I++ = '=';
|
||||
}
|
||||
|
||||
Result = AddCRC16(Result,S,I - S);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::ParseStatus - Parse the status field /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Status lines are of the form,
|
||||
Status: want flag status
|
||||
want = unknown, install, hold, deinstall, purge
|
||||
flag = ok, reinstreq, hold, hold-reinstreq
|
||||
status = not-installed, unpacked, half-configured,
|
||||
half-installed, config-files, post-inst-failed,
|
||||
removal-failed, installed
|
||||
|
||||
Some of the above are obsolete (I think?) flag = hold-* and
|
||||
status = post-inst-failed, removal-failed at least.
|
||||
*/
|
||||
bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
|
||||
pkgCache::VerIterator Ver)
|
||||
{
|
||||
const char *Start;
|
||||
const char *Stop;
|
||||
if (Section.Find("Status",Start,Stop) == false)
|
||||
return true;
|
||||
|
||||
// Isolate the first word
|
||||
const char *I = Start;
|
||||
for(; I < Stop && *I != ' '; I++);
|
||||
if (I >= Stop || *I != ' ')
|
||||
return _error->Error("Malformed Status line");
|
||||
|
||||
// Process the want field
|
||||
WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
|
||||
{"install",pkgCache::State::Install},
|
||||
{"hold",pkgCache::State::Hold},
|
||||
{"deinstall",pkgCache::State::DeInstall},
|
||||
{"purge",pkgCache::State::Purge}};
|
||||
if (GrabWord(string(Start,I-Start),WantList,
|
||||
_count(WantList),Pkg->SelectedState) == false)
|
||||
return _error->Error("Malformed 1st word in the Status line");
|
||||
|
||||
// Isloate the next word
|
||||
I++;
|
||||
Start = I;
|
||||
for(; I < Stop && *I != ' '; I++);
|
||||
if (I >= Stop || *I != ' ')
|
||||
return _error->Error("Malformed status line, no 2nd word");
|
||||
|
||||
// Process the flag field
|
||||
WordList FlagList[] = {{"ok",pkgCache::State::Ok},
|
||||
{"reinstreq",pkgCache::State::ReInstReq},
|
||||
{"hold",pkgCache::State::HoldInst},
|
||||
{"hold-reinstreq",pkgCache::State::HoldReInstReq}};
|
||||
if (GrabWord(string(Start,I-Start),FlagList,
|
||||
_count(FlagList),Pkg->InstState) == false)
|
||||
return _error->Error("Malformed 2nd word in the Status line");
|
||||
|
||||
// Isloate the last word
|
||||
I++;
|
||||
Start = I;
|
||||
for(; I < Stop && *I != ' '; I++);
|
||||
if (I != Stop)
|
||||
return _error->Error("Malformed Status line, no 3rd word");
|
||||
|
||||
// Process the flag field
|
||||
WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
|
||||
{"unpacked",pkgCache::State::UnPacked},
|
||||
{"half-configured",pkgCache::State::HalfConfigured},
|
||||
{"installed",pkgCache::State::Installed},
|
||||
{"half-installed",pkgCache::State::HalfInstalled},
|
||||
{"config-files",pkgCache::State::ConfigFiles},
|
||||
{"post-inst-failed",pkgCache::State::HalfConfigured},
|
||||
{"removal-failed",pkgCache::State::HalfInstalled}};
|
||||
if (GrabWord(string(Start,I-Start),StatusList,
|
||||
_count(StatusList),Pkg->CurrentState) == false)
|
||||
return _error->Error("Malformed 3rd word in the Status line");
|
||||
|
||||
/* A Status line marks the package as indicating the current
|
||||
version as well. Only if it is actually installed.. Otherwise
|
||||
the interesting dpkg handling of the status file creates bogus
|
||||
entries. */
|
||||
if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
|
||||
Pkg->CurrentState == pkgCache::State::ConfigFiles))
|
||||
{
|
||||
if (Ver.end() == true)
|
||||
_error->Warning("Encountered status field in a non-version description");
|
||||
else
|
||||
Pkg->CurrentVer = Ver.Index();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::ParseDepends - Parse a dependency element /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This parses the dependency elements out of a standard string in place,
|
||||
bit by bit. */
|
||||
const char *debListParser::ParseDepends(const char *Start,const char *Stop,
|
||||
string &Package,string &Ver,
|
||||
unsigned int &Op)
|
||||
{
|
||||
// Strip off leading space
|
||||
for (;Start != Stop && isspace(*Start) != 0; Start++);
|
||||
|
||||
// Parse off the package name
|
||||
const char *I = Start;
|
||||
for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
|
||||
*I != ',' && *I != '|'; I++);
|
||||
|
||||
// Malformed, no '('
|
||||
if (I != Stop && *I == ')')
|
||||
return 0;
|
||||
|
||||
if (I == Start)
|
||||
return 0;
|
||||
|
||||
// Stash the package name
|
||||
Package.assign(Start,I - Start);
|
||||
|
||||
// Skip white space to the '('
|
||||
for (;I != Stop && isspace(*I) != 0 ; I++);
|
||||
|
||||
// Parse a version
|
||||
if (I != Stop && *I == '(')
|
||||
{
|
||||
// Skip the '('
|
||||
for (I++; I != Stop && isspace(*I) != 0 ; I++);
|
||||
if (I + 3 >= Stop)
|
||||
return 0;
|
||||
|
||||
// Determine the operator
|
||||
switch (*I)
|
||||
{
|
||||
case '<':
|
||||
I++;
|
||||
if (*I == '=')
|
||||
{
|
||||
I++;
|
||||
Op = pkgCache::Dep::LessEq;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*I == '<')
|
||||
{
|
||||
I++;
|
||||
Op = pkgCache::Dep::Less;
|
||||
break;
|
||||
}
|
||||
|
||||
// < is the same as <= and << is really Cs < for some reason
|
||||
Op = pkgCache::Dep::LessEq;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
I++;
|
||||
if (*I == '=')
|
||||
{
|
||||
I++;
|
||||
Op = pkgCache::Dep::GreaterEq;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*I == '>')
|
||||
{
|
||||
I++;
|
||||
Op = pkgCache::Dep::Greater;
|
||||
break;
|
||||
}
|
||||
|
||||
// > is the same as >= and >> is really Cs > for some reason
|
||||
Op = pkgCache::Dep::GreaterEq;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
Op = pkgCache::Dep::Equals;
|
||||
I++;
|
||||
break;
|
||||
|
||||
// HACK around bad package definitions
|
||||
default:
|
||||
Op = pkgCache::Dep::Equals;
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip whitespace
|
||||
for (;I != Stop && isspace(*I) != 0; I++);
|
||||
Start = I;
|
||||
for (;I != Stop && *I != ')'; I++);
|
||||
if (I == Stop || Start == I)
|
||||
return 0;
|
||||
|
||||
// Skip trailing whitespace
|
||||
const char *End = I;
|
||||
for (; End > Start && isspace(End[-1]); End--);
|
||||
|
||||
Ver = string(Start,End-Start);
|
||||
I++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ver = string();
|
||||
Op = pkgCache::Dep::NoOp;
|
||||
}
|
||||
|
||||
// Skip whitespace
|
||||
for (;I != Stop && isspace(*I) != 0; I++);
|
||||
if (I != Stop && *I == '|')
|
||||
Op |= pkgCache::Dep::Or;
|
||||
|
||||
if (I == Stop || *I == ',' || *I == '|')
|
||||
{
|
||||
if (I != Stop)
|
||||
for (I++; I != Stop && isspace(*I) != 0; I++);
|
||||
return I;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::ParseDepends - Parse a dependency list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is the higher level depends parser. It takes a tag and generates
|
||||
a complete depends tree for the given version. */
|
||||
bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
|
||||
const char *Tag,unsigned int Type)
|
||||
{
|
||||
const char *Start;
|
||||
const char *Stop;
|
||||
if (Section.Find(Tag,Start,Stop) == false)
|
||||
return true;
|
||||
|
||||
string Package;
|
||||
string Version;
|
||||
unsigned int Op;
|
||||
|
||||
while (1)
|
||||
{
|
||||
Start = ParseDepends(Start,Stop,Package,Version,Op);
|
||||
if (Start == 0)
|
||||
return _error->Error("Problem parsing dependency %s",Tag);
|
||||
|
||||
if (NewDepends(Ver,Package,Version,Op,Type) == false)
|
||||
return false;
|
||||
if (Start == Stop)
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::ParseProvides - Parse the provides list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
|
||||
{
|
||||
const char *Start;
|
||||
const char *Stop;
|
||||
if (Section.Find("Provides",Start,Stop) == false)
|
||||
return true;
|
||||
|
||||
string Package;
|
||||
string Version;
|
||||
unsigned int Op;
|
||||
|
||||
while (1)
|
||||
{
|
||||
Start = ParseDepends(Start,Stop,Package,Version,Op);
|
||||
if (Start == 0)
|
||||
return _error->Error("Problem parsing Provides line");
|
||||
if (Op != pkgCache::Dep::NoOp)
|
||||
return _error->Error("Malformed provides line");
|
||||
|
||||
if (NewProvides(Ver,Package,Version) == false)
|
||||
return false;
|
||||
|
||||
if (Start == Stop)
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::GrabWord - Matches a word and returns /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Looks for a word in a list of words - for ParseStatus */
|
||||
bool debListParser::GrabWord(string Word,WordList *List,int Count,
|
||||
unsigned char &Out)
|
||||
{
|
||||
for (int C = 0; C != Count; C++)
|
||||
{
|
||||
if (strcasecmp(Word.c_str(),List[C].Str) == 0)
|
||||
{
|
||||
Out = List[C].Val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::Step - Move to the next section in the file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This has to be carefull to only process the correct architecture */
|
||||
bool debListParser::Step()
|
||||
{
|
||||
iOffset = Tags.Offset();
|
||||
while (Tags.Step(Section) == true)
|
||||
{
|
||||
/* See if this is the correct Architecture, if it isn't then we
|
||||
drop the whole section. A missing arch tag only happens (in theory)
|
||||
inside the Status file, so that is a positive return */
|
||||
const char *Start;
|
||||
const char *Stop;
|
||||
if (Section.Find("Architecture",Start,Stop) == false)
|
||||
return true;
|
||||
|
||||
if (stringcmp(Start,Stop,Arch.begin(),Arch.end()) == 0)
|
||||
return true;
|
||||
|
||||
if (stringcmp(Start,Stop,"all") == 0)
|
||||
return true;
|
||||
|
||||
iOffset = Tags.Offset();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::LoadReleaseInfo - Load the release information /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
|
||||
FileFd &File)
|
||||
{
|
||||
pkgTagFile Tags(File);
|
||||
pkgTagSection Section;
|
||||
if (Tags.Step(Section) == false)
|
||||
return false;
|
||||
|
||||
const char *Start;
|
||||
const char *Stop;
|
||||
if (Section.Find("Archive",Start,Stop) == true)
|
||||
FileI->Archive = WriteUniqString(Start,Stop - Start);
|
||||
if (Section.Find("Component",Start,Stop) == true)
|
||||
FileI->Component = WriteUniqString(Start,Stop - Start);
|
||||
if (Section.Find("Version",Start,Stop) == true)
|
||||
FileI->Version = WriteUniqString(Start,Stop - Start);
|
||||
if (Section.Find("Origin",Start,Stop) == true)
|
||||
FileI->Origin = WriteUniqString(Start,Stop - Start);
|
||||
if (Section.Find("Label",Start,Stop) == true)
|
||||
FileI->Label = WriteUniqString(Start,Stop - Start);
|
||||
if (Section.Find("Architecture",Start,Stop) == true)
|
||||
FileI->Architecture = WriteUniqString(Start,Stop - Start);
|
||||
|
||||
if (Section.FindFlag("NotAutomatic",FileI->Flags,
|
||||
pkgCache::Flag::NotAutomatic) == false)
|
||||
_error->Warning("Bad NotAutomatic flag");
|
||||
|
||||
return !_error->PendingError();
|
||||
}
|
||||
/*}}}*/
|
60
apt/apt-pkg/deb/deblistparser.h
Normal file
60
apt/apt-pkg/deb/deblistparser.h
Normal file
@ -0,0 +1,60 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: deblistparser.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Debian Package List Parser - This implements the abstract parser
|
||||
interface for Debian package files
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_DEBLISTPARSER_H
|
||||
#define PKGLIB_DEBLISTPARSER_H
|
||||
|
||||
#include <apt-pkg/pkgcachegen.h>
|
||||
#include <apt-pkg/tagfile.h>
|
||||
|
||||
class debListParser : public pkgCacheGenerator::ListParser
|
||||
{
|
||||
pkgTagFile Tags;
|
||||
pkgTagSection Section;
|
||||
unsigned long iOffset;
|
||||
string Arch;
|
||||
|
||||
// Parser Helper
|
||||
struct WordList
|
||||
{
|
||||
char *Str;
|
||||
unsigned char Val;
|
||||
};
|
||||
|
||||
unsigned long UniqFindTagWrite(const char *Tag);
|
||||
bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver);
|
||||
const char *ParseDepends(const char *Start,const char *Stop,
|
||||
string &Package,string &Ver,unsigned int &Op);
|
||||
bool ParseDepends(pkgCache::VerIterator Ver,const char *Tag,
|
||||
unsigned int Type);
|
||||
bool ParseProvides(pkgCache::VerIterator Ver);
|
||||
bool GrabWord(string Word,WordList *List,int Count,unsigned char &Out);
|
||||
|
||||
public:
|
||||
|
||||
// These all operate against the current section
|
||||
virtual string Package();
|
||||
virtual string Version();
|
||||
virtual bool NewVersion(pkgCache::VerIterator Ver);
|
||||
virtual unsigned short VersionHash();
|
||||
virtual bool UsePackage(pkgCache::PkgIterator Pkg,
|
||||
pkgCache::VerIterator Ver);
|
||||
virtual unsigned long Offset() {return iOffset;};
|
||||
virtual unsigned long Size() {return Section.size();};
|
||||
|
||||
virtual bool Step();
|
||||
|
||||
bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File);
|
||||
|
||||
debListParser(FileFd &File);
|
||||
};
|
||||
|
||||
#endif
|
89
apt/apt-pkg/deb/debrecords.cc
Normal file
89
apt/apt-pkg/deb/debrecords.cc
Normal file
@ -0,0 +1,89 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: debrecords.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Debian Package Records - Parser for debian package records
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/debrecords.h"
|
||||
#endif
|
||||
#include <apt-pkg/debrecords.h>
|
||||
#include <apt-pkg/error.h>
|
||||
/*}}}*/
|
||||
|
||||
// RecordParser::debRecordParser - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
debRecordParser::debRecordParser(FileFd &File,pkgCache &Cache) :
|
||||
Tags(File,Cache.Head().MaxVerFileSize + 20)
|
||||
{
|
||||
}
|
||||
/*}}}*/
|
||||
// RecordParser::Jump - Jump to a specific record /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
|
||||
{
|
||||
return Tags.Jump(Section,Ver->Offset);
|
||||
}
|
||||
/*}}}*/
|
||||
// RecordParser::FileName - Return the archive filename on the site /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string debRecordParser::FileName()
|
||||
{
|
||||
return Section.FindS("Filename");
|
||||
}
|
||||
/*}}}*/
|
||||
// RecordParser::MD5Hash - Return the archive hash /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string debRecordParser::MD5Hash()
|
||||
{
|
||||
return Section.FindS("MD5sum");
|
||||
}
|
||||
/*}}}*/
|
||||
// RecordParser::Maintainer - Return the maintainer email /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string debRecordParser::Maintainer()
|
||||
{
|
||||
return Section.FindS("Maintainer");
|
||||
}
|
||||
/*}}}*/
|
||||
// RecordParser::ShortDesc - Return a 1 line description /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string debRecordParser::ShortDesc()
|
||||
{
|
||||
string Res = Section.FindS("Description");
|
||||
string::size_type Pos = Res.find('\n');
|
||||
if (Pos == string::npos)
|
||||
return Res;
|
||||
return string(Res,0,Pos);
|
||||
}
|
||||
/*}}}*/
|
||||
// RecordParser::LongDesc - Return a longer description /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string debRecordParser::LongDesc()
|
||||
{
|
||||
return Section.FindS("Description");
|
||||
}
|
||||
/*}}}*/
|
||||
// RecordParser::SourcePkg - Return the source package name if any /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
string debRecordParser::SourcePkg()
|
||||
{
|
||||
string Res = Section.FindS("Source");
|
||||
string::size_type Pos = Res.find(' ');
|
||||
if (Pos == string::npos)
|
||||
return Res;
|
||||
return string(Res,0,Pos);
|
||||
}
|
||||
/*}}}*/
|
50
apt/apt-pkg/deb/debrecords.h
Normal file
50
apt/apt-pkg/deb/debrecords.h
Normal file
@ -0,0 +1,50 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: debrecords.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Debian Package Records - Parser for debian package records
|
||||
|
||||
This provides display-type parsing for the Packages file. This is
|
||||
different than the the list parser which provides cache generation
|
||||
services. There should be no overlap between these two.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_DEBRECORDS_H
|
||||
#define PKGLIB_DEBRECORDS_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/debrecords.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/pkgrecords.h>
|
||||
#include <apt-pkg/tagfile.h>
|
||||
|
||||
class debRecordParser : public pkgRecords::Parser
|
||||
{
|
||||
pkgTagFile Tags;
|
||||
pkgTagSection Section;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool Jump(pkgCache::VerFileIterator const &Ver);
|
||||
|
||||
public:
|
||||
|
||||
// These refer to the archive file for the Version
|
||||
virtual string FileName();
|
||||
virtual string MD5Hash();
|
||||
virtual string SourcePkg();
|
||||
|
||||
// These are some general stats about the package
|
||||
virtual string Maintainer();
|
||||
virtual string ShortDesc();
|
||||
virtual string LongDesc();
|
||||
|
||||
debRecordParser(FileFd &File,pkgCache &Cache);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
103
apt/apt-pkg/deb/debsrcrecords.cc
Normal file
103
apt/apt-pkg/deb/debsrcrecords.cc
Normal file
@ -0,0 +1,103 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: debsrcrecords.cc,v 1.2 2000/10/29 20:25:10 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Debian Source Package Records - Parser implementation for Debian style
|
||||
source indexes
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/debsrcrecords.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/debsrcrecords.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
/*}}}*/
|
||||
|
||||
// SrcRecordParser::Binaries - Return the binaries field /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This member parses the binaries field into a pair of class arrays and
|
||||
returns a list of strings representing all of the components of the
|
||||
binaries field. The returned array need not be freed and will be
|
||||
reused by the next Binaries function call. */
|
||||
const char **debSrcRecordParser::Binaries()
|
||||
{
|
||||
string Bins = Sect.FindS("Binary");
|
||||
char *Buf = Buffer;
|
||||
unsigned int Bin = 0;
|
||||
if (Bins.empty() == true)
|
||||
return 0;
|
||||
// XXX no bounds check: exploitable?
|
||||
// Strip any leading spaces
|
||||
string::const_iterator Start = Bins.begin();
|
||||
for (; Start != Bins.end() && isspace(*Start) != 0; Start++);
|
||||
|
||||
string::const_iterator Pos = Start;
|
||||
while (Pos != Bins.end())
|
||||
{
|
||||
// Skip to the next ','
|
||||
for (; Pos != Bins.end() && *Pos != ','; Pos++);
|
||||
|
||||
// Back remove spaces
|
||||
string::const_iterator End = Pos;
|
||||
for (; End > Start && (End[-1] == ',' || isspace(End[-1]) != 0); End--);
|
||||
|
||||
// Stash the string
|
||||
memcpy(Buf,Start,End-Start);
|
||||
StaticBinList[Bin] = Buf;
|
||||
Bin++;
|
||||
Buf += End-Start;
|
||||
*Buf++ = 0;
|
||||
|
||||
// Advance pos
|
||||
for (; Pos != Bins.end() && (*Pos == ',' || isspace(*Pos) != 0); Pos++);
|
||||
Start = Pos;
|
||||
}
|
||||
|
||||
StaticBinList[Bin] = 0;
|
||||
return StaticBinList;
|
||||
}
|
||||
/*}}}*/
|
||||
// SrcRecordParser::Files - Return a list of files for this source /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This parses the list of files and returns it, each file is required to have
|
||||
a complete source package */
|
||||
bool debSrcRecordParser::Files(vector<pkgSrcRecords::File> &List)
|
||||
{
|
||||
List.erase(List.begin(),List.end());
|
||||
|
||||
string Files = Sect.FindS("Files");
|
||||
if (Files.empty() == true)
|
||||
return false;
|
||||
|
||||
// Stash the / terminated directory prefix
|
||||
string Base = Sect.FindS("Directory");
|
||||
if (Base.empty() == false && Base[Base.length()-1] != '/')
|
||||
Base += '/';
|
||||
|
||||
// Iterate over the entire list grabbing each triplet
|
||||
const char *C = Files.c_str();
|
||||
while (*C != 0)
|
||||
{
|
||||
pkgSrcRecords::File F;
|
||||
string Size;
|
||||
|
||||
// Parse each of the elements
|
||||
if (ParseQuoteWord(C,F.MD5Hash) == false ||
|
||||
ParseQuoteWord(C,Size) == false ||
|
||||
ParseQuoteWord(C,F.Path) == false)
|
||||
return _error->Error("Error parsing file record");
|
||||
|
||||
// Parse the size and append the directory
|
||||
F.Size = atoi(Size.c_str());
|
||||
F.Path = Base + F.Path;
|
||||
List.push_back(F);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
54
apt/apt-pkg/deb/debsrcrecords.h
Normal file
54
apt/apt-pkg/deb/debsrcrecords.h
Normal file
@ -0,0 +1,54 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: debsrcrecords.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Debian Source Package Records - Parser implementation for Debian style
|
||||
source indexes
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_DEBSRCRECORDS_H
|
||||
#define PKGLIB_DEBSRCRECORDS_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/debsrcrecords.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/srcrecords.h>
|
||||
#include <apt-pkg/tagfile.h>
|
||||
|
||||
class debSrcRecordParser : public pkgSrcRecords::Parser
|
||||
{
|
||||
pkgTagFile Tags;
|
||||
pkgTagSection Sect;
|
||||
char Buffer[10000];
|
||||
const char *StaticBinList[400];
|
||||
unsigned long iOffset;
|
||||
|
||||
public:
|
||||
|
||||
virtual bool Restart() {return Tags.Jump(Sect,0);};
|
||||
virtual bool Step() {iOffset = Tags.Offset(); return Tags.Step(Sect);};
|
||||
virtual bool Jump(unsigned long Off) {iOffset = Off; return Tags.Jump(Sect,Off);};
|
||||
|
||||
virtual string Package() {return Sect.FindS("Package");};
|
||||
virtual string Version() {return Sect.FindS("Version");};
|
||||
virtual string Maintainer() {return Sect.FindS("Maintainer");};
|
||||
virtual string Section() {return Sect.FindS("Section");};
|
||||
virtual const char **Binaries();
|
||||
virtual unsigned long Offset() {return iOffset;};
|
||||
virtual string AsStr()
|
||||
{
|
||||
const char *Start=0,*Stop=0;
|
||||
Sect.GetSection(Start,Stop);
|
||||
return string(Start,Stop);
|
||||
};
|
||||
virtual bool Files(vector<pkgSrcRecords::File> &F);
|
||||
|
||||
debSrcRecordParser(FileFd *File,pkgSourceList::const_iterator SrcItem) :
|
||||
Parser(File,SrcItem),
|
||||
Tags(*File,sizeof(Buffer)) {};
|
||||
};
|
||||
|
||||
#endif
|
119
apt/apt-pkg/deb/dpkginit.cc
Normal file
119
apt/apt-pkg/deb/dpkginit.cc
Normal file
@ -0,0 +1,119 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: dpkginit.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
DPKG init - Initialize the dpkg stuff
|
||||
|
||||
This class provides the locking mechanism used by dpkg for its
|
||||
database area. It does the proper consistency checks and acquires the
|
||||
correct kind of lock.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Includes /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/dpkginit.h"
|
||||
#endif
|
||||
#include <apt-pkg/dpkginit.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/fileutl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
/*}}}*/
|
||||
|
||||
// DpkgLock::pkgDpkgLock - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgDpkgLock::pkgDpkgLock(bool WithUpdates)
|
||||
{
|
||||
LockFD = -1;
|
||||
GetLock(WithUpdates);
|
||||
}
|
||||
/*}}}*/
|
||||
// DpkgLock::~pkgDpkgLock - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgDpkgLock::~pkgDpkgLock()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
/*}}}*/
|
||||
// DpkgLock::GetLock - Get the lock /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This mirrors the operations dpkg does when it starts up. Note the
|
||||
checking of the updates directory. */
|
||||
bool pkgDpkgLock::GetLock(bool WithUpdates)
|
||||
{
|
||||
// Disable file locking
|
||||
if (_config->FindB("Debug::NoLocking",false) == true)
|
||||
return true;
|
||||
|
||||
Close();
|
||||
|
||||
// Create the lockfile
|
||||
string AdminDir = flNotFile(_config->Find("Dir::State::status"));
|
||||
LockFD = ::GetLock(AdminDir + "lock");
|
||||
if (LockFD == -1)
|
||||
return _error->Error("Unable to lock the administration directory, "
|
||||
"are you root?");
|
||||
|
||||
// See if we need to abort with a dirty journal
|
||||
if (WithUpdates == true && CheckUpdates() == true)
|
||||
{
|
||||
Close();
|
||||
return _error->Error("dpkg was interrupted, you must manually "
|
||||
"run 'dpkg --configure -a' to correct the problem. ");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// DpkgLock::Close - Close the lock /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgDpkgLock::Close()
|
||||
{
|
||||
close(LockFD);
|
||||
LockFD = -1;
|
||||
}
|
||||
/*}}}*/
|
||||
// DpkgLock::CheckUpdates - Check if the updates dir is dirty /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This does a check of the updates directory to see if it has any entries
|
||||
in it. */
|
||||
bool pkgDpkgLock::CheckUpdates()
|
||||
{
|
||||
// Check for updates.. (dirty)
|
||||
string File = flNotFile(_config->Find("Dir::State::status")) + "updates/";
|
||||
DIR *DirP = opendir(File.c_str());
|
||||
if (DirP == 0)
|
||||
return false;
|
||||
|
||||
/* We ignore any files that are not all digits, this skips .,.. and
|
||||
some tmp files dpkg will leave behind.. */
|
||||
bool Damaged = false;
|
||||
for (struct dirent *Ent = readdir(DirP); Ent != 0; Ent = readdir(DirP))
|
||||
{
|
||||
Damaged = true;
|
||||
for (unsigned int I = 0; Ent->d_name[I] != 0; I++)
|
||||
{
|
||||
// Check if its not a digit..
|
||||
if (isdigit(Ent->d_name[I]) == 0)
|
||||
{
|
||||
Damaged = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Damaged == true)
|
||||
break;
|
||||
}
|
||||
closedir(DirP);
|
||||
|
||||
return Damaged;
|
||||
}
|
||||
/*}}}*/
|
||||
|
34
apt/apt-pkg/deb/dpkginit.h
Normal file
34
apt/apt-pkg/deb/dpkginit.h
Normal file
@ -0,0 +1,34 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: dpkginit.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
DPKG init - Initialize the dpkg stuff
|
||||
|
||||
This basically gets a lock in /var/lib/dpkg and checks the updates
|
||||
directory
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_DPKGINIT_H
|
||||
#define PKGLIB_DPKGINIT_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/dpkginit.h"
|
||||
#endif
|
||||
|
||||
class pkgDpkgLock
|
||||
{
|
||||
int LockFD;
|
||||
|
||||
public:
|
||||
|
||||
bool CheckUpdates();
|
||||
bool GetLock(bool WithUpdates);
|
||||
void Close();
|
||||
|
||||
pkgDpkgLock(bool WithUpdates = true);
|
||||
~pkgDpkgLock();
|
||||
};
|
||||
|
||||
#endif
|
408
apt/apt-pkg/deb/dpkgpm.cc
Normal file
408
apt/apt-pkg/deb/dpkgpm.cc
Normal file
@ -0,0 +1,408 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: dpkgpm.cc,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
DPKG Package Manager - Provide an interface to dpkg
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Includes /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/dpkgpm.h"
|
||||
#endif
|
||||
#include <apt-pkg/dpkgpm.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
/*}}}*/
|
||||
|
||||
// DPkgPM::pkgDPkgPM - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgDPkgPM::pkgDPkgPM(pkgDepCache &Cache) : pkgPackageManager(Cache)
|
||||
{
|
||||
}
|
||||
/*}}}*/
|
||||
// DPkgPM::pkgDPkgPM - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgDPkgPM::~pkgDPkgPM()
|
||||
{
|
||||
}
|
||||
/*}}}*/
|
||||
// DPkgPM::Install - Install a package /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Add an install operation to the sequence list */
|
||||
bool pkgDPkgPM::Install(PkgIterator Pkg,string File)
|
||||
{
|
||||
if (File.empty() == true || Pkg.end() == true)
|
||||
return _error->Error("Internal Error, No file name for %s",Pkg.Name());
|
||||
|
||||
List.push_back(Item(Item::Install,Pkg,File));
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// DPkgPM::Configure - Configure a package /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Add a configure operation to the sequence list */
|
||||
bool pkgDPkgPM::Configure(PkgIterator Pkg)
|
||||
{
|
||||
if (Pkg.end() == true)
|
||||
return false;
|
||||
|
||||
List.push_back(Item(Item::Configure,Pkg));
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// DPkgPM::Remove - Remove a package /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Add a remove operation to the sequence list */
|
||||
bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge)
|
||||
{
|
||||
if (Pkg.end() == true)
|
||||
return false;
|
||||
|
||||
if (Purge == true)
|
||||
List.push_back(Item(Item::Purge,Pkg));
|
||||
else
|
||||
List.push_back(Item(Item::Remove,Pkg));
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// DPkgPM::RunScripts - Run a set of scripts /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This looks for a list of script sto run from the configuration file,
|
||||
each one is run with system from a forked child. */
|
||||
bool pkgDPkgPM::RunScripts(const char *Cnf)
|
||||
{
|
||||
Configuration::Item const *Opts = _config->Tree(Cnf);
|
||||
if (Opts == 0 || Opts->Child == 0)
|
||||
return true;
|
||||
Opts = Opts->Child;
|
||||
|
||||
// Fork for running the system calls
|
||||
pid_t Child = ExecFork();
|
||||
|
||||
// This is the child
|
||||
if (Child == 0)
|
||||
{
|
||||
if (chdir("/tmp/") != 0)
|
||||
_exit(100);
|
||||
|
||||
unsigned int Count = 1;
|
||||
for (; Opts != 0; Opts = Opts->Next, Count++)
|
||||
{
|
||||
if (Opts->Value.empty() == true)
|
||||
continue;
|
||||
|
||||
if (system(Opts->Value.c_str()) != 0)
|
||||
_exit(100+Count);
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
// Wait for the child
|
||||
int Status = 0;
|
||||
while (waitpid(Child,&Status,0) != Child)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return _error->Errno("waitpid","Couldn't wait for subprocess");
|
||||
}
|
||||
|
||||
// Restore sig int/quit
|
||||
signal(SIGQUIT,SIG_DFL);
|
||||
signal(SIGINT,SIG_DFL);
|
||||
|
||||
// Check for an error code.
|
||||
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
|
||||
{
|
||||
unsigned int Count = WEXITSTATUS(Status);
|
||||
if (Count > 100)
|
||||
{
|
||||
Count -= 100;
|
||||
for (; Opts != 0 && Count != 1; Opts = Opts->Next, Count--);
|
||||
_error->Error("Problem executing scripts %s '%s'",Cnf,Opts->Value.c_str());
|
||||
}
|
||||
|
||||
return _error->Error("Sub-process returned an error code");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*}}}*/
|
||||
// DPkgPM::RunScriptsWithPkgs - Run scripts with package names on stdin /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This looks for a list of scripts to run from the configuration file
|
||||
each one is run and is fed on standard input a list of all .deb files
|
||||
that are due to be installed. */
|
||||
bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
|
||||
{
|
||||
Configuration::Item const *Opts = _config->Tree(Cnf);
|
||||
if (Opts == 0 || Opts->Child == 0)
|
||||
return true;
|
||||
Opts = Opts->Child;
|
||||
|
||||
unsigned int Count = 1;
|
||||
for (; Opts != 0; Opts = Opts->Next, Count++)
|
||||
{
|
||||
if (Opts->Value.empty() == true)
|
||||
continue;
|
||||
|
||||
// Create the pipes
|
||||
int Pipes[2];
|
||||
if (pipe(Pipes) != 0)
|
||||
return _error->Errno("pipe","Failed to create IPC pipe to subprocess");
|
||||
SetCloseExec(Pipes[0],true);
|
||||
SetCloseExec(Pipes[1],true);
|
||||
|
||||
// Purified Fork for running the script
|
||||
pid_t Process = ExecFork();
|
||||
if (Process == 0)
|
||||
{
|
||||
// Setup the FDs
|
||||
dup2(Pipes[0],STDIN_FILENO);
|
||||
SetCloseExec(STDOUT_FILENO,false);
|
||||
SetCloseExec(STDIN_FILENO,false);
|
||||
SetCloseExec(STDERR_FILENO,false);
|
||||
|
||||
const char *Args[4];
|
||||
Args[0] = "/bin/sh";
|
||||
Args[1] = "-c";
|
||||
Args[2] = Opts->Value.c_str();
|
||||
Args[3] = 0;
|
||||
execv(Args[0],(char **)Args);
|
||||
_exit(100);
|
||||
}
|
||||
close(Pipes[0]);
|
||||
FileFd Fd(Pipes[1]);
|
||||
|
||||
// Feed it the filenames.
|
||||
for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
|
||||
{
|
||||
// Only deal with packages to be installed from .deb
|
||||
if (I->Op != Item::Install)
|
||||
continue;
|
||||
|
||||
// No errors here..
|
||||
if (I->File[0] != '/')
|
||||
continue;
|
||||
|
||||
/* Feed the filename of each package that is pending install
|
||||
into the pipe. */
|
||||
if (Fd.Write(I->File.begin(),I->File.length()) == false ||
|
||||
Fd.Write("\n",1) == false)
|
||||
{
|
||||
kill(Process,SIGINT);
|
||||
Fd.Close();
|
||||
ExecWait(Process,Opts->Value.c_str(),true);
|
||||
return _error->Error("Failure running script %s",Opts->Value.c_str());
|
||||
}
|
||||
}
|
||||
Fd.Close();
|
||||
|
||||
// Clean up the sub process
|
||||
if (ExecWait(Process,Opts->Value.c_str()) == false)
|
||||
return _error->Error("Failure running script %s",Opts->Value.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*}}}*/
|
||||
// DPkgPM::Go - Run the sequence /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This globs the operations and calls dpkg */
|
||||
bool pkgDPkgPM::Go()
|
||||
{
|
||||
if (RunScripts("DPkg::Pre-Invoke") == false)
|
||||
return false;
|
||||
|
||||
if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
|
||||
return false;
|
||||
|
||||
for (vector<Item>::iterator I = List.begin(); I != List.end();)
|
||||
{
|
||||
vector<Item>::iterator J = I;
|
||||
for (; J != List.end() && J->Op == I->Op; J++);
|
||||
|
||||
// Generate the argument list
|
||||
const char *Args[400];
|
||||
if (J - I > 350)
|
||||
J = I + 350;
|
||||
|
||||
unsigned int n = 0;
|
||||
unsigned long Size = 0;
|
||||
Args[n++] = _config->Find("Dir::Bin::dpkg","dpkg").c_str();
|
||||
Size += strlen(Args[n-1]);
|
||||
|
||||
// Stick in any custom dpkg options
|
||||
Configuration::Item const *Opts = _config->Tree("DPkg::Options");
|
||||
if (Opts != 0)
|
||||
{
|
||||
Opts = Opts->Child;
|
||||
for (; Opts != 0; Opts = Opts->Next)
|
||||
{
|
||||
if (Opts->Value.empty() == true)
|
||||
continue;
|
||||
Args[n++] = Opts->Value.c_str();
|
||||
Size += Opts->Value.length();
|
||||
}
|
||||
}
|
||||
|
||||
switch (I->Op)
|
||||
{
|
||||
case Item::Remove:
|
||||
Args[n++] = "--force-depends";
|
||||
Size += strlen(Args[n-1]);
|
||||
Args[n++] = "--force-remove-essential";
|
||||
Size += strlen(Args[n-1]);
|
||||
Args[n++] = "--remove";
|
||||
Size += strlen(Args[n-1]);
|
||||
break;
|
||||
|
||||
case Item::Purge:
|
||||
Args[n++] = "--force-depends";
|
||||
Size += strlen(Args[n-1]);
|
||||
Args[n++] = "--force-remove-essential";
|
||||
Size += strlen(Args[n-1]);
|
||||
Args[n++] = "--purge";
|
||||
Size += strlen(Args[n-1]);
|
||||
break;
|
||||
|
||||
case Item::Configure:
|
||||
Args[n++] = "--configure";
|
||||
Size += strlen(Args[n-1]);
|
||||
break;
|
||||
|
||||
case Item::Install:
|
||||
Args[n++] = "--unpack";
|
||||
Size += strlen(Args[n-1]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Write in the file or package names
|
||||
if (I->Op == Item::Install)
|
||||
{
|
||||
for (;I != J && Size < 1024; I++)
|
||||
{
|
||||
if (I->File[0] != '/')
|
||||
return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str());
|
||||
Args[n++] = I->File.c_str();
|
||||
Size += strlen(Args[n-1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;I != J && Size < 1024; I++)
|
||||
{
|
||||
Args[n++] = I->Pkg.Name();
|
||||
Size += strlen(Args[n-1]);
|
||||
}
|
||||
}
|
||||
Args[n] = 0;
|
||||
J = I;
|
||||
|
||||
if (_config->FindB("Debug::pkgDPkgPM",false) == true)
|
||||
{
|
||||
for (unsigned int k = 0; k != n; k++)
|
||||
clog << Args[k] << ' ';
|
||||
clog << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
cout << flush;
|
||||
clog << flush;
|
||||
cerr << flush;
|
||||
|
||||
/* Mask off sig int/quit. We do this because dpkg also does when
|
||||
it forks scripts. What happens is that when you hit ctrl-c it sends
|
||||
it to all processes in the group. Since dpkg ignores the signal
|
||||
it doesn't die but we do! So we must also ignore it */
|
||||
signal(SIGQUIT,SIG_IGN);
|
||||
signal(SIGINT,SIG_IGN);
|
||||
|
||||
// Fork dpkg
|
||||
pid_t Child = ExecFork();
|
||||
|
||||
// This is the child
|
||||
if (Child == 0)
|
||||
{
|
||||
if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
|
||||
_exit(100);
|
||||
|
||||
if (_config->FindB("DPkg::FlushSTDIN",true) == true)
|
||||
{
|
||||
int Flags,dummy;
|
||||
if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0)
|
||||
_exit(100);
|
||||
|
||||
// Discard everything in stdin before forking dpkg
|
||||
if (fcntl(STDIN_FILENO,F_SETFL,Flags | O_NONBLOCK) < 0)
|
||||
_exit(100);
|
||||
|
||||
while (read(STDIN_FILENO,&dummy,1) == 1);
|
||||
|
||||
if (fcntl(STDIN_FILENO,F_SETFL,Flags & (~(long)O_NONBLOCK)) < 0)
|
||||
_exit(100);
|
||||
}
|
||||
|
||||
/* No Job Control Stop Env is a magic dpkg var that prevents it
|
||||
from using sigstop */
|
||||
putenv("DPKG_NO_TSTP=yes");
|
||||
execvp(Args[0],(char **)Args);
|
||||
cerr << "Could not exec dpkg!" << endl;
|
||||
_exit(100);
|
||||
}
|
||||
|
||||
// Wait for dpkg
|
||||
int Status = 0;
|
||||
while (waitpid(Child,&Status,0) != Child)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
RunScripts("DPkg::Post-Invoke");
|
||||
return _error->Errno("waitpid","Couldn't wait for subprocess");
|
||||
}
|
||||
|
||||
// Restore sig int/quit
|
||||
signal(SIGQUIT,SIG_DFL);
|
||||
signal(SIGINT,SIG_DFL);
|
||||
|
||||
// Check for an error code.
|
||||
if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
|
||||
{
|
||||
RunScripts("DPkg::Post-Invoke");
|
||||
if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV)
|
||||
return _error->Error("Sub-process %s recieved a segmentation fault.",Args[0]);
|
||||
|
||||
if (WIFEXITED(Status) != 0)
|
||||
return _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
|
||||
|
||||
return _error->Error("Sub-process %s exited unexpectedly",Args[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (RunScripts("DPkg::Post-Invoke") == false)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// pkgDpkgPM::Reset - Dump the contents of the command list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgDPkgPM::Reset()
|
||||
{
|
||||
List.erase(List.begin(),List.end());
|
||||
}
|
||||
/*}}}*/
|
53
apt/apt-pkg/deb/dpkgpm.h
Normal file
53
apt/apt-pkg/deb/dpkgpm.h
Normal file
@ -0,0 +1,53 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: dpkgpm.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
DPKG Package Manager - Provide an interface to dpkg
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
#ifndef PKGLIB_DPKGPM_H
|
||||
#define PKGLIB_DPKGPM_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/dpkgpm.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/packagemanager.h>
|
||||
#include <vector>
|
||||
|
||||
class pkgDPkgPM : public pkgPackageManager
|
||||
{
|
||||
protected:
|
||||
|
||||
struct Item
|
||||
{
|
||||
enum Ops {Install, Configure, Remove, Purge} Op;
|
||||
string File;
|
||||
PkgIterator Pkg;
|
||||
Item(Ops Op,PkgIterator Pkg,string File = "") : Op(Op),
|
||||
File(File), Pkg(Pkg) {};
|
||||
Item() {};
|
||||
|
||||
};
|
||||
vector<Item> List;
|
||||
|
||||
// Helpers
|
||||
bool RunScripts(const char *Cnf);
|
||||
bool RunScriptsWithPkgs(const char *Cnf);
|
||||
|
||||
// The Actuall installation implementation
|
||||
virtual bool Install(PkgIterator Pkg,string File);
|
||||
virtual bool Configure(PkgIterator Pkg);
|
||||
virtual bool Remove(PkgIterator Pkg,bool Purge = false);
|
||||
virtual bool Go();
|
||||
virtual void Reset();
|
||||
|
||||
public:
|
||||
|
||||
pkgDPkgPM(pkgDepCache &Cache);
|
||||
virtual ~pkgDPkgPM();
|
||||
};
|
||||
|
||||
#endif
|
941
apt/apt-pkg/depcache.cc
Normal file
941
apt/apt-pkg/depcache.cc
Normal file
@ -0,0 +1,941 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: depcache.cc,v 1.20 2001/11/13 17:32:07 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Dependency Cache - Caches Dependency information.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/depcache.h"
|
||||
#endif
|
||||
#include <apt-pkg/depcache.h>
|
||||
#include <apt-pkg/systemfactory.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/sptr.h>
|
||||
|
||||
#include <i18n.h>
|
||||
/*}}}*/
|
||||
|
||||
// DepCache::pkgDepCache - Constructors /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgDepCache::pkgDepCache(MMap &Map,OpProgress &Prog) :
|
||||
pkgCache(Map), PkgState(0), DepState(0)
|
||||
{
|
||||
if (_error->PendingError() == false)
|
||||
Init(&Prog);
|
||||
}
|
||||
pkgDepCache::pkgDepCache(MMap &Map) :
|
||||
pkgCache(Map), PkgState(0), DepState(0)
|
||||
{
|
||||
if (_error->PendingError() == false)
|
||||
Init(0);
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::~pkgDepCache - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgDepCache::~pkgDepCache()
|
||||
{
|
||||
delete [] PkgState;
|
||||
delete [] DepState;
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::Init - Generate the initial extra structures. /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This allocats the extension buffers and initializes them. */
|
||||
bool pkgDepCache::Init(OpProgress *Prog)
|
||||
{
|
||||
delete [] PkgState;
|
||||
delete [] DepState;
|
||||
PkgState = new StateCache[Head().PackageCount];
|
||||
DepState = new unsigned char[Head().DependsCount];
|
||||
memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount);
|
||||
memset(DepState,0,sizeof(*DepState)*Head().DependsCount);
|
||||
|
||||
if (Prog != 0)
|
||||
{
|
||||
Prog->OverallProgress(0,2*Head().PackageCount,Head().PackageCount,
|
||||
_("Building Dependency Tree"));
|
||||
Prog->SubProgress(Head().PackageCount,_("Candidate Versions"));
|
||||
}
|
||||
|
||||
/* Set the current state of everything. In this state all of the
|
||||
packages are kept exactly as is. See AllUpgrade */
|
||||
int Done = 0;
|
||||
for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
|
||||
{
|
||||
if (Prog != 0)
|
||||
Prog->Progress(Done);
|
||||
|
||||
// Find the proper cache slot
|
||||
StateCache &State = PkgState[I->ID];
|
||||
State.iFlags = 0;
|
||||
|
||||
// Figure out the install version
|
||||
State.CandidateVer = GetCandidateVer(I);
|
||||
State.InstallVer = I.CurrentVer();
|
||||
State.Mode = ModeKeep;
|
||||
|
||||
State.Update(I,*this);
|
||||
}
|
||||
|
||||
if (Prog != 0)
|
||||
{
|
||||
|
||||
Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount,
|
||||
Head().PackageCount,
|
||||
_("Building Dependency Tree"));
|
||||
Prog->SubProgress(Head().PackageCount,_("Dependency Generation"));
|
||||
}
|
||||
|
||||
Update(Prog);
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::GetCandidateVer - Returns the Candidate install version /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The default just returns the target version if it exists or the
|
||||
highest version. */
|
||||
pkgDepCache::VerIterator pkgDepCache::GetCandidateVer(PkgIterator Pkg,
|
||||
bool AllowCurrent)
|
||||
{
|
||||
// Try to use an explicit target
|
||||
if (Pkg->TargetVer == 0 ||
|
||||
(AllowCurrent == false && Pkg.TargetVer() == Pkg.CurrentVer()))
|
||||
return pkgCache::GetCandidateVer(Pkg,AllowCurrent);
|
||||
else
|
||||
return Pkg.TargetVer();
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::IsImportantDep - True if the dependency is important /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgDepCache::IsImportantDep(DepIterator Dep)
|
||||
{
|
||||
return Dep.IsCritical();
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// DepCache::CheckDep - Checks a single dependency /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This first checks the dependency against the main target package and
|
||||
then walks along the package provides list and checks if each provides
|
||||
will be installed then checks the provides against the dep. Res will be
|
||||
set to the package which was used to satisfy the dep. */
|
||||
bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
|
||||
{
|
||||
Res = Dep.TargetPkg();
|
||||
|
||||
/* Check simple depends. A depends -should- never self match but
|
||||
we allow it anyhow because dpkg does. Technically it is a packaging
|
||||
bug. Conflicts may never self match */
|
||||
if (Dep.TargetPkg() != Dep.ParentPkg()
|
||||
|| (Dep->Type != Dep::Conflicts
|
||||
&& Dep->Type != Dep::Obsoletes))
|
||||
{
|
||||
PkgIterator Pkg = Dep.TargetPkg();
|
||||
|
||||
// Check the base package
|
||||
if (Type == NowVersion && Pkg->CurrentVer != 0)
|
||||
if (_system->checkDep(Dep.TargetVer(),
|
||||
Pkg.CurrentVer().VerStr(),Dep->CompareOp) == true)
|
||||
return true;
|
||||
|
||||
if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0)
|
||||
if (_system->checkDep(Dep.TargetVer(),
|
||||
PkgState[Pkg->ID].InstVerIter(*this).VerStr(),
|
||||
Dep->CompareOp) == true)
|
||||
return true;
|
||||
|
||||
if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0)
|
||||
if (_system->checkDep(Dep.TargetVer(),
|
||||
PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(),
|
||||
Dep->CompareOp) == true)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Dep->Type == Dep::Obsoletes)
|
||||
return false;
|
||||
|
||||
// Check the providing packages
|
||||
PrvIterator P = Dep.TargetPkg().ProvidesList();
|
||||
PkgIterator Pkg = Dep.ParentPkg();
|
||||
|
||||
for (; P.end() != true; P++)
|
||||
{
|
||||
/* Provides may never be applied against the same package if it is
|
||||
a conflicts. See the comment above. */
|
||||
if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
|
||||
continue;
|
||||
|
||||
// Check if the provides is a hit
|
||||
if (Type == NowVersion)
|
||||
{
|
||||
if (P.OwnerPkg().CurrentVer() != P.OwnerVer())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Type == InstallVersion)
|
||||
{
|
||||
StateCache &State = PkgState[P.OwnerPkg()->ID];
|
||||
if (State.InstallVer != (Version *)P.OwnerVer())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Type == CandidateVersion)
|
||||
{
|
||||
StateCache &State = PkgState[P.OwnerPkg()->ID];
|
||||
if (State.CandidateVer != (Version *)P.OwnerVer())
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare the versions.
|
||||
if (_system->checkDep(Dep.TargetVer(),P.ProvideVersion(),Dep->CompareOp) == true)
|
||||
{
|
||||
Res = P.OwnerPkg();
|
||||
/*
|
||||
if (Dep->Type == Dep::Conflicts)
|
||||
cout << "MATCH: " << Res.Name() << "::"<<P.ProvideVersion()
|
||||
<<"::"<<P.OwnerVer().VerStr()<<endl;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::AddSizes - Add the packages sizes to the counters /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Call with Mult = -1 to preform the inverse opration */
|
||||
void pkgDepCache::AddSizes(const PkgIterator &Pkg,long Mult)
|
||||
{
|
||||
StateCache &P = PkgState[Pkg->ID];
|
||||
|
||||
if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
|
||||
P.Keep() == true)
|
||||
return;
|
||||
|
||||
// Compute the size data
|
||||
if (P.NewInstall() == true)
|
||||
{
|
||||
iUsrSize += Mult*P.InstVerIter(*this)->InstalledSize;
|
||||
iDownloadSize += Mult*P.InstVerIter(*this)->Size;
|
||||
return;
|
||||
}
|
||||
|
||||
// Upgrading
|
||||
if (Pkg->CurrentVer != 0 &&
|
||||
(P.InstallVer != (Version *)Pkg.CurrentVer() ||
|
||||
(P.iFlags & ReInstall) == ReInstall) && P.InstallVer != 0)
|
||||
{
|
||||
iUsrSize += Mult*((signed)P.InstVerIter(*this)->InstalledSize -
|
||||
(signed)Pkg.CurrentVer()->InstalledSize);
|
||||
iDownloadSize += Mult*P.InstVerIter(*this)->Size;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reinstall
|
||||
if (Pkg.State() == pkgCache::PkgIterator::NeedsUnpack &&
|
||||
P.Delete() == false)
|
||||
{
|
||||
iDownloadSize += Mult*P.InstVerIter(*this)->Size;
|
||||
return;
|
||||
}
|
||||
|
||||
// Removing
|
||||
if (Pkg->CurrentVer != 0 && P.InstallVer == 0)
|
||||
{
|
||||
iUsrSize -= Mult*Pkg.CurrentVer()->InstalledSize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::AddStates - Add the package to the state counter /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This routine is tricky to use, you must make sure that it is never
|
||||
called twice for the same package. This means the Remove/Add section
|
||||
should be as short as possible and not encompass any code that will
|
||||
calld Remove/Add itself. Remember, dependencies can be circular so
|
||||
while processing a dep for Pkg it is possible that Add/Remove
|
||||
will be called on Pkg */
|
||||
void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
|
||||
{
|
||||
StateCache &State = PkgState[Pkg->ID];
|
||||
|
||||
// The Package is broken
|
||||
if ((State.DepState & DepInstMin) != DepInstMin)
|
||||
iBrokenCount += Add;
|
||||
|
||||
// Bad state
|
||||
if (Pkg.State() != PkgIterator::NeedsNothing)
|
||||
iBadCount += Add;
|
||||
|
||||
// Not installed
|
||||
if (Pkg->CurrentVer == 0)
|
||||
{
|
||||
if (State.Mode == ModeDelete &&
|
||||
(State.iFlags | Purge) == Purge && Pkg.Purge() == false)
|
||||
iDelCount += Add;
|
||||
|
||||
if (State.Mode == ModeInstall)
|
||||
iInstCount += Add;
|
||||
return;
|
||||
}
|
||||
|
||||
// Installed, no upgrade
|
||||
if (State.Upgradable() == false)
|
||||
{
|
||||
if (State.Mode == ModeDelete)
|
||||
iDelCount += Add;
|
||||
else
|
||||
if ((State.iFlags & ReInstall) == ReInstall)
|
||||
iInstCount += Add;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Alll 3 are possible
|
||||
if (State.Mode == ModeDelete)
|
||||
iDelCount += Add;
|
||||
if (State.Mode == ModeKeep)
|
||||
iKeepCount += Add;
|
||||
if (State.Mode == ModeInstall)
|
||||
iInstCount += Add;
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::BuildGroupOrs - Generate the Or group dep data /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The or group results are stored in the last item of the or group. This
|
||||
allows easy detection of the state of a whole or'd group. */
|
||||
void pkgDepCache::BuildGroupOrs(VerIterator const &V)
|
||||
{
|
||||
unsigned char Group = 0;
|
||||
|
||||
for (DepIterator D = V.DependsList(); D.end() != true; D++)
|
||||
{
|
||||
// Build the dependency state.
|
||||
unsigned char &State = DepState[D->ID];
|
||||
|
||||
/* Invert for Conflicts. We have to do this twice to get the
|
||||
right sense for a conflicts group */
|
||||
if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
|
||||
State = ~State;
|
||||
|
||||
// Add to the group if we are within an or..
|
||||
State &= 0x7;
|
||||
Group |= State;
|
||||
State |= Group << 3;
|
||||
if ((D->CompareOp & Dep::Or) != Dep::Or)
|
||||
Group = 0;
|
||||
|
||||
// Invert for Conflicts
|
||||
if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
|
||||
State = ~State;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::VersionState - Perform a pass over a dependency list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is used to run over a dependency list and determine the dep
|
||||
state of the list, filtering it through both a Min check and a Policy
|
||||
check. The return result will have SetMin/SetPolicy low if a check
|
||||
fails. It uses the DepState cache for it's computations. */
|
||||
unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check,
|
||||
unsigned char SetMin,
|
||||
unsigned char SetPolicy)
|
||||
{
|
||||
unsigned char Dep = 0xFF;
|
||||
|
||||
while (D.end() != true)
|
||||
{
|
||||
// Compute a single dependency element (glob or)
|
||||
DepIterator Start = D;
|
||||
unsigned char State = 0;
|
||||
for (bool LastOR = true; D.end() == false && LastOR == true; D++)
|
||||
{
|
||||
State |= DepState[D->ID];
|
||||
LastOR = (D->CompareOp & Dep::Or) == Dep::Or;
|
||||
}
|
||||
|
||||
// Minimum deps that must be satisfied to have a working package
|
||||
if (Start.IsCritical() == true)
|
||||
if ((State & Check) != Check)
|
||||
Dep &= ~SetMin;
|
||||
|
||||
// Policy deps that must be satisfied to install the package
|
||||
if (IsImportantDep(Start) == true &&
|
||||
(State & Check) != Check)
|
||||
Dep &= ~SetPolicy;
|
||||
}
|
||||
|
||||
return Dep;
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::DependencyState - Compute the 3 results for a dep /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is the main dependency computation bit. It computes the 3 main
|
||||
results for a dependencys, Now, Install and Candidate. Callers must
|
||||
invert the result if dealing with conflicts. */
|
||||
unsigned char pkgDepCache::DependencyState(DepIterator &D)
|
||||
{
|
||||
unsigned char State = 0;
|
||||
|
||||
if (CheckDep(D,NowVersion) == true)
|
||||
State |= DepNow;
|
||||
if (CheckDep(D,InstallVersion) == true)
|
||||
State |= DepInstall;
|
||||
if (CheckDep(D,CandidateVersion) == true)
|
||||
State |= DepCVer;
|
||||
|
||||
return State;
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::UpdateVerState - Compute the Dep member of the state /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This determines the combined dependency representation of a package
|
||||
for its two states now and install. This is done by using the pre-generated
|
||||
dependency information. */
|
||||
void pkgDepCache::UpdateVerState(PkgIterator Pkg)
|
||||
{
|
||||
// Empty deps are always true
|
||||
StateCache &State = PkgState[Pkg->ID];
|
||||
State.DepState = 0xFF;
|
||||
|
||||
// Check the Current state
|
||||
if (Pkg->CurrentVer != 0)
|
||||
{
|
||||
DepIterator D = Pkg.CurrentVer().DependsList();
|
||||
State.DepState &= VersionState(D,DepNow,DepNowMin,DepNowPolicy);
|
||||
}
|
||||
|
||||
/* Check the candidate state. We do not compare against the whole as
|
||||
a candidate state but check the candidate version against the
|
||||
install states */
|
||||
if (State.CandidateVer != 0)
|
||||
{
|
||||
DepIterator D = State.CandidateVerIter(*this).DependsList();
|
||||
State.DepState &= VersionState(D,DepInstall,DepCandMin,DepCandPolicy);
|
||||
}
|
||||
|
||||
// Check target state which can only be current or installed
|
||||
if (State.InstallVer != 0)
|
||||
{
|
||||
DepIterator D = State.InstVerIter(*this).DependsList();
|
||||
State.DepState &= VersionState(D,DepInstall,DepInstMin,DepInstPolicy);
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::Update - Figure out all the state information /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This will figure out the state of all the packages and all the
|
||||
dependencies based on the current policy. */
|
||||
void pkgDepCache::Update(OpProgress *Prog)
|
||||
{
|
||||
iUsrSize = 0;
|
||||
iDownloadSize = 0;
|
||||
iDelCount = 0;
|
||||
iInstCount = 0;
|
||||
iKeepCount = 0;
|
||||
iBrokenCount = 0;
|
||||
iBadCount = 0;
|
||||
|
||||
// Perform the depends pass
|
||||
int Done = 0;
|
||||
for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
|
||||
{
|
||||
if (Prog != 0 && Done%20 == 0)
|
||||
Prog->Progress(Done);
|
||||
for (VerIterator V = I.VersionList(); V.end() != true; V++)
|
||||
{
|
||||
unsigned char Group = 0;
|
||||
|
||||
for (DepIterator D = V.DependsList(); D.end() != true; D++)
|
||||
{
|
||||
// Build the dependency state.
|
||||
unsigned char &State = DepState[D->ID];
|
||||
State = DependencyState(D);;
|
||||
|
||||
// Add to the group if we are within an or..
|
||||
Group |= State;
|
||||
State |= Group << 3;
|
||||
if ((D->CompareOp & Dep::Or) != Dep::Or)
|
||||
Group = 0;
|
||||
|
||||
// Invert for Conflicts
|
||||
if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
|
||||
State = ~State;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the pacakge dependency state and size additions
|
||||
AddSizes(I);
|
||||
UpdateVerState(I);
|
||||
AddStates(I);
|
||||
}
|
||||
|
||||
if (Prog != 0)
|
||||
Prog->Progress(Done);
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::Update - Update the deps list of a package /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is a helper for update that only does the dep portion of the scan.
|
||||
It is mainly ment to scan reverse dependencies. */
|
||||
void pkgDepCache::Update(DepIterator D)
|
||||
{
|
||||
// Update the reverse deps
|
||||
for (;D.end() != true; D++)
|
||||
{
|
||||
unsigned char &State = DepState[D->ID];
|
||||
State = DependencyState(D);
|
||||
|
||||
// Invert for Conflicts
|
||||
if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
|
||||
State = ~State;
|
||||
|
||||
RemoveStates(D.ParentPkg());
|
||||
BuildGroupOrs(D.ParentVer());
|
||||
UpdateVerState(D.ParentPkg());
|
||||
AddStates(D.ParentPkg());
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::Update - Update the related deps of a package /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called whenever the state of a package changes. It updates
|
||||
all cached dependencies related to this package. */
|
||||
void pkgDepCache::Update(PkgIterator const &Pkg)
|
||||
{
|
||||
// Recompute the dep of the package
|
||||
RemoveStates(Pkg);
|
||||
UpdateVerState(Pkg);
|
||||
AddStates(Pkg);
|
||||
|
||||
// Update the reverse deps
|
||||
Update(Pkg.RevDependsList());
|
||||
|
||||
// Update the provides map for the current ver
|
||||
if (Pkg->CurrentVer != 0)
|
||||
for (PrvIterator P = Pkg.CurrentVer().ProvidesList();
|
||||
P.end() != true; P++)
|
||||
Update(P.ParentPkg().RevDependsList());
|
||||
|
||||
// Update the provides map for the candidate ver
|
||||
if (PkgState[Pkg->ID].CandidateVer != 0)
|
||||
for (PrvIterator P = PkgState[Pkg->ID].CandidateVerIter(*this).ProvidesList();
|
||||
P.end() != true; P++)
|
||||
Update(P.ParentPkg().RevDependsList());
|
||||
}
|
||||
|
||||
/*}}}*/
|
||||
|
||||
// DepCache::MarkKeep - Put the package in the keep state /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
|
||||
{
|
||||
// Simplifies other routines.
|
||||
if (Pkg.end() == true)
|
||||
return;
|
||||
|
||||
/* Reject an attempt to keep a non-source broken installed package, those
|
||||
must be upgraded */
|
||||
if (Pkg.State() == PkgIterator::NeedsUnpack &&
|
||||
Pkg.CurrentVer().Downloadable() == false)
|
||||
return;
|
||||
|
||||
/* We changed the soft state all the time so the UI is a bit nicer
|
||||
to use */
|
||||
StateCache &P = PkgState[Pkg->ID];
|
||||
if (Soft == true)
|
||||
P.iFlags |= AutoKept;
|
||||
else
|
||||
P.iFlags &= ~AutoKept;
|
||||
|
||||
// Check that it is not already kept
|
||||
if (P.Mode == ModeKeep)
|
||||
return;
|
||||
|
||||
// We dont even try to keep virtual packages..
|
||||
if (Pkg->VersionList == 0)
|
||||
return;
|
||||
|
||||
P.Flags &= ~Flag::Auto;
|
||||
RemoveSizes(Pkg);
|
||||
RemoveStates(Pkg);
|
||||
|
||||
P.Mode = ModeKeep;
|
||||
if (Pkg->CurrentVer == 0)
|
||||
P.InstallVer = 0;
|
||||
else
|
||||
P.InstallVer = Pkg.CurrentVer();
|
||||
|
||||
AddStates(Pkg);
|
||||
|
||||
Update(Pkg);
|
||||
|
||||
AddSizes(Pkg);
|
||||
}
|
||||
/*}}}*/
|
||||
// DepCache::MarkDelete - Put the package in the delete state /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool fReplace, bool rPurge)
|
||||
{
|
||||
// Simplifies other routines.
|
||||
if (Pkg.end() == true)
|
||||
return;
|
||||
|
||||
// Check that it is not already marked for delete
|
||||
StateCache &P = PkgState[Pkg->ID];
|
||||
P.iFlags &= ~(AutoKept | Purge);
|
||||
if ( fReplace ) P.iFlags |= Replaced;
|
||||
if (rPurge == true)
|
||||
P.iFlags |= Purge;
|
||||
|
||||
if ((P.Mode == ModeDelete || P.InstallVer == 0) &&
|
||||
(Pkg.Purge() == true || rPurge == false))
|
||||
return;
|
||||
|
||||
// We dont even try to delete virtual packages..
|
||||
if (Pkg->VersionList == 0)
|
||||
return;
|
||||
|
||||
RemoveSizes(Pkg);
|
||||
RemoveStates(Pkg);
|
||||
|
||||
if (Pkg->CurrentVer == 0 && (Pkg.Purge() == true || rPurge == false))
|
||||
P.Mode = ModeKeep;
|
||||
else
|
||||
P.Mode = ModeDelete;
|
||||
P.InstallVer = 0;
|
||||
P.Flags &= Flag::Auto;
|
||||
|
||||
AddStates(Pkg);
|
||||
Update(Pkg);
|
||||
AddSizes(Pkg);
|
||||
}
|
||||
/*}}}*/
|
||||
#if 1
|
||||
// DepCache::MarkInstall - Put the package in the install state /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst)
|
||||
{
|
||||
// Simplifies other routines.
|
||||
if (Pkg.end() == true)
|
||||
return;
|
||||
|
||||
/* Check that it is not already marked for install and that it can be
|
||||
installed */
|
||||
StateCache &P = PkgState[Pkg->ID];
|
||||
P.iFlags &= ~AutoKept;
|
||||
if (P.InstBroken() == false && (P.Mode == ModeInstall ||
|
||||
P.CandidateVer == (Version *)Pkg.CurrentVer()))
|
||||
{
|
||||
if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
|
||||
MarkKeep(Pkg);
|
||||
return;
|
||||
}
|
||||
|
||||
// We dont even try to install virtual packages..
|
||||
if (Pkg->VersionList == 0)
|
||||
return;
|
||||
|
||||
/* Target the candidate version and remove the autoflag. We reset the
|
||||
autoflag below if this was called recursively. Otherwise the user
|
||||
should have the ability to de-auto a package by changing its state */
|
||||
RemoveSizes(Pkg);
|
||||
RemoveStates(Pkg);
|
||||
|
||||
P.Mode = ModeInstall;
|
||||
P.InstallVer = P.CandidateVer;
|
||||
P.Flags &= ~Flag::Auto;
|
||||
if (P.CandidateVer == (Version *)Pkg.CurrentVer())
|
||||
P.Mode = ModeKeep;
|
||||
|
||||
AddStates(Pkg);
|
||||
Update(Pkg);
|
||||
AddSizes(Pkg);
|
||||
|
||||
|
||||
if (AutoInst == false)
|
||||
return;
|
||||
|
||||
DepIterator Dep = P.InstVerIter(*this).DependsList();
|
||||
for (; Dep.end() != true;)
|
||||
{
|
||||
// Grok or groups
|
||||
DepIterator Start = Dep;
|
||||
bool Result = true;
|
||||
for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++)
|
||||
{
|
||||
LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
|
||||
|
||||
if ((DepState[Dep->ID] & DepInstall) == DepInstall)
|
||||
Result = false;
|
||||
}
|
||||
|
||||
// Dep is satisfied okay.
|
||||
if (Result == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if this dep should be consider for install. If it is a user
|
||||
defined important dep and we are installed a new package then
|
||||
it will be installed. Otherwise we only worry about critical deps */
|
||||
if (IsImportantDep(Start) == false)
|
||||
continue;
|
||||
if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
|
||||
continue;
|
||||
|
||||
// Now we have to take action...
|
||||
PkgIterator P = Start.SmartTargetPkg();
|
||||
if ((DepState[Start->ID] & DepCVer) == DepCVer)
|
||||
{
|
||||
MarkInstall(P,true);
|
||||
|
||||
// Set the autoflag, after MarkInstall because MarkInstall unsets it
|
||||
if (P->CurrentVer == 0)
|
||||
PkgState[P->ID].Flags |= Flag::Auto;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// For conflicts we just de-install the package and mark as auto
|
||||
if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
|
||||
{
|
||||
Version **List = Start.AllTargets();
|
||||
for (Version **I = List; *I != 0; I++)
|
||||
{
|
||||
VerIterator Ver(*this,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
MarkDelete(Pkg, Start->Type == Dep::Obsoletes);
|
||||
PkgState[Pkg->ID].Flags |= Flag::Auto;
|
||||
}
|
||||
delete [] List;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
#else
|
||||
// DepCache::MarkInstall - Put the package in the install state /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
|
||||
unsigned long Depth)
|
||||
{
|
||||
if (Depth > 100)
|
||||
return;
|
||||
|
||||
// Simplifies other routines.
|
||||
if (Pkg.end() == true)
|
||||
return;
|
||||
|
||||
/* Check that it is not already marked for install and that it can be
|
||||
installed */
|
||||
StateCache &P = PkgState[Pkg->ID];
|
||||
P.iFlags &= ~AutoKept;
|
||||
if (P.InstBroken() == false && (P.Mode == ModeInstall ||
|
||||
P.CandidateVer == (Version *)Pkg.CurrentVer()))
|
||||
{
|
||||
if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
|
||||
MarkKeep(Pkg);
|
||||
return;
|
||||
}
|
||||
|
||||
// See if there is even any possible instalation candidate
|
||||
if (P.CandidateVer == 0)
|
||||
return;
|
||||
|
||||
// We dont even try to install virtual packages..
|
||||
if (Pkg->VersionList == 0)
|
||||
return;
|
||||
|
||||
/* Target the candidate version and remove the autoflag. We reset the
|
||||
autoflag below if this was called recursively. Otherwise the user
|
||||
should have the ability to de-auto a package by changing its state */
|
||||
RemoveSizes(Pkg);
|
||||
RemoveStates(Pkg);
|
||||
|
||||
P.Mode = ModeInstall;
|
||||
P.InstallVer = P.CandidateVer;
|
||||
P.Flags &= ~Flag::Auto;
|
||||
if (P.CandidateVer == (Version *)Pkg.CurrentVer())
|
||||
P.Mode = ModeKeep;
|
||||
|
||||
AddStates(Pkg);
|
||||
Update(Pkg);
|
||||
AddSizes(Pkg);
|
||||
|
||||
if (AutoInst == false)
|
||||
return;
|
||||
|
||||
DepIterator Dep = P.InstVerIter(*this).DependsList();
|
||||
for (; Dep.end() != true;)
|
||||
{
|
||||
// Grok or groups
|
||||
DepIterator Start = Dep;
|
||||
bool Result = true;
|
||||
unsigned Ors = 0;
|
||||
for (bool LastOR = true; Dep.end() == false && LastOR == true; Dep++,Ors++)
|
||||
{
|
||||
LastOR = (Dep->CompareOp & Dep::Or) == Dep::Or;
|
||||
|
||||
if ((DepState[Dep->ID] & DepInstall) == DepInstall)
|
||||
Result = false;
|
||||
}
|
||||
|
||||
// Dep is satisfied okay.
|
||||
if (Result == false)
|
||||
continue;
|
||||
|
||||
/* Check if this dep should be consider for install. If it is a user
|
||||
defined important dep and we are installed a new package then
|
||||
it will be installed. Otherwise we only worry about critical deps */
|
||||
if (IsImportantDep(Start) == false)
|
||||
continue;
|
||||
if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
|
||||
continue;
|
||||
|
||||
/* If we are in an or group locate the first or that can
|
||||
succeed. We have already cached this.. */
|
||||
for (; Ors > 1 && (DepState[Start->ID] & DepCVer) != DepCVer; Ors--)
|
||||
Start++;
|
||||
|
||||
/* This bit is for processing the possibilty of an install/upgrade
|
||||
fixing the problem */
|
||||
SPtrArray<Version *> List = Start.AllTargets();
|
||||
if ((DepState[Start->ID] & DepCVer) == DepCVer)
|
||||
{
|
||||
// Right, find the best version to install..
|
||||
Version **Cur = List;
|
||||
PkgIterator P = Start.TargetPkg();
|
||||
PkgIterator InstPkg(*Cache,0);
|
||||
|
||||
// See if there are direct matches (at the start of the list)
|
||||
for (; *Cur != 0 && (*Cur)->ParentPkg == P.Index(); Cur++)
|
||||
{
|
||||
PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
|
||||
if (PkgState[Pkg->ID].CandidateVer != *Cur)
|
||||
continue;
|
||||
InstPkg = Pkg;
|
||||
break;
|
||||
}
|
||||
|
||||
// Select the highest priority providing package
|
||||
if (InstPkg.end() == false)
|
||||
{
|
||||
pkgPrioSortList(*Cache,Cur);
|
||||
for (; *Cur != 0; Cur++)
|
||||
{
|
||||
PkgIterator Pkg(*Cache,Cache->PkgP + (*Cur)->ParentPkg);
|
||||
if (PkgState[Pkg->ID].CandidateVer != *Cur)
|
||||
continue;
|
||||
InstPkg = Pkg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (InstPkg.end() == false)
|
||||
{
|
||||
MarkInstall(InstPkg,true,Depth + 1);
|
||||
|
||||
// Set the autoflag, after MarkInstall because MarkInstall unsets it
|
||||
if (P->CurrentVer == 0)
|
||||
PkgState[InstPkg->ID].Flags |= Flag::Auto;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For conflicts we just de-install the package and mark as auto,
|
||||
Conflicts may not have or groups */
|
||||
if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
|
||||
{
|
||||
for (Version **I = List; *I != 0; I++)
|
||||
{
|
||||
VerIterator Ver(*this,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
MarkDelete(Pkg, Start->Type == Dep::Obsoletes);
|
||||
PkgState[Pkg->ID].Flags |= Flag::Auto;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
#endif
|
||||
// DepCache::SetReInstall - Set the reinstallation flag /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
|
||||
{
|
||||
RemoveSizes(Pkg);
|
||||
RemoveStates(Pkg);
|
||||
|
||||
StateCache &P = PkgState[Pkg->ID];
|
||||
if (To == true)
|
||||
P.iFlags |= ReInstall;
|
||||
else
|
||||
P.iFlags &= ~ReInstall;
|
||||
|
||||
AddStates(Pkg);
|
||||
AddSizes(Pkg);
|
||||
}
|
||||
|
||||
// StateCache::Update - Compute the various static display things /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called whenever the Candidate version changes. */
|
||||
void pkgDepCache::StateCache::Update(PkgIterator Pkg,pkgCache &Cache)
|
||||
{
|
||||
// Some info
|
||||
VerIterator Ver = CandidateVerIter(Cache);
|
||||
|
||||
// Use a null string or the version string
|
||||
if (Ver.end() == true)
|
||||
CandVersion = "";
|
||||
else
|
||||
CandVersion = Ver.VerStr();
|
||||
|
||||
// Find the current version
|
||||
CurVersion = "";
|
||||
if (Pkg->CurrentVer != 0)
|
||||
CurVersion = Pkg.CurrentVer().VerStr();
|
||||
|
||||
// Strip off the epochs for display
|
||||
CurVersion = StripEpoch(CurVersion);
|
||||
CandVersion = StripEpoch(CandVersion);
|
||||
|
||||
// Figure out if its up or down or equal
|
||||
Status = Ver.CompareVer(Pkg.CurrentVer());
|
||||
|
||||
if (Pkg->CurrentVer == 0 || Pkg->VersionList == 0 || CandidateVer == 0) {
|
||||
Status = 2;
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// StateCache::StripEpoch - Remove the epoch specifier from the version /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
|
||||
{
|
||||
if (Ver == 0)
|
||||
return 0;
|
||||
|
||||
// Strip any epoch
|
||||
for (const char *I = Ver; *I != 0; I++)
|
||||
if (*I == ':')
|
||||
return I + 1;
|
||||
return Ver;
|
||||
}
|
||||
/*}}}*/
|
187
apt/apt-pkg/depcache.h
Normal file
187
apt/apt-pkg/depcache.h
Normal file
@ -0,0 +1,187 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: depcache.h,v 1.3 2001/11/13 17:32:07 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
DepCache - Dependency Extension data for the cache
|
||||
|
||||
This class stores the cache data and a set of extension structures for
|
||||
monitoring the current state of all the packages. It also generates and
|
||||
caches the 'install' state of many things. This refers to the state of the
|
||||
package after an install has been run.
|
||||
|
||||
The StateCache::State field can be -1,0,1,2 which is <,=,>,no current.
|
||||
StateCache::Mode is which of the 3 fields is active.
|
||||
|
||||
This structure is important to support the readonly status of the cache
|
||||
file. When the data is saved the cache will be refereshed from our
|
||||
internal rep and written to disk. Then the actual persistant data
|
||||
files will be put on the disk.
|
||||
|
||||
Each dependency is compared against 3 target versions to produce to
|
||||
3 dependency results.
|
||||
Now - Compared using the Currently install version
|
||||
Install - Compared using the install version (final state)
|
||||
CVer - (Candidate Verion) Compared using the Candidate Version
|
||||
The candidate and now results are used to decide wheather a package
|
||||
should be automatically installed or if it should be left alone.
|
||||
|
||||
Remember, the Candidate Version is selected based on the distribution
|
||||
settings for the Package. The Install Version is selected based on the
|
||||
state (Delete, Keep, Install) field and can be either the Current Version
|
||||
or the Candidate version.
|
||||
|
||||
The Candidate version is what is shown the 'Install Version' field.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_DEPCACHE_H
|
||||
#define PKGLIB_DEPCACHE_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/depcache.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/pkgcache.h>
|
||||
#include <apt-pkg/progress.h>
|
||||
|
||||
class pkgDepCache : public pkgCache
|
||||
{
|
||||
public:
|
||||
|
||||
// These flags are used in DepState
|
||||
enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
|
||||
DepGNow = (1 << 3),DepGInstall = (1 << 4),DepGCVer = (1 << 5)};
|
||||
|
||||
// These flags are used in StateCache::DepState
|
||||
enum DepStateFlags {DepNowPolicy = (1 << 0), DepNowMin = (1 << 1),
|
||||
DepInstPolicy = (1 << 2), DepInstMin = (1 << 3),
|
||||
DepCandPolicy = (1 << 4), DepCandMin = (1 << 5)};
|
||||
|
||||
// These flags are used in StateCache::iFlags
|
||||
enum InternalFlags {AutoKept = (1 << 0), Purge = (1 << 1), ReInstall = (1 << 2), Replaced = (1 << 3)};
|
||||
|
||||
enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
|
||||
enum ModeList {ModeDelete = 0, ModeKeep, ModeInstall};
|
||||
struct StateCache
|
||||
{
|
||||
// Epoch stripped text versions of the two version fields
|
||||
const char *CandVersion;
|
||||
const char *CurVersion;
|
||||
|
||||
// Pointer to the candidate install version.
|
||||
Version *CandidateVer;
|
||||
|
||||
// Pointer to the install version.
|
||||
Version *InstallVer;
|
||||
|
||||
// Various tree indicators
|
||||
signed char Status; // -1,0,1,2
|
||||
unsigned char Mode; // ModeList
|
||||
unsigned char DepState; // DepState Flags
|
||||
|
||||
// Copy of Package::Flags
|
||||
unsigned short Flags;
|
||||
unsigned short iFlags; // Internal flags
|
||||
|
||||
// Update of candidate version
|
||||
const char *StripEpoch(const char *Ver);
|
||||
void Update(PkgIterator Pkg,pkgCache &Cache);
|
||||
|
||||
// Various test members for the current status of the package
|
||||
inline bool NewInstall() const {return Status == 2 && Mode == ModeInstall;};
|
||||
inline bool Delete() const {return Mode == ModeDelete;};
|
||||
inline bool Replaced() const {return iFlags & pkgDepCache::Replaced;};
|
||||
inline bool Keep() const {return Mode == ModeKeep;};
|
||||
inline bool Upgrade() const {return Status > 0 && Mode == ModeInstall;};
|
||||
inline bool Upgradable() const {return Status >= 1;};
|
||||
inline bool Downgrade() const {return Status < 0;};
|
||||
inline bool Held() const {return Status != 0 && Keep();};
|
||||
inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
|
||||
inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
|
||||
inline bool Install() const {return Mode == ModeInstall;};
|
||||
inline VerIterator InstVerIter(pkgCache &Cache)
|
||||
{return VerIterator(Cache,InstallVer);};
|
||||
inline VerIterator CandidateVerIter(pkgCache &Cache)
|
||||
{return VerIterator(Cache,CandidateVer);};
|
||||
};
|
||||
|
||||
// Helper functions
|
||||
void BuildGroupOrs(VerIterator const &V);
|
||||
void UpdateVerState(PkgIterator Pkg);
|
||||
|
||||
bool Init(OpProgress *Prog);
|
||||
|
||||
protected:
|
||||
|
||||
// State information
|
||||
StateCache *PkgState;
|
||||
unsigned char *DepState;
|
||||
|
||||
signed long iUsrSize;
|
||||
unsigned long iDownloadSize;
|
||||
unsigned long iInstCount;
|
||||
unsigned long iDelCount;
|
||||
unsigned long iKeepCount;
|
||||
unsigned long iBrokenCount;
|
||||
unsigned long iBadCount;
|
||||
|
||||
// Check for a matching provides
|
||||
bool CheckDep(DepIterator Dep,int Type,PkgIterator &Res);
|
||||
inline bool CheckDep(DepIterator Dep,int Type)
|
||||
{
|
||||
PkgIterator Res(*this);
|
||||
return CheckDep(Dep,Type,Res);
|
||||
}
|
||||
|
||||
// Computes state information for deps and versions (w/o storing)
|
||||
unsigned char DependencyState(DepIterator &D);
|
||||
unsigned char VersionState(DepIterator D,unsigned char Check,
|
||||
unsigned char SetMin,
|
||||
unsigned char SetPolicy);
|
||||
|
||||
// Recalculates various portions of the cache, call after changing something
|
||||
void Update(DepIterator Dep); // Mostly internal
|
||||
void Update(PkgIterator const &P);
|
||||
|
||||
// Count manipulators
|
||||
void AddSizes(const PkgIterator &Pkg,long Mult = 1);
|
||||
inline void RemoveSizes(const PkgIterator &Pkg) {AddSizes(Pkg,-1);};
|
||||
void AddStates(const PkgIterator &Pkg,int Add = 1);
|
||||
inline void RemoveStates(const PkgIterator &Pkg) {AddStates(Pkg,-1);};
|
||||
|
||||
public:
|
||||
|
||||
// Policy implementation
|
||||
virtual VerIterator GetCandidateVer(PkgIterator Pkg,bool AllowCurrent = true);
|
||||
virtual bool IsImportantDep(DepIterator Dep);
|
||||
|
||||
// Accessors
|
||||
inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];};
|
||||
inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];};
|
||||
|
||||
// Manipulators
|
||||
void MarkKeep(PkgIterator const &Pkg,bool Soft = false);
|
||||
void MarkDelete(PkgIterator const &Pkg, bool fReplace = false, bool Purge = false);
|
||||
void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true);
|
||||
void SetReInstall(PkgIterator const &Pkg,bool To);
|
||||
|
||||
// This is for debuging
|
||||
void Update(OpProgress *Prog = 0);
|
||||
|
||||
// Size queries
|
||||
inline signed long UsrSize() {return iUsrSize;};
|
||||
inline unsigned long DebSize() {return iDownloadSize;};
|
||||
inline unsigned long DelCount() {return iDelCount;};
|
||||
inline unsigned long KeepCount() {return iKeepCount;};
|
||||
inline unsigned long InstCount() {return iInstCount;};
|
||||
inline unsigned long BrokenCount() {return iBrokenCount;};
|
||||
inline unsigned long BadCount() {return iBadCount;};
|
||||
|
||||
pkgDepCache(MMap &Map,OpProgress &Prog);
|
||||
pkgDepCache(MMap &Map);
|
||||
virtual ~pkgDepCache();
|
||||
};
|
||||
|
||||
#endif
|
94
apt/apt-pkg/init.cc
Normal file
94
apt/apt-pkg/init.cc
Normal file
@ -0,0 +1,94 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: init.cc,v 1.16 2001/08/01 21:35:12 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Init - Initialize the package library
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include files /*{{{*/
|
||||
#include <apt-pkg/init.h>
|
||||
#include <apt-pkg/fileutl.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <config.h>
|
||||
/*}}}*/
|
||||
|
||||
|
||||
// pkgInitialize - Initialize the configuration class /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Directories are specified in such a way that the FindDir function will
|
||||
understand them. That is, if they don't start with a / then their parent
|
||||
is prepended, this allows a fair degree of flexability. */
|
||||
bool pkgInitialize(Configuration &Cnf)
|
||||
{
|
||||
// General APT things
|
||||
Cnf.Set("APT::Architecture",COMMON_CPU);
|
||||
|
||||
// State
|
||||
Cnf.Set("Dir::State","/var/state/apt/");
|
||||
Cnf.Set("Dir::State::lists","lists/");
|
||||
|
||||
/* These really should be jammed into a generic 'Local Database' engine
|
||||
which is yet to be determined. The functions in pkgcachegen should
|
||||
be the only users of these */
|
||||
Cnf.Set("Dir::State::xstatus","xstatus");
|
||||
Cnf.Set("Dir::State::userstatus","status.user");
|
||||
if (0) {//akk
|
||||
Cnf.Set("Dir::State::status","/var/lib/dpkg/status");
|
||||
} else {
|
||||
Cnf.Set("Acquire::cdrom::mount", "/mnt/cdrom");
|
||||
Cnf.Set("RPM::AllowedDupPkgs::","^kernel$");
|
||||
Cnf.Set("RPM::AllowedDupPkgs::", "kernel-smp");
|
||||
Cnf.Set("RPM::AllowedDupPkgs::", "kernel-enterprise");
|
||||
|
||||
Cnf.Set("RPM::HoldPkgs::", "kernel-source");
|
||||
Cnf.Set("RPM::HoldPkgs::", "kernel-headers");
|
||||
|
||||
Cnf.Set("Dir::State::status","/var/lib/rpm/status");
|
||||
}
|
||||
Cnf.Set("Dir::State::cdroms","cdroms.list");
|
||||
|
||||
// Cache
|
||||
Cnf.Set("Dir::Cache","/var/cache/apt/");
|
||||
Cnf.Set("Dir::Cache::archives","archives/");
|
||||
Cnf.Set("Dir::Cache::srcpkgcache","srcpkgcache.bin");
|
||||
Cnf.Set("Dir::Cache::pkgcache","pkgcache.bin");
|
||||
|
||||
// Configuration
|
||||
Cnf.Set("Dir::Etc","/etc/apt/");
|
||||
Cnf.Set("Dir::Etc::sourcelist","sources.list");
|
||||
Cnf.Set("Dir::Etc::vendorlist","vendors.list");
|
||||
Cnf.Set("Dir::Etc::main","apt.conf");
|
||||
Cnf.Set("Dir::Bin::gpg","/usr/bin/gpg");
|
||||
Cnf.Set("Dir::Bin::methods","/usr/lib/apt/methods");
|
||||
if (0) {//akk
|
||||
Cnf.Set("Dir::Bin::dpkg","/usr/bin/dpkg");
|
||||
Cnf.Set("Acquire::ComprExtension", ".gz");
|
||||
} else {
|
||||
Cnf.Set("Dir::Etc::RpmPriorities", "rpmpriorities");
|
||||
Cnf.Set("Dir::bin::gzip","/usr/bin/bzip2");
|
||||
Cnf.Set("Dir::Bin::rpm","/bin/rpm");
|
||||
Cnf.Set("Acquire::ComprExtension", ".bz2");
|
||||
}
|
||||
|
||||
// Read the main config file
|
||||
string FName = Cnf.FindFile("Dir::Etc::main");
|
||||
bool Res = true;
|
||||
if (FileExists(FName) == true)
|
||||
Res &= ReadConfigFile(Cnf,FName);
|
||||
|
||||
// Read an alternate config file
|
||||
const char *Cfg = getenv("APT_CONFIG");
|
||||
if (Cfg != 0 && FileExists(Cfg) == true)
|
||||
Res &= ReadConfigFile(Cnf,Cfg);
|
||||
|
||||
if (Res == false)
|
||||
return false;
|
||||
|
||||
if (Cnf.FindB("Debug::pkgInitialize",false) == true)
|
||||
Cnf.Dump();
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
21
apt/apt-pkg/init.h
Normal file
21
apt/apt-pkg/init.h
Normal file
@ -0,0 +1,21 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: init.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Init - Initialize the package library
|
||||
|
||||
This function must be called to configure the config class before
|
||||
calling many APT library functions.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_INIT_H
|
||||
#define PKGLIB_INIT_H
|
||||
|
||||
#include <apt-pkg/configuration.h>
|
||||
|
||||
bool pkgInitialize(Configuration &Cnf);
|
||||
|
||||
#endif
|
61
apt/apt-pkg/makefile
Normal file
61
apt/apt-pkg/makefile
Normal file
@ -0,0 +1,61 @@
|
||||
# -*- make -*-
|
||||
BASE=..
|
||||
SUBDIR=apt-pkg
|
||||
|
||||
# Header location
|
||||
SUBDIRS = rpm deb contrib
|
||||
HEADER_TARGETDIRS = apt-pkg
|
||||
|
||||
# Bring in the default rules
|
||||
include ../buildlib/defaults.mak
|
||||
|
||||
# The library name
|
||||
LIBRARY=apt-pkg
|
||||
MAJOR=3.1
|
||||
MINOR=0
|
||||
SLIBS=$(PTHREADLIB)
|
||||
|
||||
# Source code for the contributed non-core things
|
||||
SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \
|
||||
contrib/configuration.cc contrib/progress.cc contrib/cmndline.cc \
|
||||
contrib/md5.cc contrib/cdromutl.cc contrib/crc-16.cc
|
||||
|
||||
# Source code for the main library
|
||||
SOURCE+= pkgcache.cc version.cc fileutl.cc pkgcachegen.cc depcache.cc \
|
||||
orderlist.cc tagfile.cc sourcelist.cc packagemanager.cc \
|
||||
pkgrecords.cc algorithms.cc acquire.cc acquire-item.cc \
|
||||
acquire-worker.cc acquire-method.cc init.cc clean.cc \
|
||||
srcrecords.cc cachefile.cc systemfactory.cc
|
||||
|
||||
# Source code for the debian specific components
|
||||
SOURCE+= deb/deblistparser.cc deb/debrecords.cc deb/dpkgpm.cc deb/dpkginit.cc \
|
||||
deb/debsrcrecords.cc \
|
||||
deb/debfactory.cc
|
||||
|
||||
# Source code for the rpm specific components
|
||||
SOURCE+= rpm/rpminit.cc rpm/rpmlistparser.cc rpm/rpmpm.cc\
|
||||
rpm/rpmrecords.cc rpm/rpmsrcrecords.cc
|
||||
|
||||
SOURCE+= rpm/rpmfactory.cc rpm/rpmversion.cc rpm/rpmpackagedata.cc
|
||||
|
||||
# Public apt-pkg header files
|
||||
HEADERS = algorithms.h depcache.h mmap.h pkgcachegen.h cacheiterators.h \
|
||||
error.h orderlist.h sourcelist.h configuration.h fileutl.h \
|
||||
packagemanager.h tagfile.h deblistparser.h init.h pkgcache.h \
|
||||
progress.h pkgrecords.h debrecords.h cmndline.h \
|
||||
acquire.h acquire-worker.h acquire-item.h acquire-method.h md5.h \
|
||||
dpkgpm.h dpkginit.h cdromutl.h strutl.h clean.h srcrecords.h \
|
||||
debsrcrecords.h cachefile.h crc-16.h systemfactory.h sptr.h
|
||||
|
||||
HEADERS+= rpmfactory.h debfactory.h
|
||||
|
||||
HEADERS+= rpminit.h rpmlistparser.h rpmpm.h rpmrecords.h rpmpackagedata.h\
|
||||
rpmsrcrecords.h
|
||||
|
||||
|
||||
HEADERS := $(addprefix apt-pkg/,$(HEADERS))
|
||||
|
||||
# Private header files
|
||||
HEADERS+= system.h i18n.h
|
||||
|
||||
include $(LIBRARY_H)
|
960
apt/apt-pkg/orderlist.cc
Normal file
960
apt/apt-pkg/orderlist.cc
Normal file
@ -0,0 +1,960 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: orderlist.cc,v 1.4 2000/10/26 21:15:21 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Order List - Represents and Manipulates an ordered list of packages.
|
||||
|
||||
A list of packages can be ordered by a number of conflicting criteria
|
||||
each given a specific priority. Each package also has a set of flags
|
||||
indicating some usefull things about it that are derived in the
|
||||
course of sorting. The pkgPackageManager class uses this class for
|
||||
all of it's installation ordering needs.
|
||||
|
||||
This is a modified version of Manoj's Routine B. It consists of four
|
||||
independent ordering algorithms that can be applied at for different
|
||||
points in the ordering. By appling progressivly fewer ordering
|
||||
operations it is possible to give each consideration it's own
|
||||
priority and create an order that satisfies the lowest applicable
|
||||
consideration.
|
||||
|
||||
The rules for unpacking ordering are:
|
||||
1) Unpacking ignores Depends: on all packages
|
||||
2) Unpacking requires Conflicts: on -ALL- packages to be satisfied
|
||||
3) Unpacking requires PreDepends: on this package only to be satisfied
|
||||
4) Removing requires that no packages depend on the package to be
|
||||
removed.
|
||||
|
||||
And the rule for configuration ordering is:
|
||||
1) Configuring requires that the Depends: of the package be satisfied
|
||||
Conflicts+PreDepends are ignored because unpacking says they are
|
||||
already correct [exageration, it does check but we need not be
|
||||
concerned]
|
||||
|
||||
And some features that are valuable for unpacking ordering.
|
||||
f1) Unpacking a new package should advoid breaking dependencies of
|
||||
configured packages
|
||||
f2) Removal should not require a force, corrolory of f1
|
||||
f3) Unpacking should order by depends rather than fall back to random
|
||||
ordering.
|
||||
|
||||
Each of the features can be enabled in the sorting routine at an
|
||||
arbitary priority to give quite abit of control over the final unpacking
|
||||
order.
|
||||
|
||||
The rules listed above may never be violated and are called Critical.
|
||||
When a critical rule is violated then a loop condition is recorded
|
||||
and will have to be delt with in the caller.
|
||||
|
||||
The ordering keeps two lists, the main list and the 'After List'. The
|
||||
purpose of the after list is to allow packages to be delayed. This is done
|
||||
by setting the after flag on the package. Any package which requires this
|
||||
package to be ordered before will inherit the after flag and so on. This
|
||||
is used for CD swap ordering where all packages on a second CD have the
|
||||
after flag set. This forces them and all their dependents to be ordered
|
||||
toward the end.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/orderlist.h"
|
||||
#endif
|
||||
#include <apt-pkg/orderlist.h>
|
||||
#include <apt-pkg/depcache.h>
|
||||
#include <apt-pkg/error.h>
|
||||
/*}}}*/
|
||||
|
||||
pkgOrderList *pkgOrderList::Me = 0;
|
||||
|
||||
// OrderList::pkgOrderList - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgOrderList::pkgOrderList(pkgDepCache &Cache) : Cache(Cache)
|
||||
{
|
||||
FileList = 0;
|
||||
Primary = 0;
|
||||
Secondary = 0;
|
||||
RevDepends = 0;
|
||||
Remove = 0;
|
||||
LoopCount = -1;
|
||||
|
||||
/* Construct the arrays, egcs 1.0.1 bug requires the package count
|
||||
hack */
|
||||
unsigned long Size = Cache.HeaderP->PackageCount;
|
||||
Flags = new unsigned short[Size];
|
||||
End = List = new Package *[Size];
|
||||
memset(Flags,0,sizeof(*Flags)*Size);
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::~pkgOrderList - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgOrderList::~pkgOrderList()
|
||||
{
|
||||
delete [] List;
|
||||
delete [] Flags;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::IsMissing - Check if a file is missing /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgOrderList::IsMissing(PkgIterator Pkg)
|
||||
{
|
||||
// Skip packages to erase
|
||||
if (Cache[Pkg].Delete() == true)
|
||||
return false;
|
||||
|
||||
// Skip Packages that need configure only.
|
||||
if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
|
||||
Cache[Pkg].Keep() == true)
|
||||
return false;
|
||||
|
||||
if (FileList != 0 && FileList[Pkg->ID].empty() == false)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// OrderList::DoRun - Does an order run /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The caller is expeted to have setup the desired probe state */
|
||||
bool pkgOrderList::DoRun()
|
||||
{
|
||||
// Temp list
|
||||
unsigned long Size = Cache.HeaderP->PackageCount;
|
||||
Package **NList = new Package *[Size];
|
||||
AfterList = new Package *[Size];
|
||||
AfterEnd = AfterList;
|
||||
|
||||
Depth = 0;
|
||||
WipeFlags(Added | AddPending | Loop | InList);
|
||||
|
||||
for (iterator I = List; I != End; I++)
|
||||
Flag(*I,InList);
|
||||
|
||||
// Rebuild the main list into the temp list.
|
||||
iterator OldEnd = End;
|
||||
End = NList;
|
||||
for (iterator I = List; I != OldEnd; I++)
|
||||
if (VisitNode(PkgIterator(Cache,*I)) == false)
|
||||
{
|
||||
End = OldEnd;
|
||||
delete [] NList;
|
||||
delete [] AfterList;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the after list to the end of the main list
|
||||
for (Package **I = AfterList; I != AfterEnd; I++)
|
||||
*End++ = *I;
|
||||
|
||||
// Swap the main list to the new list
|
||||
delete [] List;
|
||||
delete [] AfterList;
|
||||
List = NList;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::OrderCritical - Perform critical unpacking ordering /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This performs predepends and immediate configuration ordering only.
|
||||
This is termed critical unpacking ordering. Any loops that form are
|
||||
fatal and indicate that the packages cannot be installed. */
|
||||
bool pkgOrderList::OrderCritical()
|
||||
{
|
||||
FileList = 0;
|
||||
|
||||
Primary = &pkgOrderList::DepUnPackPre;
|
||||
Secondary = 0;
|
||||
RevDepends = 0;
|
||||
Remove = 0;
|
||||
LoopCount = 0;
|
||||
|
||||
// Sort
|
||||
Me = this;
|
||||
qsort(List,End - List,sizeof(*List),&OrderCompareB);
|
||||
|
||||
if (DoRun() == false)
|
||||
return false;
|
||||
|
||||
if (LoopCount != 0)
|
||||
return _error->Error("Fatal, predepends looping detected");
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::OrderUnpack - Perform complete unpacking ordering /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This performs complete unpacking ordering and creates an order that is
|
||||
suitable for unpacking */
|
||||
bool pkgOrderList::OrderUnpack(string *FileList)
|
||||
{
|
||||
this->FileList = FileList;
|
||||
|
||||
// Setup the after flags
|
||||
if (FileList != 0)
|
||||
{
|
||||
WipeFlags(After);
|
||||
|
||||
// Set the inlist flag
|
||||
for (iterator I = List; I != End; I++)
|
||||
{
|
||||
PkgIterator P(Cache,*I);
|
||||
if (IsMissing(P) == true && IsNow(P) == true)
|
||||
Flag(*I,After);
|
||||
}
|
||||
}
|
||||
|
||||
Primary = &pkgOrderList::DepUnPackCrit;
|
||||
Secondary = &pkgOrderList::DepConfigure;
|
||||
RevDepends = &pkgOrderList::DepUnPackDep;
|
||||
Remove = &pkgOrderList::DepRemove;
|
||||
LoopCount = -1;
|
||||
|
||||
// Sort
|
||||
Me = this;
|
||||
qsort(List,End - List,sizeof(*List),&OrderCompareA);
|
||||
|
||||
if (DoRun() == false)
|
||||
return false;
|
||||
|
||||
Secondary = 0;
|
||||
if (DoRun() == false)
|
||||
return false;
|
||||
|
||||
LoopCount = 0;
|
||||
RevDepends = 0;
|
||||
Remove = 0; // Otherwise the libreadline remove problem occures
|
||||
if (DoRun() == false)
|
||||
return false;
|
||||
|
||||
LoopCount = 0;
|
||||
Primary = &pkgOrderList::DepUnPackPre;
|
||||
if (DoRun() == false)
|
||||
return false;
|
||||
|
||||
/* cout << "----------END" << endl;
|
||||
|
||||
for (iterator I = List; I != End; I++)
|
||||
{
|
||||
PkgIterator P(Cache,*I);
|
||||
if (IsNow(P) == true)
|
||||
cout << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::OrderConfigure - Perform configuration ordering /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This orders by depends only and produces an order which is suitable
|
||||
for configuration */
|
||||
bool pkgOrderList::OrderConfigure()
|
||||
{
|
||||
FileList = 0;
|
||||
Primary = &pkgOrderList::DepConfigure;
|
||||
Secondary = 0;
|
||||
RevDepends = 0;
|
||||
Remove = 0;
|
||||
LoopCount = -1;
|
||||
return DoRun();
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// OrderList::Score - Score the package for sorting /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Higher scores order earlier */
|
||||
int pkgOrderList::Score(PkgIterator Pkg)
|
||||
{
|
||||
// Removal is always done first
|
||||
if (Cache[Pkg].Delete() == true)
|
||||
return 200;
|
||||
|
||||
// This should never happen..
|
||||
if (Cache[Pkg].InstVerIter(Cache).end() == true)
|
||||
return -1;
|
||||
|
||||
int Score = 0;
|
||||
if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
|
||||
Score += 100;
|
||||
|
||||
if (IsFlag(Pkg,Immediate) == true)
|
||||
Score += 10;
|
||||
|
||||
for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
|
||||
D.end() == false; D++)
|
||||
if (D->Type == pkgCache::Dep::PreDepends)
|
||||
{
|
||||
Score += 50;
|
||||
break;
|
||||
}
|
||||
|
||||
// Important Required Standard Optional Extra
|
||||
signed short PrioMap[] = {0,5,4,3,1,0};
|
||||
if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5)
|
||||
Score += PrioMap[Cache[Pkg].InstVerIter(Cache)->Priority];
|
||||
return Score;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::FileCmp - Compare by package file /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This compares by the package file that the install version is in. */
|
||||
int pkgOrderList::FileCmp(PkgIterator A,PkgIterator B)
|
||||
{
|
||||
if (Cache[A].Delete() == true && Cache[B].Delete() == true)
|
||||
return 0;
|
||||
if (Cache[A].Delete() == true)
|
||||
return -1;
|
||||
if (Cache[B].Delete() == true)
|
||||
return 1;
|
||||
|
||||
if (Cache[A].InstVerIter(Cache).FileList().end() == true)
|
||||
return -1;
|
||||
if (Cache[B].InstVerIter(Cache).FileList().end() == true)
|
||||
return 1;
|
||||
|
||||
pkgCache::PackageFile *FA = Cache[A].InstVerIter(Cache).FileList().File();
|
||||
pkgCache::PackageFile *FB = Cache[B].InstVerIter(Cache).FileList().File();
|
||||
if (FA < FB)
|
||||
return -1;
|
||||
if (FA > FB)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// BoolCompare - Comparison function for two booleans /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
static int BoolCompare(bool A,bool B)
|
||||
{
|
||||
if (A == B)
|
||||
return 0;
|
||||
if (A == false)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::OrderCompareA - Order the installation by op /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This provides a first-pass sort of the list and gives a decent starting
|
||||
point for further complete ordering. It is used by OrderUnpack only */
|
||||
int pkgOrderList::OrderCompareA(const void *a, const void *b)
|
||||
{
|
||||
PkgIterator A(Me->Cache,*(Package **)a);
|
||||
PkgIterator B(Me->Cache,*(Package **)b);
|
||||
|
||||
// We order packages with a set state toward the front
|
||||
int Res;
|
||||
if ((Res = BoolCompare(Me->IsNow(A),Me->IsNow(B))) != 0)
|
||||
return -1*Res;
|
||||
|
||||
// We order missing files to toward the end
|
||||
/* if (Me->FileList != 0)
|
||||
{
|
||||
if ((Res = BoolCompare(Me->IsMissing(A),
|
||||
Me->IsMissing(B))) != 0)
|
||||
return Res;
|
||||
}*/
|
||||
|
||||
if (A.State() != pkgCache::PkgIterator::NeedsNothing &&
|
||||
B.State() == pkgCache::PkgIterator::NeedsNothing)
|
||||
return -1;
|
||||
|
||||
if (A.State() == pkgCache::PkgIterator::NeedsNothing &&
|
||||
B.State() != pkgCache::PkgIterator::NeedsNothing)
|
||||
return 1;
|
||||
|
||||
int ScoreA = Me->Score(A);
|
||||
int ScoreB = Me->Score(B);
|
||||
if (ScoreA > ScoreB)
|
||||
return -1;
|
||||
|
||||
if (ScoreA < ScoreB)
|
||||
return 1;
|
||||
|
||||
return strcmp(A.Name(),B.Name());
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::OrderCompareB - Order the installation by source /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This orders by installation source. This is usefull to handle
|
||||
inter-source breaks */
|
||||
int pkgOrderList::OrderCompareB(const void *a, const void *b)
|
||||
{
|
||||
PkgIterator A(Me->Cache,*(Package **)a);
|
||||
PkgIterator B(Me->Cache,*(Package **)b);
|
||||
|
||||
if (A.State() != pkgCache::PkgIterator::NeedsNothing &&
|
||||
B.State() == pkgCache::PkgIterator::NeedsNothing)
|
||||
return -1;
|
||||
|
||||
if (A.State() == pkgCache::PkgIterator::NeedsNothing &&
|
||||
B.State() != pkgCache::PkgIterator::NeedsNothing)
|
||||
return 1;
|
||||
|
||||
int F = Me->FileCmp(A,B);
|
||||
if (F != 0)
|
||||
{
|
||||
if (F > 0)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ScoreA = Me->Score(A);
|
||||
int ScoreB = Me->Score(B);
|
||||
if (ScoreA > ScoreB)
|
||||
return -1;
|
||||
|
||||
if (ScoreA < ScoreB)
|
||||
return 1;
|
||||
|
||||
return strcmp(A.Name(),B.Name());
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// OrderList::VisitDeps - Visit forward install dependencies /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This calls the dependency function for the normal forwards dependencies
|
||||
of the package */
|
||||
bool pkgOrderList::VisitDeps(DepFunc F,PkgIterator Pkg)
|
||||
{
|
||||
if (F == 0 || Pkg.end() == true || Cache[Pkg].InstallVer == 0)
|
||||
return true;
|
||||
|
||||
return (this->*F)(Cache[Pkg].InstVerIter(Cache).DependsList());
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::VisitRDeps - Visit reverse dependencies /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This calls the dependency function for all of the normal reverse depends
|
||||
of the package */
|
||||
bool pkgOrderList::VisitRDeps(DepFunc F,PkgIterator Pkg)
|
||||
{
|
||||
if (F == 0 || Pkg.end() == true)
|
||||
return true;
|
||||
|
||||
return (this->*F)(Pkg.RevDependsList());
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::VisitRProvides - Visit provides reverse dependencies /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This calls the dependency function for all reverse dependencies
|
||||
generated by the provides line on the package. */
|
||||
bool pkgOrderList::VisitRProvides(DepFunc F,VerIterator Ver)
|
||||
{
|
||||
if (F == 0 || Ver.end() == true)
|
||||
return true;
|
||||
|
||||
bool Res = true;
|
||||
for (PrvIterator P = Ver.ProvidesList(); P.end() == false; P++)
|
||||
Res &= (this->*F)(P.ParentPkg().RevDependsList());
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::VisitProvides - Visit all of the providing packages /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This routine calls visit on all providing packages. */
|
||||
bool pkgOrderList::VisitProvides(DepIterator D,bool Critical)
|
||||
{
|
||||
Version **List = D.AllTargets();
|
||||
for (Version **I = List; *I != 0; I++)
|
||||
{
|
||||
VerIterator Ver(Cache,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
if (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)
|
||||
continue;
|
||||
|
||||
if (D->Type != pkgCache::Dep::Conflicts && D->Type != pkgCache::Dep::Obsoletes
|
||||
&& Cache[Pkg].InstallVer != *I)
|
||||
continue;
|
||||
|
||||
if ((D->Type == pkgCache::Dep::Conflicts || D->Type == pkgCache::Dep::Obsoletes)
|
||||
&& (Version *)Pkg.CurrentVer() != *I)
|
||||
continue;
|
||||
|
||||
// Skip over missing files
|
||||
if (Critical == false && IsMissing(D.ParentPkg()) == true)
|
||||
continue;
|
||||
|
||||
if (VisitNode(Pkg) == false)
|
||||
{
|
||||
delete [] List;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
delete [] List;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::VisitNode - Recursive ordering director /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is the core ordering routine. It calls the set dependency
|
||||
consideration functions which then potentialy call this again. Finite
|
||||
depth is achived through the colouring mechinism. */
|
||||
bool pkgOrderList::VisitNode(PkgIterator Pkg)
|
||||
{
|
||||
// Looping or irrelevent.
|
||||
// This should probably trancend not installed packages
|
||||
if (Pkg.end() == true || IsFlag(Pkg,Added) == true ||
|
||||
IsFlag(Pkg,AddPending) == true || IsFlag(Pkg,InList) == false)
|
||||
return true;
|
||||
|
||||
/* for (int j = 0; j != Depth; j++) cout << ' ';
|
||||
cout << "Visit " << Pkg.Name() << endl;*/
|
||||
Depth++;
|
||||
|
||||
// Color grey
|
||||
Flag(Pkg,AddPending);
|
||||
|
||||
DepFunc Old = Primary;
|
||||
|
||||
// Perform immedate configuration of the package if so flagged.
|
||||
if (IsFlag(Pkg,Immediate) == true && Primary != &pkgOrderList::DepUnPackPre)
|
||||
Primary = &pkgOrderList::DepUnPackPreD;
|
||||
|
||||
if (IsNow(Pkg) == true)
|
||||
{
|
||||
bool Res = true;
|
||||
if (Cache[Pkg].Delete() == false)
|
||||
{
|
||||
// Primary
|
||||
Res &= Res && VisitDeps(Primary,Pkg);
|
||||
Res &= Res && VisitRDeps(Primary,Pkg);
|
||||
Res &= Res && VisitRProvides(Primary,Pkg.CurrentVer());
|
||||
Res &= Res && VisitRProvides(Primary,Cache[Pkg].InstVerIter(Cache));
|
||||
|
||||
// RevDep
|
||||
Res &= Res && VisitRDeps(RevDepends,Pkg);
|
||||
Res &= Res && VisitRProvides(RevDepends,Pkg.CurrentVer());
|
||||
Res &= Res && VisitRProvides(RevDepends,Cache[Pkg].InstVerIter(Cache));
|
||||
|
||||
// Secondary
|
||||
Res &= Res && VisitDeps(Secondary,Pkg);
|
||||
Res &= Res && VisitRDeps(Secondary,Pkg);
|
||||
Res &= Res && VisitRProvides(Secondary,Pkg.CurrentVer());
|
||||
Res &= Res && VisitRProvides(Secondary,Cache[Pkg].InstVerIter(Cache));
|
||||
}
|
||||
else
|
||||
{
|
||||
// RevDep
|
||||
Res &= Res && VisitRDeps(Remove,Pkg);
|
||||
Res &= Res && VisitRProvides(Remove,Pkg.CurrentVer());
|
||||
}
|
||||
}
|
||||
|
||||
if (IsFlag(Pkg,Added) == false)
|
||||
{
|
||||
Flag(Pkg,Added,Added | AddPending);
|
||||
if (IsFlag(Pkg,After) == true)
|
||||
*AfterEnd++ = Pkg;
|
||||
else
|
||||
*End++ = Pkg;
|
||||
}
|
||||
|
||||
Primary = Old;
|
||||
Depth--;
|
||||
|
||||
/* for (int j = 0; j != Depth; j++) cout << ' ';
|
||||
cout << "Leave " << Pkg.Name() << ' ' << IsFlag(Pkg,Added) << ',' << IsFlag(Pkg,AddPending) << endl;*/
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// OrderList::DepUnPackCrit - Critical UnPacking ordering /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Critical unpacking ordering strives to satisfy Conflicts: and
|
||||
PreDepends: only. When a prdepends is encountered the Primary
|
||||
DepFunc is changed to be DepUnPackPreD.
|
||||
|
||||
Loops are preprocessed and logged. */
|
||||
bool pkgOrderList::DepUnPackCrit(DepIterator D)
|
||||
{
|
||||
for (; D.end() == false; D++)
|
||||
{
|
||||
if (D.Reverse() == true)
|
||||
{
|
||||
/* Reverse depenanices are only interested in conflicts,
|
||||
predepend breakage is ignored here */
|
||||
if (D->Type != pkgCache::Dep::Conflicts && D->Type != pkgCache::Dep::Obsoletes)
|
||||
continue;
|
||||
|
||||
// Duplication elimination, consider only the current version
|
||||
if (D.ParentPkg().CurrentVer() != D.ParentVer())
|
||||
continue;
|
||||
|
||||
/* For reverse dependencies we wish to check if the
|
||||
dependency is satisifed in the install state. The
|
||||
target package (caller) is going to be in the installed
|
||||
state. */
|
||||
if (CheckDep(D) == true)
|
||||
continue;
|
||||
|
||||
if (VisitNode(D.ParentPkg()) == false)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Forward critical dependencies MUST be correct before the
|
||||
package can be unpacked. */
|
||||
if (D->Type != pkgCache::Dep::Conflicts && D->Type != pkgCache::Dep::Obsoletes &&
|
||||
D->Type != pkgCache::Dep::PreDepends)
|
||||
continue;
|
||||
|
||||
/* We wish to check if the dep is okay in the now state of the
|
||||
target package against the install state of this package. */
|
||||
if (CheckDep(D) == true)
|
||||
{
|
||||
/* We want to catch predepends loops with the code below.
|
||||
Conflicts loops that are Dep OK are ignored */
|
||||
if (IsFlag(D.TargetPkg(),AddPending) == false ||
|
||||
D->Type != pkgCache::Dep::PreDepends)
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is the loop detection
|
||||
if (IsFlag(D.TargetPkg(),Added) == true ||
|
||||
IsFlag(D.TargetPkg(),AddPending) == true)
|
||||
{
|
||||
if (IsFlag(D.TargetPkg(),AddPending) == true)
|
||||
AddLoop(D);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Predepends require a special ordering stage, they must have
|
||||
all dependents installed as well */
|
||||
DepFunc Old = Primary;
|
||||
bool Res = false;
|
||||
if (D->Type == pkgCache::Dep::PreDepends)
|
||||
Primary = &pkgOrderList::DepUnPackPreD;
|
||||
Res = VisitProvides(D,true);
|
||||
Primary = Old;
|
||||
if (Res == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::DepUnPackPreD - Critical UnPacking ordering with depends /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Critical PreDepends (also configure immediate and essential) strives to
|
||||
ensure not only that all conflicts+predepends are met but that this
|
||||
package will be immediately configurable when it is unpacked.
|
||||
|
||||
Loops are preprocessed and logged. */
|
||||
bool pkgOrderList::DepUnPackPreD(DepIterator D)
|
||||
{
|
||||
if (D.Reverse() == true)
|
||||
return DepUnPackCrit(D);
|
||||
|
||||
for (; D.end() == false; D++)
|
||||
{
|
||||
if (D.IsCritical() == false)
|
||||
continue;
|
||||
|
||||
/* We wish to check if the dep is okay in the now state of the
|
||||
target package against the install state of this package. */
|
||||
if (CheckDep(D) == true)
|
||||
{
|
||||
/* We want to catch predepends loops with the code below.
|
||||
Conflicts loops that are Dep OK are ignored */
|
||||
if (IsFlag(D.TargetPkg(),AddPending) == false ||
|
||||
D->Type != pkgCache::Dep::PreDepends)
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is the loop detection
|
||||
if (IsFlag(D.TargetPkg(),Added) == true ||
|
||||
IsFlag(D.TargetPkg(),AddPending) == true)
|
||||
{
|
||||
if (IsFlag(D.TargetPkg(),AddPending) == true)
|
||||
AddLoop(D);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (VisitProvides(D,true) == false)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::DepUnPackPre - Critical Predepends ordering /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Critical PreDepends (also configure immediate and essential) strives to
|
||||
ensure not only that all conflicts+predepends are met but that this
|
||||
package will be immediately configurable when it is unpacked.
|
||||
|
||||
Loops are preprocessed and logged. All loops will be fatal. */
|
||||
bool pkgOrderList::DepUnPackPre(DepIterator D)
|
||||
{
|
||||
if (D.Reverse() == true)
|
||||
return true;
|
||||
|
||||
for (; D.end() == false; D++)
|
||||
{
|
||||
/* Only consider the PreDepends or Depends. Depends are only
|
||||
considered at the lowest depth or in the case of immediate
|
||||
configure */
|
||||
if (D->Type != pkgCache::Dep::PreDepends)
|
||||
{
|
||||
if (D->Type == pkgCache::Dep::Depends)
|
||||
{
|
||||
if (Depth == 1 && IsFlag(D.ParentPkg(),Immediate) == false)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We wish to check if the dep is okay in the now state of the
|
||||
target package against the install state of this package. */
|
||||
if (CheckDep(D) == true)
|
||||
{
|
||||
/* We want to catch predepends loops with the code below.
|
||||
Conflicts loops that are Dep OK are ignored */
|
||||
if (IsFlag(D.TargetPkg(),AddPending) == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is the loop detection
|
||||
if (IsFlag(D.TargetPkg(),Added) == true ||
|
||||
IsFlag(D.TargetPkg(),AddPending) == true)
|
||||
{
|
||||
if (IsFlag(D.TargetPkg(),AddPending) == true)
|
||||
AddLoop(D);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (VisitProvides(D,true) == false)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::DepUnPackDep - Reverse dependency considerations /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Reverse dependencies are considered to determine if unpacking this
|
||||
package will break any existing dependencies. If so then those
|
||||
packages are ordered before this one so that they are in the
|
||||
UnPacked state.
|
||||
|
||||
The forwards depends loop is designed to bring the packages dependents
|
||||
close to the package. This helps reduce deconfigure time.
|
||||
|
||||
Loops are irrelevent to this. */
|
||||
bool pkgOrderList::DepUnPackDep(DepIterator D)
|
||||
{
|
||||
|
||||
for (; D.end() == false; D++)
|
||||
if (D.IsCritical() == true)
|
||||
{
|
||||
if (D.Reverse() == true)
|
||||
{
|
||||
/* Duplication prevention. We consider rev deps only on
|
||||
the current version, a not installed package
|
||||
cannot break */
|
||||
if (D.ParentPkg()->CurrentVer == 0 ||
|
||||
D.ParentPkg().CurrentVer() != D.ParentVer())
|
||||
continue;
|
||||
|
||||
// The dep will not break so it is irrelevent.
|
||||
if (CheckDep(D) == true)
|
||||
continue;
|
||||
|
||||
// Skip over missing files
|
||||
if (IsMissing(D.ParentPkg()) == true)
|
||||
continue;
|
||||
|
||||
if (VisitNode(D.ParentPkg()) == false)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (D->Type == pkgCache::Dep::Depends)
|
||||
if (VisitProvides(D,false) == false)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::DepConfigure - Configuration ordering /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Configuration only ordering orders by the Depends: line only. It
|
||||
orders configuration so that when a package comes to be configured it's
|
||||
dependents are configured.
|
||||
|
||||
Loops are ingored. Depends loop entry points are chaotic. */
|
||||
bool pkgOrderList::DepConfigure(DepIterator D)
|
||||
{
|
||||
// Never consider reverse configuration dependencies.
|
||||
if (D.Reverse() == true)
|
||||
return true;
|
||||
|
||||
for (; D.end() == false; D++)
|
||||
if (D->Type == pkgCache::Dep::Depends)
|
||||
if (VisitProvides(D,false) == false)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::DepRemove - Removal ordering /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* Removal visits all reverse depends. It considers if the dependency
|
||||
of the Now state version to see if it is okay with removing this
|
||||
package. This check should always fail, but is provided for symetery
|
||||
with the other critical handlers.
|
||||
|
||||
Loops are preprocessed and logged. Removal loops can also be
|
||||
detected in the critical handler. They are characterized by an
|
||||
old version of A depending on B but the new version of A conflicting
|
||||
with B, thus either A or B must break to install. */
|
||||
bool pkgOrderList::DepRemove(DepIterator D)
|
||||
{
|
||||
if (D.Reverse() == false)
|
||||
return true;
|
||||
for (; D.end() == false; D++)
|
||||
if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
|
||||
{
|
||||
// Duplication elimination, consider the current version only
|
||||
if (D.ParentPkg().CurrentVer() != D.ParentVer())
|
||||
continue;
|
||||
|
||||
/* We wish to see if the dep on the parent package is okay
|
||||
in the removed (install) state of the target pkg. */
|
||||
if (CheckDep(D) == true)
|
||||
{
|
||||
// We want to catch loops with the code below.
|
||||
if (IsFlag(D.ParentPkg(),AddPending) == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
// This is the loop detection
|
||||
if (IsFlag(D.ParentPkg(),Added) == true ||
|
||||
IsFlag(D.ParentPkg(),AddPending) == true)
|
||||
{
|
||||
if (IsFlag(D.ParentPkg(),AddPending) == true)
|
||||
AddLoop(D);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip over missing files
|
||||
if (IsMissing(D.ParentPkg()) == true)
|
||||
continue;
|
||||
|
||||
if (VisitNode(D.ParentPkg()) == false)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// OrderList::AddLoop - Add a loop to the loop list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We record the loops. This is a relic since loop breaking is done
|
||||
genericaly as part of the safety routines. */
|
||||
bool pkgOrderList::AddLoop(DepIterator D)
|
||||
{
|
||||
if (LoopCount < 0 || LoopCount >= 20)
|
||||
return false;
|
||||
|
||||
// Skip dups
|
||||
if (LoopCount != 0)
|
||||
{
|
||||
if (Loops[LoopCount - 1].ParentPkg() == D.ParentPkg() ||
|
||||
Loops[LoopCount - 1].TargetPkg() == D.ParentPkg())
|
||||
return true;
|
||||
}
|
||||
|
||||
Loops[LoopCount++] = D;
|
||||
|
||||
// Mark the packages as being part of a loop.
|
||||
Flag(D.TargetPkg(),Loop);
|
||||
Flag(D.ParentPkg(),Loop);
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::WipeFlags - Unset the given flags from all packages /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
void pkgOrderList::WipeFlags(unsigned long F)
|
||||
{
|
||||
unsigned long Size = Cache.HeaderP->PackageCount;
|
||||
for (unsigned long I = 0; I != Size; I++)
|
||||
Flags[I] &= ~F;
|
||||
}
|
||||
/*}}}*/
|
||||
// OrderList::CheckDep - Check a dependency for truth /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This performs a complete analysis of the dependency wrt to the
|
||||
current add list. It returns true if after all events are
|
||||
performed it is still true. This sort of routine can be approximated
|
||||
by examining the DepCache, however in convoluted cases of provides
|
||||
this fails to produce a suitable result. */
|
||||
bool pkgOrderList::CheckDep(DepIterator D)
|
||||
{
|
||||
Version **List = D.AllTargets();
|
||||
bool Hit = false;
|
||||
for (Version **I = List; *I != 0; I++)
|
||||
{
|
||||
VerIterator Ver(Cache,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
/* The meaning of Added and AddPending is subtle. AddPending is
|
||||
an indication that the package is looping. Because of the
|
||||
way ordering works Added means the package will be unpacked
|
||||
before this one and AddPending means after. It is therefore
|
||||
correct to ignore AddPending in all cases, but that exposes
|
||||
reverse-ordering loops which should be ignored. */
|
||||
if (IsFlag(Pkg,Added) == true ||
|
||||
(IsFlag(Pkg,AddPending) == true && D.Reverse() == true))
|
||||
{
|
||||
if (Cache[Pkg].InstallVer != *I)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if ((Version *)Pkg.CurrentVer() != *I ||
|
||||
Pkg.State() != PkgIterator::NeedsNothing)
|
||||
continue;
|
||||
|
||||
/* Conflicts requires that all versions are not present, depends
|
||||
just needs one */
|
||||
if (D->Type != pkgCache::Dep::Conflicts && D->Type != pkgCache::Dep::Obsoletes)
|
||||
{
|
||||
/* Try to find something that does not have the after flag set
|
||||
if at all possible */
|
||||
if (IsFlag(Pkg,After) == true)
|
||||
{
|
||||
Hit = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
delete [] List;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsFlag(Pkg,After) == true)
|
||||
Flag(D.ParentPkg(),After);
|
||||
|
||||
delete [] List;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
delete [] List;
|
||||
|
||||
// We found a hit, but it had the after flag set
|
||||
if (Hit == true && D->Type == pkgCache::Dep::PreDepends)
|
||||
{
|
||||
Flag(D.ParentPkg(),After);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Conflicts requires that all versions are not present, depends
|
||||
just needs one */
|
||||
if (D->Type == pkgCache::Dep::Conflicts || D->Type == pkgCache::Dep::Obsoletes)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
129
apt/apt-pkg/orderlist.h
Normal file
129
apt/apt-pkg/orderlist.h
Normal file
@ -0,0 +1,129 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: orderlist.h,v 1.1.1.1 2000/08/10 12:42:39 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Order List - Represents and Manipulates an ordered list of packages.
|
||||
|
||||
A list of packages can be ordered by a number of conflicting criteria
|
||||
each given a specific priority. Each package also has a set of flags
|
||||
indicating some usefull things about it that are derived in the
|
||||
course of sorting. The pkgPackageManager class uses this class for
|
||||
all of it's installation ordering needs.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_ORDERLIST_H
|
||||
#define PKGLIB_ORDERLIST_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/orderlist.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/pkgcache.h>
|
||||
|
||||
class pkgDepCache;
|
||||
class pkgOrderList
|
||||
{
|
||||
protected:
|
||||
|
||||
pkgDepCache &Cache;
|
||||
|
||||
// Bring some usefull types into the local scope
|
||||
typedef pkgCache::PkgIterator PkgIterator;
|
||||
typedef pkgCache::VerIterator VerIterator;
|
||||
typedef pkgCache::DepIterator DepIterator;
|
||||
typedef pkgCache::PrvIterator PrvIterator;
|
||||
typedef pkgCache::Package Package;
|
||||
typedef pkgCache::Version Version;
|
||||
typedef bool (pkgOrderList::*DepFunc)(DepIterator D);
|
||||
|
||||
// These are the currently selected ordering functions
|
||||
DepFunc Primary;
|
||||
DepFunc Secondary;
|
||||
DepFunc RevDepends;
|
||||
DepFunc Remove;
|
||||
|
||||
// State
|
||||
Package **End;
|
||||
Package **List;
|
||||
Package **AfterList;
|
||||
Package **AfterEnd;
|
||||
string *FileList;
|
||||
DepIterator Loops[20];
|
||||
int LoopCount;
|
||||
int Depth;
|
||||
unsigned short *Flags;
|
||||
|
||||
// Main visit function
|
||||
bool VisitNode(PkgIterator Pkg);
|
||||
bool VisitDeps(DepFunc F,PkgIterator Pkg);
|
||||
bool VisitRDeps(DepFunc F,PkgIterator Pkg);
|
||||
bool VisitRProvides(DepFunc F,VerIterator Ver);
|
||||
bool VisitProvides(DepIterator Pkg,bool Critical);
|
||||
|
||||
// Dependency checking functions.
|
||||
bool DepUnPackCrit(DepIterator D);
|
||||
bool DepUnPackPreD(DepIterator D);
|
||||
bool DepUnPackPre(DepIterator D);
|
||||
bool DepUnPackDep(DepIterator D);
|
||||
bool DepConfigure(DepIterator D);
|
||||
bool DepRemove(DepIterator D);
|
||||
|
||||
// Analysis helpers
|
||||
bool AddLoop(DepIterator D);
|
||||
bool CheckDep(DepIterator D);
|
||||
bool DoRun();
|
||||
|
||||
// For pre sorting
|
||||
static pkgOrderList *Me;
|
||||
static int OrderCompareA(const void *a, const void *b);
|
||||
static int OrderCompareB(const void *a, const void *b);
|
||||
int FileCmp(PkgIterator A,PkgIterator B);
|
||||
|
||||
public:
|
||||
|
||||
typedef Package **iterator;
|
||||
|
||||
// State flags
|
||||
enum Flags {Added = (1 << 0), AddPending = (1 << 1),
|
||||
Immediate = (1 << 2), Loop = (1 << 3),
|
||||
UnPacked = (1 << 4), Configured = (1 << 5),
|
||||
Removed = (1 << 6), // Early Remove
|
||||
InList = (1 << 7),
|
||||
After = (1 << 8),
|
||||
States = (UnPacked | Configured | Removed)};
|
||||
|
||||
// Flag manipulators
|
||||
inline bool IsFlag(PkgIterator Pkg,unsigned long F) {return (Flags[Pkg->ID] & F) == F;};
|
||||
inline bool IsFlag(Package *Pkg,unsigned long F) {return (Flags[Pkg->ID] & F) == F;};
|
||||
void Flag(PkgIterator Pkg,unsigned long State, unsigned long F) {Flags[Pkg->ID] = (Flags[Pkg->ID] & (~F)) | State;};
|
||||
inline void Flag(PkgIterator Pkg,unsigned long F) {Flags[Pkg->ID] |= F;};
|
||||
inline void Flag(Package *Pkg,unsigned long F) {Flags[Pkg->ID] |= F;};
|
||||
inline bool IsNow(PkgIterator Pkg) {return (Flags[Pkg->ID] & (States & (~Removed))) == 0;};
|
||||
bool IsMissing(PkgIterator Pkg);
|
||||
void WipeFlags(unsigned long F);
|
||||
void SetFileList(string *FileList) {this->FileList = FileList;};
|
||||
|
||||
// Accessors
|
||||
inline iterator begin() {return List;};
|
||||
inline iterator end() {return End;};
|
||||
inline void push_back(Package *Pkg) {*(End++) = Pkg;};
|
||||
inline void push_back(PkgIterator Pkg) {*(End++) = Pkg;};
|
||||
inline void pop_back() {End--;};
|
||||
inline bool empty() {return End == List;};
|
||||
inline unsigned int size() {return End - List;};
|
||||
|
||||
// Ordering modes
|
||||
bool OrderCritical();
|
||||
bool OrderUnpack(string *FileList = 0);
|
||||
bool OrderConfigure();
|
||||
|
||||
int Score(PkgIterator Pkg);
|
||||
|
||||
pkgOrderList(pkgDepCache &Cache);
|
||||
~pkgOrderList();
|
||||
};
|
||||
|
||||
#endif
|
671
apt/apt-pkg/packagemanager.cc
Normal file
671
apt/apt-pkg/packagemanager.cc
Normal file
@ -0,0 +1,671 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: packagemanager.cc,v 1.15 2001/11/13 17:32:07 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Package Manager - Abstacts the package manager
|
||||
|
||||
More work is needed in the area of transitioning provides, ie exim
|
||||
replacing smail. This can cause interesing side effects.
|
||||
|
||||
Other cases involving conflicts+replaces should be tested.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/packagemanager.h"
|
||||
#endif
|
||||
#include <apt-pkg/packagemanager.h>
|
||||
#include <apt-pkg/orderlist.h>
|
||||
#include <apt-pkg/depcache.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/systemfactory.h>
|
||||
#include <apt-pkg/acquire-item.h>
|
||||
#include <apt-pkg/algorithms.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
|
||||
#include <i18n.h>
|
||||
|
||||
/*}}}*/
|
||||
|
||||
// PM::PackageManager - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgPackageManager::pkgPackageManager(pkgDepCache &Cache) : Cache(Cache)
|
||||
{
|
||||
FileNames = new string[Cache.Head().PackageCount];
|
||||
List = 0;
|
||||
Debug = _config->FindB("Debug::pkgPackageManager",false);
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::PackageManager - Destructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgPackageManager::~pkgPackageManager()
|
||||
{
|
||||
delete List;
|
||||
delete [] FileNames;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::GetArchives - Queue the archives for download /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
|
||||
pkgRecords *Recs)
|
||||
{
|
||||
if (CreateOrderList() == false)
|
||||
return false;
|
||||
|
||||
if (List->OrderUnpack() == false)
|
||||
return _error->Error("Internal ordering error");
|
||||
|
||||
for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
|
||||
{
|
||||
PkgIterator Pkg(Cache,*I);
|
||||
FileNames[Pkg->ID] = string();
|
||||
|
||||
// Skip packages to erase
|
||||
if (Cache[Pkg].Delete() == true)
|
||||
continue;
|
||||
|
||||
// Skip Packages that need configure only.
|
||||
if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
|
||||
Cache[Pkg].Keep() == true)
|
||||
continue;
|
||||
|
||||
// Skip already processed packages
|
||||
if (List->IsNow(Pkg) == false)
|
||||
continue;
|
||||
|
||||
new pkgAcqArchive(Owner,Sources,Recs,Cache[Pkg].InstVerIter(Cache),
|
||||
FileNames[Pkg->ID]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::FixMissing - Keep all missing packages /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called to correct the installation when packages could not
|
||||
be downloaded. */
|
||||
bool pkgPackageManager::FixMissing()
|
||||
{
|
||||
pkgProblemResolver Resolve(Cache);
|
||||
List->SetFileList(FileNames);
|
||||
|
||||
bool Bad = false;
|
||||
for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
|
||||
{
|
||||
if (List->IsMissing(I) == false)
|
||||
continue;
|
||||
|
||||
// Okay, this file is missing and we need it. Mark it for keep
|
||||
Bad = true;
|
||||
Cache.MarkKeep(I);
|
||||
}
|
||||
|
||||
// We have to empty the list otherwise it will not have the new changes
|
||||
delete List;
|
||||
List = 0;
|
||||
|
||||
if (Bad == false)
|
||||
return true;
|
||||
|
||||
// Now downgrade everything that is broken
|
||||
return Resolve.ResolveByKeep() == true && Cache.BrokenCount() == 0;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// PM::CreateOrderList - Create the ordering class /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This populates the ordering list with all the packages that are
|
||||
going to change. */
|
||||
bool pkgPackageManager::CreateOrderList()
|
||||
{
|
||||
if (List != 0)
|
||||
return true;
|
||||
|
||||
delete List;
|
||||
List = new pkgOrderList(Cache);
|
||||
|
||||
bool NoImmConfigure = _config->FindB("APT::Immediate-Configure",false);
|
||||
|
||||
// Generate the list of affected packages and sort it
|
||||
for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
|
||||
{
|
||||
// Mark the package and its dependends for immediate configuration
|
||||
if (((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential ||
|
||||
(I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) &&
|
||||
NoImmConfigure == false)
|
||||
{
|
||||
List->Flag(I,pkgOrderList::Immediate);
|
||||
|
||||
// Look for other packages to make immediate configurea
|
||||
if (Cache[I].InstallVer != 0)
|
||||
for (DepIterator D = Cache[I].InstVerIter(Cache).DependsList();
|
||||
D.end() == false; D++)
|
||||
if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
|
||||
List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
|
||||
|
||||
// And again with the current version.
|
||||
if (I->CurrentVer != 0)
|
||||
for (DepIterator D = I.CurrentVer().DependsList();
|
||||
D.end() == false; D++)
|
||||
if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
|
||||
List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
|
||||
}
|
||||
|
||||
// Not interesting
|
||||
if ((Cache[I].Keep() == true ||
|
||||
Cache[I].InstVerIter(Cache) == I.CurrentVer()) &&
|
||||
I.State() == pkgCache::PkgIterator::NeedsNothing &&
|
||||
(Cache[I].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall &&
|
||||
(I.Purge() != false || Cache[I].Mode != pkgDepCache::ModeDelete ||
|
||||
(Cache[I].iFlags & pkgDepCache::Purge) != pkgDepCache::Purge))
|
||||
continue;
|
||||
|
||||
// Append it to the list
|
||||
List->push_back(I);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::DepAlwaysTrue - Returns true if this dep is irrelevent /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The restriction on provides is to eliminate the case when provides
|
||||
are transitioning between valid states [ie exim to smail] */
|
||||
bool pkgPackageManager::DepAlwaysTrue(DepIterator D)
|
||||
{
|
||||
if (D.TargetPkg()->ProvidesList != 0)
|
||||
return false;
|
||||
|
||||
if ((Cache[D] & pkgDepCache::DepInstall) != 0 &&
|
||||
(Cache[D] & pkgDepCache::DepNow) != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::CheckRConflicts - Look for reverse conflicts /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This looks over the reverses for a conflicts line that needs early
|
||||
removal. */
|
||||
bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D,
|
||||
const char *Ver)
|
||||
{
|
||||
for (;D.end() == false; D++)
|
||||
{
|
||||
if (D->Type != pkgCache::Dep::Conflicts && D->Type != pkgCache::Dep::Obsoletes)
|
||||
continue;
|
||||
|
||||
// The package hasnt been changed
|
||||
if (List->IsNow(Pkg) == false)
|
||||
continue;
|
||||
|
||||
// Ignore self conflicts, ignore conflicts from irrelevent versions
|
||||
if (D.ParentPkg() == Pkg || D.ParentVer() != D.ParentPkg().CurrentVer())
|
||||
continue;
|
||||
|
||||
if (_system->checkDep(D.TargetVer(),Ver,D->CompareOp) == false)
|
||||
continue;
|
||||
|
||||
if (EarlyRemove(D.ParentPkg()) == false)
|
||||
return _error->Error("Reverse conflicts early remove for package '%s' failed",
|
||||
Pkg.Name());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::ConfigureAll - Run the all out configuration /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This configures every package. It is assumed they are all unpacked and
|
||||
that the final configuration is valid. */
|
||||
bool pkgPackageManager::ConfigureAll()
|
||||
{
|
||||
pkgOrderList OList(Cache);
|
||||
|
||||
// Populate the order list
|
||||
for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
|
||||
if (List->IsFlag(pkgCache::PkgIterator(Cache,*I),
|
||||
pkgOrderList::UnPacked) == true)
|
||||
OList.push_back(*I);
|
||||
|
||||
if (OList.OrderConfigure() == false)
|
||||
return false;
|
||||
|
||||
// Perform the configuring
|
||||
for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
|
||||
{
|
||||
PkgIterator Pkg(Cache,*I);
|
||||
|
||||
if (Configure(Pkg) == false)
|
||||
return false;
|
||||
|
||||
List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::SmartConfigure - Perform immediate configuration of the pkg /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This routine scheduals the configuration of the given package and all
|
||||
of it's dependents. */
|
||||
bool pkgPackageManager::SmartConfigure(PkgIterator Pkg)
|
||||
{
|
||||
pkgOrderList OList(Cache);
|
||||
|
||||
if (DepAdd(OList,Pkg) == false) {
|
||||
cout<<"AAA"<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OList.OrderConfigure() == false) {
|
||||
cout<<"BBB"<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform the configuring
|
||||
for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
|
||||
{
|
||||
PkgIterator Pkg(Cache,*I);
|
||||
|
||||
if (Configure(Pkg) == false) {
|
||||
cout<<"CCC"<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
|
||||
}
|
||||
|
||||
// Sanity Check
|
||||
if (List->IsFlag(Pkg,pkgOrderList::Configured) == false) {
|
||||
cout<<"DDD"<<endl;
|
||||
return _error->Error("Internal error, could not immediate configure %s",Pkg.Name());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::DepAdd - Add all dependents to the oder list /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This recursively adds all dependents to the order list */
|
||||
bool pkgPackageManager::DepAdd(pkgOrderList &OList,PkgIterator Pkg,int Depth)
|
||||
{
|
||||
if (OList.IsFlag(Pkg,pkgOrderList::Added) == true)
|
||||
return true;
|
||||
if (List->IsFlag(Pkg,pkgOrderList::Configured) == true)
|
||||
return true;
|
||||
if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == false)
|
||||
return false;
|
||||
|
||||
|
||||
// Put the package on the list
|
||||
OList.push_back(Pkg);
|
||||
OList.Flag(Pkg,pkgOrderList::Added);
|
||||
Depth++;
|
||||
|
||||
// Check the dependencies to see if they are all satisfied.
|
||||
bool Bad = false;
|
||||
for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
|
||||
{
|
||||
if (D->Type != pkgCache::Dep::Depends && D->Type != pkgCache::Dep::PreDepends)
|
||||
{
|
||||
D++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Grok or groups
|
||||
Bad = true;
|
||||
for (bool LastOR = true; D.end() == false && LastOR == true; D++)
|
||||
{
|
||||
LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
|
||||
|
||||
if (Bad == false)
|
||||
continue;
|
||||
|
||||
Version **VList = D.AllTargets();
|
||||
for (Version **I = VList; *I != 0 && Bad == true; I++)
|
||||
{
|
||||
VerIterator Ver(Cache,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
// See if the current version is ok
|
||||
if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true &&
|
||||
Pkg.State() == PkgIterator::NeedsNothing)
|
||||
{
|
||||
Bad = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not the install version
|
||||
if (Cache[Pkg].InstallVer != *I ||
|
||||
(Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
|
||||
continue;
|
||||
if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == true)
|
||||
Bad = !DepAdd(OList,Pkg,Depth);
|
||||
if (List->IsFlag(Pkg,pkgOrderList::Configured) == true)
|
||||
Bad = false;
|
||||
}
|
||||
delete [] VList;
|
||||
}
|
||||
|
||||
if (Bad == true)
|
||||
{
|
||||
OList.Flag(Pkg,0,pkgOrderList::Added);
|
||||
OList.pop_back();
|
||||
Depth--;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Depth--;
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::EarlyRemove - Perform removal of packages before their time /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is called to deal with conflicts arising from unpacking */
|
||||
bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
|
||||
{
|
||||
if (List->IsNow(Pkg) == false)
|
||||
return true;
|
||||
|
||||
// Already removed it
|
||||
if (List->IsFlag(Pkg,pkgOrderList::Removed) == true)
|
||||
return true;
|
||||
|
||||
// Woops, it will not be re-installed!
|
||||
if (List->IsFlag(Pkg,pkgOrderList::InList) == false)
|
||||
return false;
|
||||
|
||||
// Essential packages get special treatment
|
||||
bool IsEssential = false;
|
||||
if ((Pkg->Flags & pkgCache::Flag::Essential) != 0)
|
||||
IsEssential = true;
|
||||
|
||||
/* Check for packages that are the dependents of essential packages and
|
||||
promote them too */
|
||||
if (Pkg->CurrentVer != 0)
|
||||
{
|
||||
for (DepIterator D = Pkg.RevDependsList(); D.end() == false &&
|
||||
IsEssential == false; D++)
|
||||
if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
|
||||
if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0)
|
||||
IsEssential = true;
|
||||
}
|
||||
|
||||
if (IsEssential == true)
|
||||
{
|
||||
if (_config->FindB("APT::Force-LoopBreak",false) == false)
|
||||
return _error->Error(_("This installation run will require temporarily "
|
||||
"removing the essential package %s due to a "
|
||||
"Conflicts/Pre-Depends loop. This is often bad, "
|
||||
"but if you really want to do it, activate the "
|
||||
"APT::Force-LoopBreak option."),Pkg.Name());
|
||||
}
|
||||
|
||||
bool Res = SmartRemove(Pkg);
|
||||
if (Cache[Pkg].Delete() == false)
|
||||
List->Flag(Pkg,pkgOrderList::Removed,pkgOrderList::States);
|
||||
|
||||
return Res;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::SmartRemove - Removal Helper /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgPackageManager::SmartRemove(PkgIterator Pkg)
|
||||
{
|
||||
if (List->IsNow(Pkg) == false)
|
||||
return true;
|
||||
|
||||
List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
|
||||
if (Cache[Pkg].Replaced())
|
||||
return true;
|
||||
return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge);
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::SmartUnPack - Install helper /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This performs the task of handling pre-depends. */
|
||||
bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
|
||||
{
|
||||
// Check if it is already unpacked
|
||||
if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
|
||||
Cache[Pkg].Keep() == true)
|
||||
{
|
||||
List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States);
|
||||
if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true) {
|
||||
if (SmartConfigure(Pkg) == false)
|
||||
return _error->Error("Internal Error, Could not perform immediate configuration: %s",
|
||||
Pkg.Name());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* See if this packages install version has any predependencies
|
||||
that are not met by 'now' packages. */
|
||||
for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
|
||||
D.end() == false; )
|
||||
{
|
||||
// Compute a single dependency element (glob or)
|
||||
pkgCache::DepIterator Start;
|
||||
pkgCache::DepIterator End;
|
||||
D.GlobOr(Start,End);
|
||||
|
||||
while (End->Type == pkgCache::Dep::PreDepends)
|
||||
{
|
||||
// Look for possible ok targets.
|
||||
Version **VList = Start.AllTargets();
|
||||
bool Bad = true;
|
||||
for (Version **I = VList; *I != 0 && Bad == true; I++)
|
||||
{
|
||||
VerIterator Ver(Cache,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
// See if the current version is ok
|
||||
if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true &&
|
||||
Pkg.State() == PkgIterator::NeedsNothing)
|
||||
{
|
||||
Bad = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for something that could be configured.
|
||||
for (Version **I = VList; *I != 0 && Bad == true; I++)
|
||||
{
|
||||
VerIterator Ver(Cache,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
// Not the install version
|
||||
if (Cache[Pkg].InstallVer != *I ||
|
||||
(Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
|
||||
continue;
|
||||
|
||||
Bad = !SmartConfigure(Pkg);
|
||||
}
|
||||
|
||||
delete [] VList;
|
||||
|
||||
/* If this or element did not match then continue on to the
|
||||
next or element until a matching element is found*/
|
||||
if (Bad == true)
|
||||
{
|
||||
if (Start == End)
|
||||
return _error->Error("Internal Error, Couldn't configure a pre-depend: %s",
|
||||
Pkg.Name());
|
||||
Start++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (End->Type == pkgCache::Dep::Conflicts || End->Type == pkgCache::Dep::Obsoletes)
|
||||
{
|
||||
/* Look for conflicts. Two packages that are both in the install
|
||||
state cannot conflict so we don't check.. */
|
||||
Version **VList = End.AllTargets();
|
||||
for (Version **I = VList; *I != 0; I++)
|
||||
{
|
||||
VerIterator Ver(Cache,*I);
|
||||
PkgIterator Pkg = Ver.ParentPkg();
|
||||
|
||||
// See if the current version is conflicting
|
||||
// and that it's not obsoleting a virtual package
|
||||
if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true &&
|
||||
!(Pkg->ProvidesList == 0 && End->Type == pkgCache::Dep::Obsoletes))
|
||||
{
|
||||
if (EarlyRemove(Pkg) == false)
|
||||
return _error->Error("Internal Error, Could not early remove %s",Pkg.Name());
|
||||
}
|
||||
}
|
||||
delete [] VList;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for reverse conflicts.
|
||||
if (CheckRConflicts(Pkg,Pkg.RevDependsList(),
|
||||
Cache[Pkg].InstVerIter(Cache).VerStr()) == false)
|
||||
return false;
|
||||
|
||||
for (PrvIterator P = Cache[Pkg].InstVerIter(Cache).ProvidesList();
|
||||
P.end() == false; P++)
|
||||
CheckRConflicts(Pkg,P.ParentPkg().RevDependsList(),P.ProvideVersion());
|
||||
|
||||
if (Install(Pkg,FileNames[Pkg->ID]) == false)
|
||||
return false;
|
||||
|
||||
List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States);
|
||||
|
||||
// Perform immedate configuration of the package.
|
||||
if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true) {
|
||||
if (SmartConfigure(Pkg) == false)
|
||||
return _error->Error("Internal Error, Could not perform immediate configuration");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::OrderInstall - Installation ordering routine /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
|
||||
{
|
||||
for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
|
||||
{
|
||||
// Not interesting
|
||||
if ((Cache[I].Keep() == true ||
|
||||
Cache[I].InstVerIter(Cache) == I.CurrentVer()) &&
|
||||
I.State() == pkgCache::PkgIterator::NeedsNothing &&
|
||||
(Cache[I].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall &&
|
||||
(I.Purge() != false || Cache[I].Mode != pkgDepCache::ModeDelete ||
|
||||
(Cache[I].iFlags & pkgDepCache::Purge) != pkgDepCache::Purge))
|
||||
continue;
|
||||
|
||||
// Perform a delete or an install
|
||||
if (Cache[I].Delete() == true)
|
||||
{
|
||||
if (!Cache[I].Replaced() && !Remove(I))
|
||||
return Failed;
|
||||
}
|
||||
else
|
||||
if (Install(I, FileNames[I->ID]) == false)
|
||||
return Failed;
|
||||
}
|
||||
return Completed;
|
||||
#if 0
|
||||
if (CreateOrderList() == false)
|
||||
return Failed;
|
||||
|
||||
Reset();
|
||||
|
||||
if (Debug == true)
|
||||
clog << "Begining to order" << endl;
|
||||
|
||||
if (List->OrderUnpack(FileNames) == false)
|
||||
{
|
||||
_error->Error("Internal ordering error");
|
||||
return Failed;
|
||||
}
|
||||
|
||||
if (Debug == true)
|
||||
clog << "Done ordering" << endl;
|
||||
|
||||
bool DoneSomething = false;
|
||||
for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
|
||||
{
|
||||
PkgIterator Pkg(Cache,*I);
|
||||
|
||||
if (List->IsNow(Pkg) == false)
|
||||
{
|
||||
if (Debug == true)
|
||||
clog << "Skipping already done " << Pkg.Name() << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (List->IsMissing(Pkg) == true)
|
||||
{
|
||||
if (Debug == true)
|
||||
clog << "Sequence completed at " << Pkg.Name() << endl;
|
||||
if (DoneSomething == false)
|
||||
{
|
||||
_error->Error("Internal Error, ordering was unable to handle the media swap");
|
||||
return Failed;
|
||||
}
|
||||
return Incomplete;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (Cache[Pkg].Keep() == true &&
|
||||
Pkg.State() == pkgCache::PkgIterator::NeedsNothing &&
|
||||
(Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
|
||||
{
|
||||
_error->Error("Internal Error, trying to manipulate a kept package");
|
||||
return Failed;
|
||||
}
|
||||
|
||||
// Perform a delete or an install
|
||||
if (Cache[Pkg].Delete() == true)
|
||||
{
|
||||
if (SmartRemove(Pkg) == false)
|
||||
return Failed;
|
||||
}
|
||||
else
|
||||
if (SmartUnPack(Pkg) == false)
|
||||
return Failed;
|
||||
DoneSomething = true;
|
||||
}
|
||||
|
||||
// Final run through the configure phase
|
||||
if (ConfigureAll() == false)
|
||||
return Failed;
|
||||
|
||||
// Sanity check
|
||||
for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
|
||||
{
|
||||
if (List->IsFlag(*I,pkgOrderList::Configured) == false)
|
||||
{
|
||||
_error->Error("Internal error, packages left unconfigured. %s",
|
||||
PkgIterator(Cache,*I).Name());
|
||||
return Failed;
|
||||
}
|
||||
}
|
||||
|
||||
return Completed;
|
||||
#endif
|
||||
}
|
||||
/*}}}*/
|
||||
// PM::DoInstall - Does the installation /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This uses the filenames in FileNames and the information in the
|
||||
DepCache to perform the installation of packages.*/
|
||||
pkgPackageManager::OrderResult pkgPackageManager::DoInstall()
|
||||
{
|
||||
OrderResult Res = OrderInstall();
|
||||
if (Res != Failed)
|
||||
if (Go() == false)
|
||||
return Failed;
|
||||
return Res;
|
||||
}
|
||||
/*}}}*/
|
93
apt/apt-pkg/packagemanager.h
Normal file
93
apt/apt-pkg/packagemanager.h
Normal file
@ -0,0 +1,93 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: packagemanager.h,v 1.2 2000/09/26 14:22:14 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Package Manager - Abstacts the package manager
|
||||
|
||||
Three steps are
|
||||
- Aquiration of archives (stores the list of final file names)
|
||||
- Sorting of operations
|
||||
- Invokation of package manager
|
||||
|
||||
This is the final stage when the package cache entities get converted
|
||||
into file names and the state stored in a DepCache is transformed
|
||||
into a series of operations.
|
||||
|
||||
In the final scheme of things this may serve as a director class to
|
||||
access the actual install methods based on the file type being
|
||||
installed.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Header section: pkglib
|
||||
#ifndef PKGLIB_PACKAGEMANAGER_H
|
||||
#define PKGLIB_PACKAGEMANAGER_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/packagemanager.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <apt-pkg/pkgcache.h>
|
||||
|
||||
class pkgAcquire;
|
||||
class pkgDepCache;
|
||||
class pkgSourceList;
|
||||
class pkgOrderList;
|
||||
class pkgRecords;
|
||||
class pkgPackageManager
|
||||
{
|
||||
public:
|
||||
|
||||
enum OrderResult {Completed,Failed,Incomplete};
|
||||
|
||||
protected:
|
||||
string *FileNames;
|
||||
pkgDepCache &Cache;
|
||||
pkgOrderList *List;
|
||||
bool Debug;
|
||||
|
||||
// Bring some usefull types into the local scope
|
||||
typedef pkgCache::PkgIterator PkgIterator;
|
||||
typedef pkgCache::VerIterator VerIterator;
|
||||
typedef pkgCache::DepIterator DepIterator;
|
||||
typedef pkgCache::PrvIterator PrvIterator;
|
||||
typedef pkgCache::Version Version;
|
||||
typedef pkgCache::Package Package;
|
||||
|
||||
bool DepAdd(pkgOrderList &Order,PkgIterator P,int Depth = 0);
|
||||
OrderResult OrderInstall();
|
||||
bool CheckRConflicts(PkgIterator Pkg,DepIterator Dep,const char *Ver);
|
||||
bool CreateOrderList();
|
||||
|
||||
// Analysis helpers
|
||||
bool DepAlwaysTrue(DepIterator D);
|
||||
|
||||
// Install helpers
|
||||
bool ConfigureAll();
|
||||
bool SmartConfigure(PkgIterator Pkg);
|
||||
bool SmartUnPack(PkgIterator Pkg);
|
||||
bool SmartRemove(PkgIterator Pkg);
|
||||
bool EarlyRemove(PkgIterator Pkg);
|
||||
|
||||
// The Actuall installation implementation
|
||||
virtual bool Install(PkgIterator /*Pkg*/,string /*File*/) {return false;};
|
||||
virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
|
||||
virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
|
||||
virtual bool Go() {return true;};
|
||||
virtual void Reset() {};
|
||||
|
||||
public:
|
||||
|
||||
// Main action members
|
||||
bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
|
||||
pkgRecords *Recs);
|
||||
OrderResult DoInstall();
|
||||
bool FixMissing();
|
||||
|
||||
pkgPackageManager(pkgDepCache &Cache);
|
||||
virtual ~pkgPackageManager();
|
||||
};
|
||||
|
||||
#endif
|
545
apt/apt-pkg/pkgcache.cc
Normal file
545
apt/apt-pkg/pkgcache.cc
Normal file
@ -0,0 +1,545 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: pkgcache.cc,v 1.11 2001/06/25 16:16:18 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Package Cache - Accessor code for the cache
|
||||
|
||||
Please see doc/apt-pkg/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 /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/pkgcache.h"
|
||||
#pragma implementation "apt-pkg/cacheiterators.h"
|
||||
#endif
|
||||
#include <apt-pkg/pkgcache.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
#include <apt-pkg/systemfactory.h>
|
||||
|
||||
#include <i18n.h>
|
||||
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <system.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 = 3;
|
||||
MinorVersion = 7;
|
||||
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);
|
||||
VerFileSz = sizeof(pkgCache::VerFile);
|
||||
|
||||
PackageCount = 0;
|
||||
VersionCount = 0;
|
||||
DependsCount = 0;
|
||||
PackageFileCount = 0;
|
||||
VerFileCount = 0;
|
||||
ProvidesCount = 0;
|
||||
MaxVerFileSize = 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 &&
|
||||
VerFileSz == Against.VerFileSz &&
|
||||
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();
|
||||
VerFileP = (VerFile *)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();
|
||||
|
||||
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) const
|
||||
{
|
||||
unsigned long Hash = 0;
|
||||
#if 0
|
||||
for (const char *I = Str.begin(); I != Str.end(); I++)
|
||||
Hash = 5*Hash + tolower(*I);
|
||||
#else
|
||||
for (const char *I = Str.begin(); I != Str.end(); I++)
|
||||
Hash = 5*Hash + *I;
|
||||
#endif
|
||||
return Hash % _count(HeaderP->HashTable);
|
||||
}
|
||||
|
||||
unsigned long pkgCache::sHash(const char *Str) const
|
||||
{
|
||||
unsigned long Hash = 0;
|
||||
#if 0
|
||||
for (const char *I = Str; *I != 0; I++)
|
||||
Hash = 5*Hash + tolower(*I);
|
||||
#else
|
||||
for (const char *I = Str; *I != 0; I++)
|
||||
Hash = 5*Hash + *I;
|
||||
#endif
|
||||
return Hash % _count(HeaderP->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 0
|
||||
if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] &&
|
||||
stringcasecmp(Name.begin(),Name.end(),StrP + Pkg->Name) == 0)
|
||||
return PkgIterator(*this,Pkg);
|
||||
#else
|
||||
if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] &&
|
||||
stringcmp(Name.begin(),Name.end(),StrP + Pkg->Name) == 0)
|
||||
return PkgIterator(*this,Pkg);
|
||||
#endif
|
||||
}
|
||||
return PkgIterator(*this,0);
|
||||
}
|
||||
/*}}}*/
|
||||
// Cache::Priority - Convert a priority value to a string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
const char *pkgCache::Priority(unsigned char Prio)
|
||||
{
|
||||
const char *Mapping[] = {0,"important","required","standard","optional","extra"};
|
||||
if (Prio < _count(Mapping))
|
||||
return Mapping[Prio];
|
||||
return 0;
|
||||
}
|
||||
/*}}}*/
|
||||
// Cache::GetCandidateVer - Returns the Candidate install version /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* The default just returns the highest available version that is not
|
||||
a source and automatic */
|
||||
pkgCache::VerIterator pkgCache::GetCandidateVer(PkgIterator Pkg,
|
||||
bool AllowCurrent)
|
||||
{
|
||||
/* Not source/not automatic versions cannot be a candidate version
|
||||
unless they are already installed */
|
||||
VerIterator Last(*this,0);
|
||||
|
||||
for (VerIterator I = Pkg.VersionList(); I.end() == false; I++)
|
||||
{
|
||||
if (Pkg.CurrentVer() == I && AllowCurrent == true)
|
||||
return I;
|
||||
|
||||
for (VerFileIterator J = I.FileList(); J.end() == false; J++)
|
||||
{
|
||||
if ((J.File()->Flags & Flag::NotSource) != 0)
|
||||
continue;
|
||||
|
||||
/* Stash the highest version of a not-automatic source, we use it
|
||||
if there is nothing better */
|
||||
if ((J.File()->Flags & Flag::NotAutomatic) != 0)
|
||||
{
|
||||
if (Last.end() == true)
|
||||
Last = I;
|
||||
continue;
|
||||
}
|
||||
|
||||
return I;
|
||||
}
|
||||
}
|
||||
|
||||
return Last;
|
||||
}
|
||||
/*}}}*/
|
||||
|
||||
// Bases for iterator classes /*{{{*/
|
||||
void pkgCache::VerIterator::_dummy() {}
|
||||
void pkgCache::DepIterator::_dummy() {}
|
||||
void pkgCache::PrvIterator::_dummy() {}
|
||||
/*}}}*/
|
||||
// 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];
|
||||
}
|
||||
};
|
||||
/*}}}*/
|
||||
// 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->InstState == pkgCache::State::ReInstReq ||
|
||||
Pkg->InstState == pkgCache::State::HoldReInstReq)
|
||||
return NeedsUnpack;
|
||||
|
||||
if (Pkg->CurrentState == pkgCache::State::UnPacked ||
|
||||
Pkg->CurrentState == pkgCache::State::HalfConfigured)
|
||||
return NeedsConfigure;
|
||||
|
||||
if (Pkg->CurrentState == pkgCache::State::HalfInstalled ||
|
||||
Pkg->InstState != pkgCache::State::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 == pkgCache::Dep::Conflicts ||
|
||||
Dep->Type == pkgCache::Dep::Obsoletes ||
|
||||
Dep->Type == pkgCache::Dep::Depends ||
|
||||
Dep->Type == pkgCache::Dep::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;
|
||||
}
|
||||
|
||||
Result = PStart.OwnerPkg();
|
||||
// Check for non dups
|
||||
if (P.end() != true)
|
||||
return true;
|
||||
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. The resulting pointer
|
||||
must be delete [] 'd */
|
||||
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 (_system->checkDep(TargetVer(),I.VerStr(),Dep->CompareOp) == false)
|
||||
continue;
|
||||
|
||||
if ((Dep->Type == pkgCache::Dep::Conflicts
|
||||
|| Dep->Type == pkgCache::Dep::Obsoletes) &&
|
||||
ParentPkg() == I.ParentPkg())
|
||||
continue;
|
||||
|
||||
Size++;
|
||||
if (Res != 0)
|
||||
*End++ = I;
|
||||
}
|
||||
|
||||
// Follow all provides
|
||||
for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++)
|
||||
{
|
||||
if (_system->checkDep(TargetVer(),I.ProvideVersion(),Dep->CompareOp) == false)
|
||||
continue;
|
||||
|
||||
if ((Dep->Type == pkgCache::Dep::Conflicts
|
||||
|| Dep->Type == pkgCache::Dep::Obsoletes) &&
|
||||
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;
|
||||
}
|
||||
/*}}}*/
|
||||
// DepIterator::CompType - Return a string describing the compare type /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This returns a string representation of the dependency compare
|
||||
type */
|
||||
const char *pkgCache::DepIterator::CompType()
|
||||
{
|
||||
const char *Ops[] = {"","<=",">=","<",">","=","!="};
|
||||
if ((unsigned)(Dep->CompareOp & 0xF) < 7)
|
||||
return Ops[Dep->CompareOp & 0xF];
|
||||
return "";
|
||||
}
|
||||
/*}}}*/
|
||||
// DepIterator::DepType - Return a string describing the dep type /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
const char *pkgCache::DepIterator::DepType()
|
||||
{
|
||||
const char *Types[] = {"","Depends","PreDepends","Suggests",
|
||||
"Recommends","Conflicts","Replaces","Obsoletes"};
|
||||
if (Dep->Type < 8)
|
||||
return Types[Dep->Type];
|
||||
return "";
|
||||
}
|
||||
/*}}}*/
|
||||
// DepIterator::GlobOr - Compute an OR group /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This Takes an iterator, iterates past the current dependency grouping
|
||||
and returns Start and End so that so End is the final element
|
||||
in the group, if End == Start then D is End++ and End is the
|
||||
dependency D was pointing to. Use in loops to iterate sensibly. */
|
||||
void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End)
|
||||
{
|
||||
// Compute a single dependency element (glob or)
|
||||
Start = *this;
|
||||
End = *this;
|
||||
for (bool LastOR = true; end() == false && LastOR == true;)
|
||||
{
|
||||
LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
|
||||
(*this)++;
|
||||
if (LastOR == true)
|
||||
End = (*this);
|
||||
}
|
||||
}
|
||||
/*}}}*/
|
||||
// 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;
|
||||
}
|
||||
/*}}}*/
|
||||
// VerIterator::Downloadable - Checks if the version is downloadable /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgCache::VerIterator::Downloadable() const
|
||||
{
|
||||
VerFileIterator Files = FileList();
|
||||
for (; Files.end() == false; Files++)
|
||||
if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// VerIterator::PriorityType - Return a string describing the priority /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
const char *pkgCache::VerIterator::PriorityType()
|
||||
{
|
||||
const char *Types[] = {"","Important","Required","Standard",
|
||||
"Optional","Extra"};
|
||||
if (Ver->Priority < 6)
|
||||
return Types[Ver->Priority];
|
||||
return "";
|
||||
}
|
||||
/*}}}*/
|
||||
// VerIterator::Automatic - Check if this version is 'automatic' /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This checks to see if any of the versions files are not NotAutomatic.
|
||||
True if this version is selectable for automatic installation. */
|
||||
bool pkgCache::VerIterator::Automatic() const
|
||||
{
|
||||
VerFileIterator Files = FileList();
|
||||
for (; Files.end() == false; Files++)
|
||||
if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/*}}}*/
|
||||
// VerIterator::NewestFile - Return the newest file version relation /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This looks at the version numbers associated with all of the sources
|
||||
this version is in and returns the highest.*/
|
||||
pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
|
||||
{
|
||||
VerFileIterator Files = FileList();
|
||||
VerFileIterator Highest = Files;
|
||||
for (; Files.end() == false; Files++)
|
||||
{
|
||||
if (_system->versionCompare(Files.File().Version(),Highest.File().Version()) > 0)
|
||||
Highest = Files;
|
||||
}
|
||||
|
||||
return Highest;
|
||||
}
|
||||
/*}}}*/
|
||||
// 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;
|
||||
}
|
||||
/*}}}*/
|
281
apt/apt-pkg/pkgcache.h
Normal file
281
apt/apt-pkg/pkgcache.h
Normal file
@ -0,0 +1,281 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: pkgcache.h,v 1.2 2000/09/18 18:34:42 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Cache - Structure definitions for the cache file
|
||||
|
||||
Please see doc/apt-pkg/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
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "apt-pkg/pkgcache.h"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <apt-pkg/mmap.h>
|
||||
|
||||
class pkgCache
|
||||
{
|
||||
public:
|
||||
// Cache element predeclarations
|
||||
struct Header;
|
||||
struct Package;
|
||||
struct PackageFile;
|
||||
struct Version;
|
||||
struct Provides;
|
||||
struct Dependency;
|
||||
struct StringItem;
|
||||
struct VerFile;
|
||||
|
||||
// Iterators
|
||||
class PkgIterator;
|
||||
class VerIterator;
|
||||
class DepIterator;
|
||||
class PrvIterator;
|
||||
class PkgFileIterator;
|
||||
class VerFileIterator;
|
||||
friend PkgIterator;
|
||||
friend VerIterator;
|
||||
friend DepIterator;
|
||||
friend PrvIterator;
|
||||
friend PkgFileIterator;
|
||||
friend VerFileIterator;
|
||||
|
||||
// These are all the constants used in the cache structures
|
||||
struct Dep
|
||||
{
|
||||
enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
|
||||
Conflicts=5,Replaces=6,Obsoletes=7};
|
||||
enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
|
||||
Greater=0x4,Equals=0x5,NotEquals=0x6};
|
||||
};
|
||||
|
||||
struct State
|
||||
{
|
||||
enum VerPriority {Important=1,Required=2,Standard=3,Optional=4,Extra=5};
|
||||
enum PkgSelectedState {Unknown=0,Install=1,Hold=2,DeInstall=3,Purge=4};
|
||||
enum PkgInstState {Ok=0,ReInstReq=1,HoldInst=2,HoldReInstReq=3};
|
||||
enum PkgCurrentState {NotInstalled=0,UnPacked=1,HalfConfigured=2,
|
||||
HalfInstalled=4,ConfigFiles=5,Installed=6};
|
||||
};
|
||||
|
||||
struct Flag
|
||||
{
|
||||
enum PkgFlags {Auto=(1<<0),Essential=(1<<3),Important=(1<<4)};
|
||||
enum PkgFFlags {NotSource=(1<<0),NotAutomatic=(1<<1)};
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
// Memory mapped cache file
|
||||
string CacheFile;
|
||||
MMap ⤅
|
||||
|
||||
unsigned long sHash(string S) const;
|
||||
unsigned long sHash(const char *S) const;
|
||||
|
||||
public:
|
||||
|
||||
// Pointers to the arrays of items
|
||||
Header *HeaderP;
|
||||
Package *PkgP;
|
||||
VerFile *VerFileP;
|
||||
PackageFile *PkgFileP;
|
||||
Version *VerP;
|
||||
Provides *ProvideP;
|
||||
Dependency *DepP;
|
||||
StringItem *StringItemP;
|
||||
char *StrP;
|
||||
|
||||
virtual bool ReMap();
|
||||
inline bool Sync() {return Map.Sync();};
|
||||
inline MMap &GetMap() {return Map;};
|
||||
|
||||
// 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);};
|
||||
|
||||
// Usefull transformation things
|
||||
const char *Priority(unsigned char Priority);
|
||||
|
||||
// Accessors
|
||||
PkgIterator FindPkg(string Name);
|
||||
Header &Head() {return *HeaderP;};
|
||||
inline PkgIterator PkgBegin();
|
||||
inline PkgIterator PkgEnd();
|
||||
inline PkgFileIterator FileBegin();
|
||||
inline PkgFileIterator FileEnd();
|
||||
VerIterator GetCandidateVer(PkgIterator Pkg,bool AllowCurrent = true);
|
||||
|
||||
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;
|
||||
unsigned short VerFileSz;
|
||||
|
||||
// Structure counts
|
||||
unsigned long PackageCount;
|
||||
unsigned long VersionCount;
|
||||
unsigned long DependsCount;
|
||||
unsigned long PackageFileCount;
|
||||
unsigned long VerFileCount;
|
||||
unsigned long ProvidesCount;
|
||||
|
||||
// Offsets
|
||||
map_ptrloc FileList; // struct PackageFile
|
||||
map_ptrloc StringList; // struct StringItem
|
||||
unsigned long MaxVerFileSize;
|
||||
|
||||
/* Allocation pools, there should be one of these for each structure
|
||||
excluding the header */
|
||||
DynamicMMap::Pool Pools[7];
|
||||
|
||||
// Rapid package name lookup
|
||||
map_ptrloc HashTable[2*1048];
|
||||
|
||||
bool CheckSizes(Header &Against) const;
|
||||
Header();
|
||||
};
|
||||
|
||||
struct pkgCache::Package
|
||||
{
|
||||
// Pointers
|
||||
map_ptrloc Name; // Stringtable
|
||||
map_ptrloc VersionList; // Version
|
||||
map_ptrloc TargetVer; // Version
|
||||
map_ptrloc CurrentVer; // Version
|
||||
map_ptrloc TargetDist; // StringTable (StringItem)
|
||||
map_ptrloc Section; // StringTable (StringItem)
|
||||
|
||||
// Linked list
|
||||
map_ptrloc NextPackage; // Package
|
||||
map_ptrloc RevDepends; // Dependency
|
||||
map_ptrloc ProvidesList; // Provides
|
||||
|
||||
// Install/Remove/Purge etc
|
||||
unsigned char SelectedState; // What
|
||||
unsigned char InstState; // Flags
|
||||
unsigned char CurrentState; // State
|
||||
|
||||
unsigned short ID;
|
||||
unsigned long Flags;
|
||||
};
|
||||
|
||||
struct pkgCache::PackageFile
|
||||
{
|
||||
// Names
|
||||
map_ptrloc FileName; // Stringtable
|
||||
map_ptrloc Archive; // Stringtable
|
||||
map_ptrloc Component; // Stringtable
|
||||
map_ptrloc Version; // Stringtable
|
||||
map_ptrloc Origin; // Stringtable
|
||||
map_ptrloc Label; // Stringtable
|
||||
map_ptrloc Architecture; // Stringtable
|
||||
unsigned long Size;
|
||||
unsigned long Flags;
|
||||
|
||||
// Linked list
|
||||
map_ptrloc NextFile; // PackageFile
|
||||
unsigned short ID;
|
||||
time_t mtime; // Modification time for the file
|
||||
};
|
||||
|
||||
struct pkgCache::VerFile
|
||||
{
|
||||
map_ptrloc File; // PackageFile
|
||||
map_ptrloc NextFile; // PkgVerFile
|
||||
map_ptrloc Offset; // File offset
|
||||
unsigned short Size;
|
||||
};
|
||||
|
||||
struct pkgCache::Version
|
||||
{
|
||||
map_ptrloc VerStr; // Stringtable
|
||||
map_ptrloc Section; // StringTable (StringItem)
|
||||
map_ptrloc Arch; // StringTable
|
||||
|
||||
// Lists
|
||||
map_ptrloc FileList; // VerFile
|
||||
map_ptrloc NextVer; // Version
|
||||
map_ptrloc DependsList; // Dependency
|
||||
map_ptrloc ParentPkg; // Package
|
||||
map_ptrloc ProvidesList; // Provides
|
||||
|
||||
map_ptrloc Size; // These are the .deb size
|
||||
map_ptrloc InstalledSize;
|
||||
unsigned short Hash;
|
||||
unsigned short ID;
|
||||
unsigned char Priority;
|
||||
};
|
||||
|
||||
struct pkgCache::Dependency
|
||||
{
|
||||
map_ptrloc Version; // Stringtable
|
||||
map_ptrloc Package; // Package
|
||||
map_ptrloc NextDepends; // Dependency
|
||||
map_ptrloc NextRevDepends; // Dependency
|
||||
map_ptrloc ParentVer; // Version
|
||||
|
||||
// Specific types of depends
|
||||
unsigned char Type;
|
||||
unsigned char CompareOp;
|
||||
unsigned short ID;
|
||||
};
|
||||
|
||||
struct pkgCache::Provides
|
||||
{
|
||||
map_ptrloc ParentPkg; // Pacakge
|
||||
map_ptrloc Version; // Version
|
||||
map_ptrloc ProvideVersion; // Stringtable
|
||||
map_ptrloc NextProvides; // Provides
|
||||
map_ptrloc NextPkgProv; // Provides
|
||||
};
|
||||
|
||||
struct pkgCache::StringItem
|
||||
{
|
||||
map_ptrloc String; // Stringtable
|
||||
map_ptrloc NextItem; // StringItem
|
||||
};
|
||||
|
||||
#include <apt-pkg/cacheiterators.h>
|
||||
|
||||
inline pkgCache::PkgIterator pkgCache::PkgBegin()
|
||||
{return PkgIterator(*this);};
|
||||
inline pkgCache::PkgIterator pkgCache::PkgEnd()
|
||||
{return PkgIterator(*this,PkgP);};
|
||||
inline pkgCache::PkgFileIterator pkgCache::FileBegin()
|
||||
{return PkgFileIterator(*this);};
|
||||
inline pkgCache::PkgFileIterator pkgCache::FileEnd()
|
||||
{return PkgFileIterator(*this,PkgFileP);};
|
||||
|
||||
#endif
|
468
apt/apt-pkg/pkgcachegen.cc
Normal file
468
apt/apt-pkg/pkgcachegen.cc
Normal file
@ -0,0 +1,468 @@
|
||||
// -*- mode: cpp; mode: fold -*-
|
||||
// Description /*{{{*/
|
||||
// $Id: pkgcachegen.cc,v 1.24 2001/12/11 20:50:12 kojima Exp $
|
||||
/* ######################################################################
|
||||
|
||||
Package Cache Generator - Generator for the cache structure.
|
||||
|
||||
This builds the cache structure from the abstract package list parser.
|
||||
|
||||
##################################################################### */
|
||||
/*}}}*/
|
||||
// Include Files /*{{{*/
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "apt-pkg/pkgcachegen.h"
|
||||
#endif
|
||||
|
||||
#include <apt-pkg/pkgcachegen.h>
|
||||
#include <apt-pkg/error.h>
|
||||
#include <apt-pkg/progress.h>
|
||||
#include <apt-pkg/sourcelist.h>
|
||||
#include <apt-pkg/configuration.h>
|
||||
#include <apt-pkg/strutl.h>
|
||||
|
||||
#include <apt-pkg/systemfactory.h>
|
||||
|
||||
#include <i18n.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <system.h>
|
||||
/*}}}*/
|
||||
// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* We set the diry flag and make sure that is written to the disk */
|
||||
pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map,OpProgress &Prog) : Map(Map), Cache(Map), Progress(&Prog)
|
||||
{
|
||||
CurrentFile = 0;
|
||||
|
||||
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]));
|
||||
memset(UniqHash,0,sizeof(UniqHash));
|
||||
}
|
||||
/*}}}*/
|
||||
// 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,
|
||||
pkgCache::VerIterator *OutVer)
|
||||
{
|
||||
List.Owner = this;
|
||||
|
||||
unsigned int Counter = 0;
|
||||
while (List.Step() == true)
|
||||
{
|
||||
// Get a pointer to the package structure
|
||||
string PackageName = List.Package();
|
||||
|
||||
if (PackageName.empty() == true)
|
||||
return false;
|
||||
|
||||
pkgCache::PkgIterator Pkg;
|
||||
if (NewPackage(Pkg,PackageName) == false)
|
||||
return _error->Error(_("Error occured while processing %s (NewPackage)"),PackageName.c_str());
|
||||
Counter++;
|
||||
if (Counter % 100 == 0 && Progress != 0)
|
||||
Progress->Progress(List.Offset());
|
||||
|
||||
/* 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();
|
||||
if (Version.empty() == true)
|
||||
{
|
||||
if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
|
||||
return _error->Error(_("Error occured while processing %s (UsePackage1)"),PackageName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
pkgCache::VerIterator Ver = Pkg.VersionList();
|
||||
map_ptrloc *Last = &Pkg->VersionList;
|
||||
int Res = 1;
|
||||
for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
|
||||
{
|
||||
Res = _system->versionCompare(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 */
|
||||
unsigned long Hash = List.VersionHash();
|
||||
bool ToEnd = true;
|
||||
|
||||
if (Res == 0 && Ver->Hash == Hash)
|
||||
{
|
||||
if (List.UsePackage(Pkg,Ver) == false)
|
||||
return _error->Error(_("Error occured while processing %s (UsePackage2)"),PackageName.c_str());
|
||||
|
||||
if (NewFileVer(Ver,List) == false)
|
||||
return _error->Error(_("Error occured while processing %s (NewFileVer1)"),PackageName.c_str());
|
||||
|
||||
// Read only a single record and return
|
||||
if (OutVer != 0)
|
||||
{
|
||||
*OutVer = Ver;
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
} else if (Res == 0) {
|
||||
cout << _("WARNING: '") << PackageName << _("' has 2 packages with same version but different dependencies. ");
|
||||
cout << _("That usually means a packaging bug.") << endl;
|
||||
|
||||
if (Pkg.CurrentVer() == Ver) {
|
||||
// if this is the currently installed version, then
|
||||
// keep it as the 1st in the same version set
|
||||
ToEnd = false;
|
||||
} else {
|
||||
// if this one is not the currently installed version,
|
||||
// just ignore it. and hope that this package doesn't
|
||||
// have an extra dependency that would fix some
|
||||
// situation... which would be severe a packaging bug anyway
|
||||
// cout << "Skipping package"<<endl;
|
||||
// continue;
|
||||
// apparently have some problems yet, got a case where
|
||||
// an isntalled pkg was undetected
|
||||
}
|
||||
}
|
||||
// Skip to the end of the same version set
|
||||
if (Res == 0 && ToEnd == true)
|
||||
{
|
||||
for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
|
||||
{
|
||||
Res = _system->versionCompare(Version.begin(),Version.end(),Ver.VerStr(),
|
||||
Ver.VerStr() + strlen(Ver.VerStr()));
|
||||
if (Res != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new version
|
||||
*Last = NewVersion(Ver,Version,*Last);
|
||||
Ver->ParentPkg = Pkg.Index();
|
||||
Ver->Hash = Hash;
|
||||
if (List.NewVersion(Ver) == false)
|
||||
return _error->Error(_("Error occured while processing %s (NewVersion1)"),PackageName.c_str());
|
||||
|
||||
if (List.UsePackage(Pkg,Ver) == false)
|
||||
return _error->Error(_("Error occured while processing %s (UsePackage3)"),PackageName.c_str());
|
||||
|
||||
if (NewFileVer(Ver,List) == false)
|
||||
return _error->Error(_("Error occured while processing %s (NewVersion2)"),PackageName.c_str());
|
||||
|
||||
// Read only a single record and return
|
||||
if (OutVer != 0)
|
||||
{
|
||||
*OutVer = Ver;
|
||||
return 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)
|
||||
{
|
||||
Pkg = Cache.FindPkg(Name);
|
||||
if (Pkg.end() == false)
|
||||
return true;
|
||||
|
||||
// Get a structure
|
||||
unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
|
||||
if (Package == 0)
|
||||
return false;
|
||||
|
||||
Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
|
||||
|
||||
// Insert it into the hash table
|
||||
unsigned long Hash = Cache.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)
|
||||
{
|
||||
if (CurrentFile == 0)
|
||||
return true;
|
||||
|
||||
// Get a structure
|
||||
unsigned long VerFile = Map.Allocate(sizeof(pkgCache::VerFile));
|
||||
if (VerFile == 0)
|
||||
return false;
|
||||
|
||||
pkgCache::VerFileIterator VF(Cache,Cache.VerFileP + VerFile);
|
||||
VF->File = CurrentFile - Cache.PkgFileP;
|
||||
|
||||
// Link it to the end of the list
|
||||
map_ptrloc *Last = &Ver->FileList;
|
||||
for (pkgCache::VerFileIterator V = Ver.FileList(); V.end() == false; V++)
|
||||
Last = &V->NextFile;
|
||||
VF->NextFile = *Last;
|
||||
*Last = VF.Index();
|
||||
|
||||
VF->Offset = List.Offset();
|
||||
VF->Size = List.Size();
|
||||
if (Cache.HeaderP->MaxVerFileSize < VF->Size)
|
||||
Cache.HeaderP->MaxVerFileSize = VF->Size;
|
||||
Cache.HeaderP->VerFileCount++;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// CacheGenerator::NewVersion - Create a new Version /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This puts a version structure in the linked list */
|
||||
unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
|
||||
string VerStr,
|
||||
unsigned long Next)
|
||||
{
|
||||
// Get a structure
|
||||
unsigned long Version = Map.Allocate(sizeof(pkgCache::Version));
|
||||
if (Version == 0)
|
||||
return 0;
|
||||
|
||||
// Fill it in
|
||||
Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
|
||||
Ver->NextVer = Next;
|
||||
Ver->ID = Cache.HeaderP->VersionCount++;
|
||||
Ver->VerStr = Map.WriteString(VerStr);
|
||||
if (Ver->VerStr == 0)
|
||||
return 0;
|
||||
|
||||
return Version;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::NewDepends - Create a dependency element /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This creates a dependency element in the tree. It is linked to the
|
||||
version and to the package that it is pointing to. */
|
||||
bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
|
||||
string PackageName,
|
||||
string Version,
|
||||
unsigned int Op,
|
||||
unsigned int Type)
|
||||
{
|
||||
pkgCache &Cache = Owner->Cache;
|
||||
|
||||
// Get a structure
|
||||
unsigned long Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency));
|
||||
if (Dependency == 0)
|
||||
return false;
|
||||
|
||||
// Fill it in
|
||||
pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
|
||||
Dep->ParentVer = Ver.Index();
|
||||
Dep->Type = Type;
|
||||
Dep->CompareOp = Op;
|
||||
Dep->ID = Cache.HeaderP->DependsCount++;
|
||||
|
||||
// Locate the target package
|
||||
pkgCache::PkgIterator Pkg;
|
||||
if (Owner->NewPackage(Pkg,PackageName) == false)
|
||||
return false;
|
||||
|
||||
// Probe the reverse dependency list for a version string that matches
|
||||
if (Version.empty() == false)
|
||||
{
|
||||
/* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++, Hit++)
|
||||
if (I->Version != 0 && I.TargetVer() == Version)
|
||||
Dep->Version = I->Version;*/
|
||||
if (Dep->Version == 0)
|
||||
if ((Dep->Version = WriteString(Version)) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Link it to the package
|
||||
Dep->Package = Pkg.Index();
|
||||
Dep->NextRevDepends = Pkg->RevDepends;
|
||||
Pkg->RevDepends = Dep.Index();
|
||||
|
||||
/* Link it to the version (at the end of the list)
|
||||
Caching the old end point speeds up generation substantially */
|
||||
if (OldDepVer != Ver)
|
||||
{
|
||||
OldDepLast = &Ver->DependsList;
|
||||
for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
|
||||
OldDepLast = &D->NextDepends;
|
||||
OldDepVer = Ver;
|
||||
}
|
||||
|
||||
|
||||
Dep->NextDepends = *OldDepLast;
|
||||
*OldDepLast = Dep.Index();
|
||||
OldDepLast = &Dep->NextDepends;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// ListParser::NewProvides - Create a Provides element /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* */
|
||||
bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
|
||||
string PackageName,
|
||||
string Version)
|
||||
{
|
||||
pkgCache &Cache = Owner->Cache;
|
||||
|
||||
// We do not add self referencing provides
|
||||
if (Ver.ParentPkg().Name() == PackageName)
|
||||
return true;
|
||||
|
||||
// Get a structure
|
||||
unsigned long Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
|
||||
if (Provides == 0)
|
||||
return false;
|
||||
Cache.HeaderP->ProvidesCount++;
|
||||
|
||||
// Fill it in
|
||||
pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
|
||||
Prv->Version = Ver.Index();
|
||||
Prv->NextPkgProv = Ver->ProvidesList;
|
||||
Ver->ProvidesList = Prv.Index();
|
||||
|
||||
if (Version.empty() == false)
|
||||
{
|
||||
if (Prv->ProvideVersion == 0)
|
||||
if ((Prv->ProvideVersion = WriteString(Version)) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Locate the target package
|
||||
pkgCache::PkgIterator Pkg;
|
||||
if (Owner->NewPackage(Pkg,PackageName) == false)
|
||||
return false;
|
||||
|
||||
// Link it to the package
|
||||
Prv->ParentPkg = Pkg.Index();
|
||||
Prv->NextProvides = Pkg->ProvidesList;
|
||||
Pkg->ProvidesList = Prv.Index();
|
||||
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// 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 %s",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;
|
||||
CurrentFile->ID = Cache.HeaderP->PackageFileCount;
|
||||
PkgFileName = File;
|
||||
Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
|
||||
Cache.HeaderP->PackageFileCount++;
|
||||
|
||||
if (CurrentFile->FileName == 0)
|
||||
return false;
|
||||
|
||||
if (Progress != 0)
|
||||
Progress->SubProgress(Buf.st_size);
|
||||
return true;
|
||||
}
|
||||
/*}}}*/
|
||||
// CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
|
||||
// ---------------------------------------------------------------------
|
||||
/* This is used to create handles to strings. Given the same text it
|
||||
always returns the same number */
|
||||
unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
|
||||
unsigned int Size)
|
||||
{
|
||||
/* We use a very small transient hash table here, this speeds up generation
|
||||
by a fair amount on slower machines */
|
||||
pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % _count(UniqHash)];
|
||||
if (Bucket != 0 &&
|
||||
stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0)
|
||||
return Bucket->String;
|
||||
|
||||
// Search for an insertion point
|
||||
pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
|
||||
int Res = 1;
|
||||
map_ptrloc *Last = &Cache.HeaderP->StringList;
|
||||
for (; I != Cache.StringItemP; Last = &I->NextItem,
|
||||
I = Cache.StringItemP + I->NextItem)
|
||||
{
|
||||
Res = stringcmp(S,S+Size,Cache.StrP + I->String);
|
||||
if (Res >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Match
|
||||
if (Res == 0)
|
||||
{
|
||||
Bucket = I;
|
||||
return I->String;
|
||||
}
|
||||
|
||||
// Get a structure
|
||||
unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
|
||||
if (Item == 0)
|
||||
return 0;
|
||||
|
||||
// Fill in the structure
|
||||
pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
|
||||
ItemP->NextItem = I - Cache.StringItemP;
|
||||
*Last = Item;
|
||||
ItemP->String = Map.WriteString(S,Size);
|
||||
if (ItemP->String == 0)
|
||||
return 0;
|
||||
|
||||
Bucket = ItemP;
|
||||
return ItemP->String;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user