0.3.19cnc55-alt3

- Added librpm-4.0.4 build support.
- Built with librpm-4.0.4, updated buildrequires.
This commit is contained in:
Дмитрий Левин 2002-03-27 15:18:37 +00:00
commit e3ad0ef694
367 changed files with 71211 additions and 0 deletions

4
.gear-rules Normal file
View File

@ -0,0 +1,4 @@
copy: *.conf
copy: *.patch
tar.bz2: apt
copy: rpmpriorities

View 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)
{

View 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@

View 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>

View 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],

View 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

View 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");
}

View 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;

View 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();

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1 @@
rapt

1
apt/CVS/Root Normal file
View File

@ -0,0 +1 @@
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs

1780
apt/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

28
apt/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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//

View File

@ -0,0 +1 @@
rapt/apt-pkg

1
apt/apt-pkg/CVS/Root Normal file
View File

@ -0,0 +1 @@
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs

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
View 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

View 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)
{
}
/*}}}*/

View 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

View 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();
}
/*}}}*/

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

113
apt/apt-pkg/algorithms.h Normal file
View 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
View 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
View 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

View 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
View 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
View 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

View File

@ -0,0 +1 @@
D

View File

@ -0,0 +1 @@
rapt/apt-pkg/cnc

1
apt/apt-pkg/cnc/CVS/Root Normal file
View File

@ -0,0 +1 @@
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs

View 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

View File

@ -0,0 +1 @@
rapt/apt-pkg/contrib

View File

@ -0,0 +1 @@
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs

View 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;
}
/*}}}*/

View 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

View 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;
}
/*}}}*/

View 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

View 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;
}
/*}}}*/

View 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

View 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;
}

View 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

View 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;
}
/*}}}*/

View 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

View 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;
}
/*}}}*/

View 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

View 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
View 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
View 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
View 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
View 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

View 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);
}
/*}}}*/

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View File

@ -0,0 +1 @@
rapt/apt-pkg/deb

1
apt/apt-pkg/deb/CVS/Root Normal file
View File

@ -0,0 +1 @@
:pserver:anonymous@cvs.conectiva.com.br:/home/cvs

View 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;
}
/*}}}*/

View 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

View 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();
}
/*}}}*/

View 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

View 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);
}
/*}}}*/

View 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

View 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;
}
/*}}}*/

View 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
View 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;
}
/*}}}*/

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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;
}
/*}}}*/

View 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
View 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
View 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 &Map;
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
View 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