summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Stubbs <jstubbs@gentoo.org>2005-08-28 08:37:44 +0000
committerJason Stubbs <jstubbs@gentoo.org>2005-08-28 08:37:44 +0000
commitd9fc4acc572c6647a4f27b838d35d27d805d190e (patch)
tree262a8de35d8c7567312757da5f1f66efdc8cece5
downloadportage-idfetch-d9fc4acc572c6647a4f27b838d35d27d805d190e.tar.gz
portage-idfetch-d9fc4acc572c6647a4f27b838d35d27d805d190e.tar.bz2
portage-idfetch-d9fc4acc572c6647a4f27b838d35d27d805d190e.zip
Migration (without history) of the current stable line to subversion.
svn path=/main/branches/2.0/; revision=1941
-rw-r--r--ChangeLog3076
-rw-r--r--ChangeLog.0004288
-rw-r--r--TODO60
-rwxr-xr-xbin/archive-conf101
-rwxr-xr-xbin/chkcontents62
-rwxr-xr-xbin/clean_locks36
-rwxr-xr-xbin/dispatch-conf311
-rwxr-xr-xbin/dobin28
-rwxr-xr-xbin/doconfd15
-rwxr-xr-xbin/dodir8
-rwxr-xr-xbin/dodoc23
-rwxr-xr-xbin/doenvd15
-rwxr-xr-xbin/doexe26
-rwxr-xr-xbin/dohard13
-rwxr-xr-xbin/dohtml159
-rwxr-xr-xbin/doinfo21
-rwxr-xr-xbin/doinitd15
-rwxr-xr-xbin/doins53
-rwxr-xr-xbin/dojar54
-rwxr-xr-xbin/dolib41
-rwxr-xr-xbin/dolib.a7
-rwxr-xr-xbin/dolib.so7
-rwxr-xr-xbin/doman52
-rwxr-xr-xbin/domo26
-rwxr-xr-xbin/dopython23
-rwxr-xr-xbin/dosbin27
-rwxr-xr-xbin/dosed22
-rwxr-xr-xbin/dosym13
-rwxr-xr-xbin/ebuild61
-rwxr-xr-xbin/ebuild.sh1868
-rwxr-xr-xbin/emake14
-rwxr-xr-xbin/emerge3213
-rwxr-xr-xbin/emerge-webrsync141
-rwxr-xr-xbin/emerge.orig3227
-rwxr-xr-xbin/env-update11
-rwxr-xr-xbin/env-update.sh221
-rwxr-xr-xbin/etc-update407
-rwxr-xr-xbin/find-requires44
-rwxr-xr-xbin/fix-db.py175
-rwxr-xr-xbin/fixdbentries20
-rwxr-xr-xbin/fixpackages14
-rwxr-xr-xbin/fowners15
-rwxr-xr-xbin/fperms15
-rwxr-xr-xbin/md5check.py102
-rwxr-xr-xbin/md5check.sh31
-rwxr-xr-xbin/mirror.py167
-rwxr-xr-xbin/newbin13
-rwxr-xr-xbin/newconfd13
-rwxr-xr-xbin/newdoc13
-rwxr-xr-xbin/newenvd13
-rwxr-xr-xbin/newexe13
-rwxr-xr-xbin/newinitd13
-rwxr-xr-xbin/newins13
-rwxr-xr-xbin/newlib.a13
-rwxr-xr-xbin/newlib.so13
-rwxr-xr-xbin/newman13
-rwxr-xr-xbin/newsbin13
-rwxr-xr-xbin/pemerge.py44
-rwxr-xr-xbin/pkgmerge59
-rwxr-xr-xbin/pkgmerge.new84
-rwxr-xr-xbin/pkgname17
-rwxr-xr-xbin/portage_gpg_update.sh6
-rwxr-xr-xbin/portageq256
-rwxr-xr-xbin/prepall39
-rwxr-xr-xbin/prepalldocs33
-rwxr-xr-xbin/prepallinfo9
-rwxr-xr-xbin/prepallman12
-rwxr-xr-xbin/prepallstrip11
-rwxr-xr-xbin/prepinfo45
-rwxr-xr-xbin/preplib25
-rwxr-xr-xbin/preplib.so10
-rwxr-xr-xbin/prepman46
-rwxr-xr-xbin/prepstrip48
-rwxr-xr-xbin/quickpkg148
-rwxr-xr-xbin/regenworld93
-rwxr-xr-xbin/repoman1522
-rwxr-xr-xbin/xpak14
-rw-r--r--cnf/dispatch-conf.conf36
-rw-r--r--cnf/etc-update.conf71
-rw-r--r--cnf/make.conf319
-rw-r--r--cnf/make.conf.alpha305
-rw-r--r--cnf/make.conf.amd64316
-rw-r--r--cnf/make.conf.arm313
-rw-r--r--cnf/make.conf.hppa322
-rw-r--r--cnf/make.conf.ia64284
-rw-r--r--cnf/make.conf.mac6
-rw-r--r--cnf/make.conf.mips302
-rw-r--r--cnf/make.conf.ppc335
-rw-r--r--cnf/make.conf.ppc64320
-rw-r--r--cnf/make.conf.s390284
-rw-r--r--cnf/make.conf.sparc320
-rw-r--r--cnf/make.conf.x86319
-rw-r--r--cnf/make.conf.x86-fbsd310
-rw-r--r--cnf/make.globals67
-rwxr-xr-xmake-man-tarball.sh13
-rw-r--r--man/alternatives.eclass.559
-rw-r--r--man/check-kernel.eclass.553
-rw-r--r--man/check-reqs.eclass.555
-rw-r--r--man/cvs.eclass.580
-rw-r--r--man/dispatch-conf.193
-rw-r--r--man/distutils.eclass.539
-rw-r--r--man/ebook.eclass.575
-rw-r--r--man/ebuild.1184
-rw-r--r--man/ebuild.5837
-rw-r--r--man/emerge.1555
-rw-r--r--man/env-update.128
-rw-r--r--man/etc-update.140
-rw-r--r--man/eutils.eclass.5176
-rw-r--r--man/fixheadtails.eclass.532
-rw-r--r--man/flag-o-matic.eclass.584
-rw-r--r--man/font.eclass.564
-rw-r--r--man/fortran.eclass.553
-rw-r--r--man/games.eclass.5119
-rw-r--r--man/horde.eclass.551
-rw-r--r--man/libtool.eclass.548
-rw-r--r--man/make.conf.5395
-rw-r--r--man/perl-module.eclass.566
-rw-r--r--man/portage.5588
-rw-r--r--man/python.eclass.582
-rw-r--r--man/quickpkg.156
-rw-r--r--man/repoman.1127
-rw-r--r--man/rpm.eclass.537
-rw-r--r--man/ruby.eclass.547
-rw-r--r--man/ssl-cert.eclass.554
-rw-r--r--man/stardict.eclass.534
-rw-r--r--man/subversion.eclass.559
-rw-r--r--man/tla.eclass.552
-rw-r--r--man/toolchain-funcs.eclass.5112
-rw-r--r--man/versionator.eclass.553
-rw-r--r--man/vim-plugin.eclass.586
-rw-r--r--man/vim.eclass.556
-rw-r--r--pym/cvstree.py295
-rw-r--r--pym/dcdialog.py412
-rw-r--r--pym/dispatch_conf.py162
-rw-r--r--pym/emergehelp.py370
-rw-r--r--pym/getbinpkg.py541
-rw-r--r--pym/output.py167
-rw-r--r--pym/portage.py7452
-rw-r--r--pym/portage.py.orig7427
-rw-r--r--pym/portage_checksum.py134
-rw-r--r--pym/portage_const.py48
-rw-r--r--pym/portage_contents.py161
-rw-r--r--pym/portage_data.py85
-rw-r--r--pym/portage_db_anydbm.py64
-rw-r--r--pym/portage_db_cpickle.py79
-rw-r--r--pym/portage_db_flat.py113
-rw-r--r--pym/portage_db_template.py174
-rw-r--r--pym/portage_db_test.py21
-rw-r--r--pym/portage_dep.py155
-rw-r--r--pym/portage_exception.py163
-rw-r--r--pym/portage_exec.py215
-rw-r--r--pym/portage_file.py62
-rw-r--r--pym/portage_gpg.py149
-rw-r--r--pym/portage_localization.py21
-rw-r--r--pym/portage_locks.py360
-rw-r--r--pym/portage_util.py459
-rw-r--r--pym/xpak.py384
-rw-r--r--qa/iuse/iuse.sh20
-rwxr-xr-xqa/iuse/iuse2.py58
-rwxr-xr-xspec/emerge.syntax1149
-rw-r--r--src/bsd-flags/PKG-INFO10
-rw-r--r--src/bsd-flags/chflags.c161
-rw-r--r--src/bsd-flags/setup.cfg6
-rwxr-xr-xsrc/bsd-flags/setup.py24
-rw-r--r--src/python-missingos/ChangeLog16
-rw-r--r--src/python-missingos/PKG-INFO10
-rw-r--r--src/python-missingos/README15
-rw-r--r--src/python-missingos/missingos.c120
-rw-r--r--src/python-missingos/setup.cfg8
-rwxr-xr-xsrc/python-missingos/setup.py24
-rw-r--r--src/sandbox-1.1/ChangeLog265
-rw-r--r--src/sandbox-1.1/Makefile81
-rw-r--r--src/sandbox-1.1/canonicalize.c173
-rwxr-xr-xsrc/sandbox-1.1/create-localdecls115
-rw-r--r--src/sandbox-1.1/getcwd.c511
-rw-r--r--src/sandbox-1.1/libctest.c7
-rw-r--r--src/sandbox-1.1/libsandbox.c1383
-rw-r--r--src/sandbox-1.1/sandbox.bashrc8
-rw-r--r--src/sandbox-1.1/sandbox.c863
-rw-r--r--src/sandbox-1.1/sandbox.h68
-rw-r--r--src/sandbox-1.1/sandbox_futils.c513
-rw-r--r--src/sandbox-dev/ChangeLog91
-rw-r--r--src/sandbox-dev/Makefile62
-rw-r--r--src/sandbox-dev/canonicalize.c194
-rwxr-xr-xsrc/sandbox-dev/create-localdecls95
-rw-r--r--src/sandbox-dev/libctest.c6
-rw-r--r--src/sandbox-dev/libsandbox.c1214
-rw-r--r--src/sandbox-dev/sandbox.bashrc8
-rw-r--r--src/sandbox-dev/sandbox.c816
-rw-r--r--src/sandbox-dev/sandbox.h69
-rw-r--r--src/sandbox-dev/sandbox_futils.c352
-rw-r--r--src/sandbox/Makefile30
-rw-r--r--src/sandbox/libsandbox.c873
-rw-r--r--src/sandbox/problems/Makefile31
-rw-r--r--src/sandbox/problems/libsandbox_emacsbug.c34
-rw-r--r--src/sandbox/problems/libsandbox_muttbug.c24
-rw-r--r--src/sandbox/problems/sandbox_dev_fd_foo.c42
-rw-r--r--src/sandbox/problems/sandbox_muttbug.c43
-rw-r--r--src/sandbox/sandbox.bashrc8
-rw-r--r--src/sandbox/sandbox.c921
-rw-r--r--src/tbz2tool.c228
-rwxr-xr-xtabcheck.py6
-rwxr-xr-xtarball.sh58
203 files changed, 60349 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 00000000..bc90eadc
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3076 @@
+# ChangeLog for Portage; the Gentoo Linux ports system
+# Copyright 1999-2005 Gentoo Foundation; Distributed under the GPL v2
+# $Id: ChangeLog,v 1.796.2.146 2005/08/20 17:24:30 jstubbs Exp $
+
+ MAJOR CHANGES in 2.0.51:
+ 1. /var/cache/edb/virtuals is no longer used at all. It's calculated now.
+ 2. /var/cache/edb/world is now /var/lib/portage/world.
+ 3. /etc/portage/profile/virtuals is _USER_ configs only.
+
+ 21 Aug 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Skip protecting
+ ownership of symlinks. Patch by truedfx #94199
+
+ 14 Aug 2005; Mike Frysinger <vapier@gentoo.org> bin/prepstrip:
+ Don't try to strip if `file` failed #102499 by Daniel Drake.
+
+ 10 Aug 2005; Mike Frysinger <vapier@gentoo.org> bin/quickpkg:
+ Call gawk instead of awk so non-GNU systems work #102050 by Stephen Bennett.
+ Also clean up the script a bit.
+
+ 08 Aug 2005; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh:
+ fixed bug #101035 , basically checking pipestatus during unpack for
+ piped unpacks.
+
+ 07 Aug 2005; Mike Frysinger <vapier@gentoo.org> bin/ebuild.sh:
+ Add support for unpacking rar archives.
+
+ 04 Aug 2005; Brian Harring <ferringb@gentoo.org> bin/emerge:
+ bug 64585, sanity check on cache cleansing.
+
+ 04 Aug 2005: Brian Harring <ferringb@gentoo.org> bin/emerge:
+ It's not perfect, but a fix for bug #96410. A better fix would be
+ to get the categories limiter out of settings...
+
+ 29 Jul 2005; Mike Frysinger <vapier@gentoo.org> bin/doman:
+ Back port from portage HEAD:
+ Remove old unused options (-x11/-gnome/-kde/etc...) and cleanup.
+
+ 04 Jul 2005; Mike Frysinger <vapier@gentoo.org>
+ bin/ebuild-default-functions.sh:
+ Fix gnuconfig find expression #93363 by TGL.
+
+ 23 Jun 2005; Mike Frysinger <vapier@gentoo.org>
+ bin/ebuild-default-functions.sh:
+ Update the scanelf RUNPATH check to abort on null paths.
+
+ 17 Jun 2005; Mike Frysinger <vapier@gentoo.org> bin/repoman:
+ Report exit status if gpg failed to return with 0.
+
+ 14 Jun 2005; Marius Mauch <genone@gentoo.org> man/portage.5:
+ Remove references to non-existant $PORTDIR/profiles/use.mask and revert
+ the "fix" for bug 87173.
+
+ 13 Jun 2005; Mike Frysinger <vapier@gentoo.org> bin/ebuild.sh:
+ Use the %p output modifier instead of %F so we don't have to update the
+ output by removing all the $D references.
+
+ 29 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Made
+ /etc/profile.env sourced regardless of USERLAND. Made copying of config.sub
+ and config.guess --force'd as they are sometimes u-w. Replaced a if/else of
+ chgrp root/wheel with chgrp 0.
+
+ 29 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Moved the system
+ package unmerge check after slots are checked and removed the countdown for
+ when --ask is specified. Added a chdir to the removal of old cache call so
+ that there are no errors due to userpriv and being in a non-portage-readable
+ directory.
+
+ 29 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/etc-update: Moved the
+ temporary work dir from /tmp/$$ to ${PORTAGE_TMPDIR}/$$.
+
+ 29 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/prepinfo bin/prepman:
+ Reordered the -{min,max}depth and -name arguments to find so that warnings
+ are not produced.
+
+ 29 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added support
+ for FreeBSD's ldconfig. Fixed an incorrect chown of BUILD_PREFIX instead of
+ PORT_LOGDIR.
+
+ 29 May 2005; Mike Frysinger <vapier@gentoo.org> bin/ebuild.sh bin/prepstrip:
+ Backport scanelf QA checks from HEAD.
+
+ 25 May 2005; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh: Bug 93293,
+ die + stat_perms issues. Tweaked do_stat definition so it's one time instead
+ of ongoing also.
+
+ 19 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Disabled
+ userpriv as a user globally instead of only in fetch.
+
+ 19 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emake: Made the
+ make command configurable but defaulted to "make".
+
+ 19 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Fixed an
+ issue that would cause binary package reinstalls when IUSE disagreed.
+
+ 19 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Fixed an
+ issue where the portage version wasn't appended to the commit message
+ when specified on the command line. Fixed the detection of files above
+ the package level during Manifest generation.
+
+ 19 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Renamed
+ the userpriv FEATURE to userfetch for the fetch() phase and fixed a bug
+ where privileges would try to be dropped even as non-root. Fixed a bug
+ where files were attempted to be fetched when only a manifest recreation
+ is requested.
+
+ 17 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Stopped
+ attempting to fetch files when only the manifest is being generated.
+
+*portage-2.0.51.22 (15 May 2005): Maintainence Release
+
+ 15 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/dodoc: Removed the dodoc
+ new testing features from head's version of dodoc.
+
+ 15 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Made --newuse
+ take priority over --usepkg.
+
+ 15 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Added HOMEPAGE
+ to the list of vars that must be defined. Restored detection of the
+ digest.partial check. Made a commit message required.
+
+ 15 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed the
+ definition of PYTHONPATH in env_update(). Fixed the handling of quotes in
+ env_update().
+
+ 13 May 2005; Jason Stubbs <jstubbs@gentoo.org> cnf/dispatch-conf.conf
+ bin/dispatch-conf: Removed the pager config option and made if part of the
+ diff command option.
+
+ 13 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/dodoc: Backported vapier's
+ fix for 0-byte files causing a spurious "file not found" error.
+
+ 13 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Remove --verbose
+ and --tree from options when using --resume as the combination is currently
+ broken.
+
+ 13 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Added three new
+ checks on ebuild's PROVIDEs. Optimized out a lot of unnecessary aux_get()
+ calls. Modified to commit an unsigned Manifest before committing the signed
+ one to help ensure broken digests don't make it to rsync.
+
+ 13 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added SCCS to
+ the list of directories to ignore when ignorecvs is set in cacheddir. Drop
+ priveleges during fetch when userpriv is set. Added message display when
+ changing permissions on ccache dirs.
+
+ 06 May 2005; Brian Harring <ferringb@gentoo.org> bin/ebuild: fix portage_util
+ import on osx.
+
+ 05 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/etc-update: Fixed the
+ regex and added locale overrides to the use of cut as per bug #91159.
+
+ 05 May 2005; Jason Stubbs <jstubbs@gentoo.org> cnf/make.globals: Made
+ CONFIG_PROTECT default to /etc only as packages are augmenting it via env.d
+ where necessary.
+
+ 05 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Reverted deletion
+ of apparently unused code as it was being used in the case of --noreplace.
+
+ 04 May 2005; Marius Mauch <genone@gentoo.org> bin/g-cpan.pl, man/g-cpan.pl.1:
+ removed g-cpan.pl as it's now a standalone tool.
+
+ 02 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added back
+ support for ~* and * in package.keywords as it got dropped at some point.
+
+*portage-2.0.51.21 (01 May 2005): Maintainence Release
+
+ 01 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Fixed an
+ inverse logic bug in the setting of ccache size.
+
+ 01 May 2005; Jason Stubbs <jstubbs@gentoo.org>: Removed g-cpan.pl as it
+ is now maintained externally. Removed other old and/or unmaintained
+ scripts.
+
+ 01 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Dropped
+ confmem from 16 previous files down to 1 previous file so that upgrading
+ and downgrading behaves in terms of config files.
+
+ 01 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added
+ checking of overlays for package.mask, categories and others.
+
+ 01 May 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Skip testing
+ if has already been performed (indicated by .tested)
+
+ 01 May 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Removed
+ debugging information and added a fix for merging a symlink to a
+ directory over a file.
+
+ 01 May 2005; Jason Stubbs <jstubbs@gentoo.org> cnf/make.globals: Added
+ a basic CONFIG_PROTECT setting for those users who use only binary
+ packages and don't have a portage tree.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/doman: Added Mike's
+ patch to broaden the accepted man pages from [1-8n] to [0-9n](|f|p|pm)
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge pym/portage.py:
+ Added an implementation for the emerge config action and a supporting
+ method findname on the vardbapi class.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> man/portage.5: Removed
+ invalid example from portage.keywords.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Drop privs
+ when doing cache cleansing after syncing.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed
+ several issues with userpriv.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Made the
+ autoconfig feature non-optional.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Removed
+ running of depscan.sh from env-update.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Applied
+ solar's patches from bug #90720 that allow most ebuild operations to work
+ as any user in the portage group.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed a bug
+ that would cause an empty CBUILD to be defined if CHOST is not defined.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> cnf/make.globals.*: Removed
+ the now deprecated arch-specific make.globals files.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/dispatch-conf
+ pym/dispatch-conf.py: Fixed a typo with the added merge option. Added
+ hard-coded default merge option so that dispatch-conf can be used to do
+ a line by line of dispatch-conf.conf.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Updated econf
+ to use LOCAL_EXTRA_ECONF rather than EXTRA_ECONF directly, as noted by
+ eradicator. Removed the forced resizing of ccache when CCACHE_SIZE is
+ undefined.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Fixed bug in
+ --info during sorting when two versions have only differing -r component.
+ Ported Brian's regen method to --metadata for faster updates.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Fixed an
+ off-by-one indexing into a list during scanning for Manfiest commits.
+
+ 29 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed a bug
+ in the checking of whether sandbox is usable when usersandbox is enabled.
+ Combined u+w and g+w mods on ccache dir into the one exec. Added missing g+s
+ mods on ccache dir, which was causing mods at each check. Moved mtime check
+ in aux_get so that it applies to updating from the metadata cache as well.
+ Relocated the fix for mynewcat outside of the loop to prevent needless
+ re-calculation. Added debugging code for bug #71787.
+
+ 24 Apr 2005; Masatomo Nakano <nakano@gentoo.org> pym/portage.py
+ Fixed undefined value causing traceback when moving package in binarytree.
+
+*portage-2.0.51.20 (23 Apr 2005): Maintainence Release
+
+ 23 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage_const.py:
+ Adjusted sandbox path to match the external sandbox.
+
+ 23 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Added a 3 second
+ delay after a failed Manifest commit. Fixed bug where files at the category
+ level were being treated as packages.
+
+ 23 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py portage_util.py
+ portage_db_cpickle.py: Replaced HIGHEST_PROTOCOL with it's equivalent -1 to
+ ensure python-2.2 compatibility. Added back ChangeLog and metadata.xml to
+ Manifest generation for portage compatibility.
+
+ 21 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Adding
+ setting of CBUILD to CHOST if it is not set. Fixed getmaskingstatus to
+ choose an arch-based keyword over -*.
+
+ 21 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Removed
+ stale code from dyn_setup.
+
+ 19 Apr 2005; Brian Harring <ferringb@gentoo.org> pym/portage_db_flat.py:
+ Correction for string method name, again, danke to swegener.
+
+ 19 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild: Added a missing
+ import of portage_util.
+
+ 19 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed my
+ assumption that ChangeLog and metadata.xml will exist during digest creation.
+
+ 17 Apr 2005; Brian Harring <ferringb@gentoo.org> pym/portage.py: eclass cache
+ touche up, mtime wasn't being properly checked (thanks to swegener for catching
+ it).
+
+ 17 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage_exec.py
+ pym/portage.py: Added checks to see if the sandbox is executable and disabled
+ when it isn't.
+
+ 17 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/dispatch-conf
+ cnf/dispatch-conf.conf pym/dispatch-conf.py: Made the merge command
+ configurable. Fixed a bug that caused conflicts to make their way into the
+ final configuration file. Made the config archive dir automatically created
+ if there is nothing in the way.
+
+ 17 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/output.py: Reverted the
+ feature to make use of screen titles.
+
+ 17 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Made detection
+ of --ask capability use stdin instead of stdout.
+
+ 15 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Removed
+ ChangeLog and metadata.xml from Manifest creation and checking. Quietened
+ failed mtimedb writes. Added patch to allow fetching to read-only DISTDIR.
+ Added logic to detect changing between userpriv and non-userpriv and
+ update the ccache permissions at each change.
+
+ 15 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> cnf/make.globals*: Removed
+ vars not directly related to portage. Architecture specific ones are going
+ into the relevant profiles. USE_ORDER and CONFIG_PROTECT* will likely be
+ going into base.
+
+ 14 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Applied
+ patch from #69763 to allow fetching to a read-only distfiles dir.
+
+ 13 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Downgraded
+ the nesteddie check to a warning as it sometimes has false positives.
+
+ 13 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> cnf/make.conf*: Removed
+ size estimation of PORTDIR.
+
+ 13 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added
+ verification of package.provided contents. Fixed a bug with an incorrect
+ error on binary package category moves. Fixed a small bug that would
+ cause a crash on an invalid PRELINK_PATH_MASK. Added signal handling of
+ SIGPIPE. Added deep fixing of permissions on CCACHE_DIR when changing
+ between userpriv states.
+
+ 13 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Added sorting to
+ versions listed in emerge info output.
+
+ 13 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> man/emerge.1: Removed --inject
+ documentation.
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Added --nocolor
+ option courtesy of Jason Cooper on gentoo-user@g.o.
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Fixed the date
+ parsing of repoman to allow ranged and single years beginning 1999. #85242
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added
+ pusedict optimization. #85786
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Fixed emerge to
+ always add packages to world unless --oneshot is specified.
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/dispatch-conf:
+ Replaced shutil.movefile() calls for python-2.2 compatibility.
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/portageq pym/portage.py:
+ Utilized PORTAGE_CALLER to only print profile deprecation noticies when
+ emerge first starts up.
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman:
+ Limited digest.assumed and ebuild.allmasked (by default) to scans at
+ the package level only. Removed IUSE from required variables. Fixed
+ duplicate reporting of required variables. Adjusted size limit of
+ files/* to 20480 bytes. Fixed allmasked check. Removed reinitialization
+ of each profile at every usage.
+
+ 12 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed
+ spelling error. Removed code from portdbapi.gvisible that was only
+ utilized by repoman's (broken) allmasked check.
+
+ 03 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Modified to
+ ignore blockers when using --buildpkgonly.
+
+ 02 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py:
+ Made autouse calculated only at import time to ensure that use flags
+ from dep calculation are the same as those used at build time.
+
+ 02 Apr 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage_dep.py:
+ Fixed a bug where a return type was a tuple instead of a list in
+ paren_reduce().
+
+ 23 Mar 2005; Jason Stubbs <jstubbs@gentoo.org> bin/dispatch-conf:
+ Removed the -a argument from all diff usage.
+
+ 08 Mar 2005; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Tweak to ensure restrict is dumped to the env, with PORTAGE_RESTRICT
+ being dumped also.
+
+ 06 Mar 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Added a check
+ to make sure the file exists before working with it, when called with an
+ ebuild path. #84102
+
+*portage-2.0.51.19 (04 Mar 2005): Maintainence Release
+
+ 02 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixing
+ ferringb's fix by adding the full scope of normpath.
+
+ 02 Mar 2005; Nicholas Jones <carpaski@gentoo.org> pemerge.py: Add it back
+ since I seem to have removed it by changing/refreshing dirs at some point.
+
+ 01 Mar 2005; Brian Harring <ferringb@gentoo.org> pym/portage.py: bug 83712,
+ a lovely normalized path bug in eclass_cache resulting in false positives on
+ eclass cache staleness...
+
+ 01 Mar 2005; Brian Harring <ferringb@gentoo.org> bin/prepman: bug 83704,
+ prepman getting stupid about gzip'ing already bzip2'd man pages.
+
+ 01 Mar 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Expanded
+ syslist during the unmerge phase so that all packages listed in system
+ are correctly checked and warned against. #83670
+
+*portage-2.0.51.18 (28 Feb 2005): Maintainence Release
+
+ 28 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added a
+ -* to updated FEATURES before saving back to the env. #79566
+
+ 27 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added back
+ sorting of the final list from portdbapi.cp_all() so that emerge regen
+ is ordered correctly.
+
+*portage-2.0.51.17 (26 Feb 2005): Maintainence Release
+
+ 26 Feb 2005; Nicholas Jones <carpaski@gentoo.org> *: Darwin userland patch
+ from Kito (bug 82312). Adjusted a couple bits like the file was installed
+ with message and etc-update's USERLAND check per Jason suggestion.
+
+ 26 Feb 2005; Nicholas Jones <carpaski@gentoo.org> portage_data.py: Added
+ the 'gnu' suffix check for the BSD/GNU people. (bug 80018)
+
+ 26 Feb 2005; Nicholas Jones <carpaski@gentoo.org> pym/xpak.py: Added in a
+ method to get both the data and index segments for use with the other memory
+ based functions.
+
+ 21 Feb 2005; Brian Harring <ferringb@gentoo.org> pym/portage.py: So yeah.
+ Don't fool with the eclass_cache.porttree ordering unless you understand that
+ it -must- match bash's inherit order (where overlays override portdir).
+
+ 15 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> emerge: Disabled the cache
+ update output when using --quiet. #81678
+
+ 15 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> make.conf*: Added
+ warning with regard to changing CHOST. #81007
+
+ 13 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> make.conf*: Added warning
+ with regard to changing PORTDIR and /etc/make.profile.
+
+ 13 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> portage.py: Fixed the global
+ features usage in the config class and made sure that any adjustments are
+ propogated back to the env.
+
+ 13 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> chflags.c: Replaced stat
+ call with an lstat call in lhasproblems as the calling code expects the
+ function to operate directly on symlinks.
+
+*portage-2.0.51.16 (06 Feb 2005): Maintainence Release + BSD chflags
+
+ 06 Feb 2005; Nicholas Jones <carpaski@gentoo.org> portage.py, src/chflags:
+ Addition of BSD chflags support (from spb@gentoo.org). Wrapped all the
+ calls within a check for the modules existance so we can reduce any problems
+ due to a failing or missing module. Internally renamed it bsd_chflags.
+
+ 06 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> bin/ebuild.sh: Completed
+ renaming of "maketest" to "test". RESTRICT supports both. #77446
+
+ 06 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> pym/output.py: Added checking
+ of whether stderr is a tty before changing xterm titles. #73824
+
+ 05 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Added removal of
+ --tree and --changelog upon a restart of emerge. Added --ask support to
+ emerge metadata.
+
+ 05 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Removed the
+ requisite that a profile must depend on ">=sys-apps/portage-2.0.51" to be
+ able to use package.mask.
+
+ 05 Feb 2005; Jason Stubbs <jstubbs@gentoo.org> bin/repoman pym/portage.py:
+ Removed the disabling of PORTDIR_OVERLAY from portage.py and added code to
+ repoman to set PORTDIR to the current directory's repo unless it doesn't
+ contain a profiles directory. If that is the case, PORTDIR is kept and
+ PORTDIR_OVERLAY is set to the current overlay -only-.
+
+ 03 Feb 2005; Brian Harring <ferringb@gentoo.org> pym/portage.py: bug 80506,
+ fixed RESTRICT="(no|)userpriv".
+
+ 31 Jan 2005; Brian Harring <ferringb@gentoo.org> pym/portage.py: Spanky pointed
+ a bug assuming the intermediate directories for WORLD_FILE existed already.
+
+ 30 Jan 2005; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh: Update from
+ eradicator, bug #75420. Multilib stuff. :)
+
+ 30 Jan 2005; Brian Harring <ferringb@gentoo.org> bin/prepman: Fixing bug
+ #79788. Some screwy syntax for a find call was screwing up gzip'ing of man
+ pages for osx boxes.
+
+ 30 Jan 2005; Jason Stubbs <jstubbs@gentoo.org> emerge emerge.1: Added short
+ -N option for --newuse. Moved virtuals updating for packages that are about
+ to be installed so that the update happens after the virtuals within that
+ package's direct dependencies are resolved. Made the blocking message
+ slightly easier to understand. Added a suggestion to run emerge with --newuse
+ before running depclean.
+
+ 30 Jan 2005; Jason Stubbs <jstubbs@gentoo.org> etc-update: Removed the
+ unsetting of various options that happens when using graphical mode.
+
+ 30 Jan 2005; Jason Stubbs <jstubbs@gentoo.org> quickpkg: Added -h and --help
+ options.
+
+ 30 Jan 2005; Jason Stubbs <jstubbs@gentoo.org> repoman: Added patch to call
+ xmllint directly on metadata.xml rather than piping it. This prevents the
+ need (and possible failure) to escape quote characters.
+
+ 30 Jan 2005; Jason Stubbs <jstubbs@gentoo.org> portage.py: Fixed a bug with
+ calculations using PRELINK_PATH_MASK where paths matching those in
+ PRELINK_PATH_MASK were not removed.
+
+ 28 Jan 2005; Brian Harring <ferringb@gentoo.org> portage_db_flat.py: removed
+ the portage_locks locking that was added, using a different strategy reliant
+ on rename. Basically, for a pull- you open the file. If that fails, then
+ the cache lacks that entry. If it succeeds, you do your stat calls (to get
+ mtime) against the -file handle-, via fstat. You can read from that inode
+ without issue, but do not assume that that inode is the still accessible via
+ another open call (it may've been updated since). Pushes are accomplished
+ via writing everything to a temp file, then renaming that file to the correct
+ name- chmod/chown/utime calls need to be done prior to the rename.
+ So, if a pull is ongoing while a push starts up and finishes, the pull still
+ is accessing the old cache entry- worst case scenario, it goes and reupdates
+ the cache entry. This is acceptable, since the overhead from using a seperate
+ lockfile is much more costly (in some cases, a difference of 3m to 20m).
+ Normal cases, roughly 13% improvement.
+
+ 24 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ fetch/nofetch RESTRICT bug introduced in -r14. Completely disable overlay
+ when calling from repoman.
+
+ 24 Jan 2005; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Test print out
+ fix.
+
+ 19 Jan 2005; Brian Harring <ferringb@gentoo.org> ebuild.sh: Quick change to
+ features=autoconfig, avoiding an extra subshell.
+
+*portage-2.0.51-r14 (15 Jan 2005): Stable Candidate
+
+ 18 Jan 2005; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Unset IFS
+ after entering the for loop for bashrc's. The IFS setting applies to the
+ source command and messes up the assumptions about bash scripts and IFS.
+
+ 18 Jan 2005; Jason Stubbs <jstubbs@gentoo.org> portage.py emerge-webrsync:
+ Fixed the bash syntax error in emerge-webrsync as per #77941. Fixed the
+ blocking virtuals bug as per #78201. Removed the warning about negations
+ and reapplied negations to profile virtuals.
+
+ 17 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage.py: Prevented
+ negations from applying in virtuals and provided a warning.
+
+ 16 Jan 2005; Nicholas Jones <carpaski@gentoo.org> repoman: Fix to match up
+ to the namespace changes in portage.
+
+ 16 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage.py: Patch from a
+ bug report on a traceback that occurs when re-digesting a file without any
+ distfiles but with a preexisting digest.
+
+ 16 Jan 2005; Nicholas Jones <carpaski@gentoo.org> *.py: Added a cvs_id_str
+ to each portage module so we can account for them easily. Added printing
+ of those versions on a 'emerge -d info'. Cleaned up the * imports in the
+ modules so there shouldn't be any namespace pollution left.
+
+*portage-2.0.51-r13 (15 Jan 2005): Testing for virtuals changes
+
+ 15 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage.py: Adjusted the
+ virtuals handling into an advanced for of what Jason started using promotion
+ instead of blanket settings. Removed the user_profile dir completely when
+ using repoman via a new user_profile_dir variable that is stored on creation.
+ Split the getvirtuals() call into two pieces so that setinst() can also
+ recreate the virtuals properly when modifying the vartree.
+
+ 15 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage_util.py: Modified
+ the stack_dictlist function to handle '-*' and do it in the proper order.
+
+ 13 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage.py, emerge:
+ Adjusted the version handling for portage so that we can use CVS versions
+ and ignore the restarts when using livecvsportage.
+
+ 13 Jan 2005; Nicholas Jones <carpaski@gentoo.org> repoman: Added the
+ portage/repoman version used to the commit messages.
+
+ 13 Jan 2005; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed the
+ reverse ordering of profile virtuals before installed virtuals stacking.
+ Turn a reference assignment into a copy to fix a bug where digesting would
+ not include files that were already fetched previously. Added information
+ about which package is causing an error to some aux_get() errors.
+
+*portage-2.0.51-r11 (13 Jan 2005): Cleanup
+
+ 13 Jan 2005; Nicholas Jones <carpaski@gentoo.org> cnf/*: Updates for the
+ OSUOSL -> distfiles.gentoo.org changeover. Addition of PORTAGE_TMPFS to
+ the config files.
+
+ 13 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for a
+ typo in the primaryuri index.
+
+*portage-2.0.51-r10 (11 Jan 2005): Cleanup
+
+ 12 Jan 2005; Nicholas Jones <carpaski@gentoo.org> repoman: Fixed the
+ namespace collision in the time module and calls.
+
+ 11 Jan 2005; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fixes for the
+ libdir patch -- libtool can't handle "usr//lib".
+
+ 10 Jan 2005; Nicholas Jones <carpaski@gentoo.org> portage.py: Made maketest
+ enable 'test' in features. Marked a couple more negative flags for restrict.
+ Made tmpfs checking a little smarter and let us enable /dev/shm by default.
+
+ 10 Jan 2005; Nicholas Jones <carpaski@gentoo.org> output.py: Fixed the
+ colors and overscore problems. Added a larger section and better code
+ for generating colors and effects -- Unused at the moment. Added a patch
+ that included screen title handling.
+
+ 10 Jan 2005; Nicholas Jones <carpaski@gentoo.org> repoman: Rewrite the
+ datetime code to use time.gmtime() instead so python2.2 works still.
+
+ 10 Jan 2005; Nicholas Jones <carpaski@gentoo.org> regenworld: Made it work
+ with cascade profiles by using the proper system reference.
+
+ 10 Jan 2005; Nicholas Jones <carpaski@gentoo.org> emerge: Fix for the gcc
+ hardened version printing. Moved the stdin close on rsync down below the
+ rsync part to allow --ask to work.
+
+ 10 Jan 2005; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Die if unpack
+ is not given any files to unpack. Modification for the no_inst stuff to be
+ less crazy with the echo redirection stuff.
+
+ 08 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> ebuild.sh: Moved the "true" to
+ the end of the dyn_clean() function.
+
+ 06 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> ebuild.sh: Added eradicator's
+ multilib-strict patch, which allows checking and failing if binaries are
+ about to be installed into an incorrect directory. The feature is configured
+ via the MUTLILIB_STRICT_DIRS and MULTILIB_STRICT_DENY and has no effect if
+ either they are not defined or the feature is not enabled.
+
+ 04 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> ebuild.sh: Added removal of
+ the .packaged and .tested files to the clean stage. Adjusted cleaning of the
+ temp dir to include the directory as well, rather than only the files
+ therein. Added a check and appropriate removal of the entire scratch dir if
+ it is empty at the end of the clean phase.
+
+ 04 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> portage.py: Turned the
+ primaryuri global counter into separate counters per file, so that urls
+ are inserted at the appropriate places.
+
+ 04 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> portage.py: Adjusted virtuals
+ stacking so that /etc/portage/virtuals is stacked on top of the profile
+ virtuals (including the custom /etc/portage/profile), reordered the list
+ of installed virtuals to match that of the combined profile virtuals and
+ then stacked the installed virtuals on top of those. Also added back the
+ deprecation notice.
+
+ 04 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> emerge: Added code to
+ "emerge info" to summarise variables that aren't set rather than hide them.
+
+ 02 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> dolib ebuild.sh preplib:
+ Applied eradicator's libdir patch for multilib support. #75420
+
+ 02 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> ebuild.sh: Added support for
+ INSTALL_MASK. #67190
+
+ 02 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> portage.py portage_util.py:
+ Added support for the "source" keyword to make.conf. #74842
+
+ 02 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> ebuild.sh: Adjusted autoconfig
+ to work on ${WORKDIR} instead of ${S} and modified output. #72360
+ Added notice on econf failure to include config.log (if it exists) into any
+ bug report. #75268 Don't prepend "/" to CONF_LIBDIR if it already begins
+ with "/" #75523
+
+ 02 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> emerge: Don't update info dirs
+ if noinfo FEATURE is enabled. #76378
+
+ 02 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> emerge: Set the processing of
+ profiles/info_vars to only include those which have been set to some value.
+ #75920
+
+ 02 Dec 2005; Jason Stubbs <jstubbs@gentoo.org> repoman: Modified header check
+ to use the year of the mtime of the ebuild rather than the current year.
+
+ 24 Dec 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Removed assumption
+ that /etc/make.profile/make.defaults must exist for configdict["defaults"] to
+ be populated (and thus ARCH prepended to USE).
+
+ 23 Dec 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Adjusted fetching
+ on digest creation such that any preexisting digest entries are used, but
+ fetching and digesting occurs for all SRC_URI entries otherwise.
+
+ 22 Dec 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Removed the
+ virtuals deprecation notice as the "preferred" location does not yet
+ provide the required behaviour.
+
+ 14 Dec 2004; Nicholas Jones <carpaski@gentoo.org> doins: Fix and notices
+ for $D handling.
+
+ 14 Dec 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: spb's chflags
+ adjustment for dyn_clean. stat_perms() overhaul for bsd and ppc.
+
+ 14 Dec 2004; Nicholas Jones <carpaski@gentoo.org> webrsync: TMPDIR is
+ used properly and a tar-failure fix.
+
+ 14 Dec 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: RESTRICT
+ changes -- nomirror and mirror are now the same (use 'mirror') -- lmirror
+ is a temporary way to sidestep mirror restrictions -- primaryuri makes
+ portage attempt to retrieve from the source mirror before falling back to
+ other mirrors (corrects behavior some impose for 'mirror').
+
+ 14 Dec 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_flat.py: Do
+ not fail when we're on a readonly FS and we're only reading (lockfiles).
+
+ 09 Dec 2004; Marius Mauch <genone@gentoo.org> bin/ebuild.sh:
+ change LDFLAGS to CFLAGS for the setXid check.
+
+ 05 Dec 2004; Nicholas Jones <carpaski@gentoo.org> pym/portage.py: swegener
+ made quite a find in portdbapi.cpv_exists, the comparison on the tuple
+ returned by findname2 always evaluated true.
+
+*portage-2.0.51-r8 (03 Dec 2004): Cleanup
+
+ 03 Dec 2004; Nicholas Jones <carpaski@gentoo.org> repoman: A patch to
+ handle stray digests.
+
+ 03 Dec 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Patches to
+ fix the matching bug #73136 and the '-atom' profile bug #73167.
+
+*portage-2.0.51-r7 (01 Dec 2004): Cleanup
+
+ 01 Dec 2004; Nicholas Jones <carpaski@gentoo.org> sandbox: updated with
+ ferringb's code for the pids file overrun issue.
+
+ 01 Dec 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Reverted repoman
+ profile selection to previous behaviour. Kept verbosity, but modified
+ messages according to the behaviour.
+
+*portage-2.0.51-r5/6 (30 Nov 2004): Cleanup
+
+ 29 Nov 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Added a
+ (backport?) missing return to treewalk.
+
+ 29 Nov 2004; Nicholas Jones <carpaski@gentoo.org> cnf/*: Removed the
+ prozilla references. Adjusted the default mirrors to a gentoo round-
+ robin.
+
+ 29 Nov 2004; Nicholas Jones <carpaski@gentoo.org> portage_exec.py: Modified
+ the magic constants to be os.access calls.
+
+ 29 Nov 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: A few XXX
+ comments. Removed 'aumtime' from the global space. Removed the virtuals
+ code that created an empty and unused virtuals file in /var/cache/edb.
+
+ 29 Nov 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Added a few XXX
+ comments to bad code/calls. Adjusted emerge info so that it can read more
+ variables and atoms to print out from the portage tree.
+
+ 29 Nov 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fixed/Backport
+ the changes to stat_perms so that it works. Fixed the read commands.
+
+ 10 Nov 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh:
+ dyn_install was attempting to be helpful and chown files owned
+ by portage, resulting in suid/sgid being stripped. bug #56129.
+
+ 07 Nov 2004; Brian Harring <ferringb@gentoo.org> portage.py: buggy
+ logic in listdir w/ ignorecvs, rewrote. (#70170).
+
+ 07 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> dispatch-conf: Moved back
+ to the version of dispatch-conf that was released (due to python-2.2
+ compatibility) and fixed a small type in that version. #70282
+
+*portage-2.0.51-r4 (05 Nov 2004): Internal Release
+
+ 05 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> doins: Added vapier's fix
+ for doins changing existing directory permissions. #69896
+
+ 04 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> tbz2tool.c: Added vapier's
+ fix for tbz2tool on ia64. #70001
+
+ 03 Nov 2004; Brian Harring <ferringb@gentoo.org> portage_dep.py: Bug in
+ paren_reduce where it was returning a tuple (supposed to return a list).
+
+ 03 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> dispatch-conf: Simplified
+ the temp file creation and usage.
+
+ 03 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Fixed issues
+ with PROVIDE calculation by flattening the dep array. #32114
+
+ 02 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Updated
+ ExtractKernelVersion() to support 2.6.9's new localversion. #67804
+ Reordered a cache update and a return statement so that the cache is
+ actually updated in ververify. #69523
+
+ 02 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> ebuild.sh: Turned off
+ shell option extglob as it interferes with the g++ QA interceptor. #69690
+
+ 02 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Fixed a bug
+ where a broken symlink blocking the installation of a regular file would
+ cause a traceback. #69672
+
+ 02 Nov 2004; Jason Stubbs <jstubbs@gentoo.org> quickpkg: Applied vapier's
+ fix for processing file names that contain spaces. #36997 Applied
+ vapier's fix for parallel quickpkg's writing to a single log file. #37270
+
+ 29 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Fixed issue where
+ emerge adds package to world when --onlydeps is specified. #69260
+ Fixed issue where emerge was adding packages to world when --uprade is
+ specified even if the package is already installed. #69287 Fixed logic
+ in path/to/ebuild check so that symlinks do not cause false positives.
+
+ 29 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> dispatch-conf: Added usata's
+ fix for mac-os compatibility. #69304
+
+ 29 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> getbinpkg.py: Reversed the
+ logic of ftp passive-mode selection. #69371
+
+ 29 Oct 2004; Brian Harring <ferringb@gentoo.org> portage.py: config.reset
+ was pruning vars out of backupenv on each reset call. #69388
+
+ 28 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emergehelp.py: Fixed up
+ some incorrect descriptions. Added documentation for new and changed
+ functionality. Removed documentation for deprecated options.
+
+ 28 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> getbinpkg.py: Added missing
+ substitution of ${FILE} in resume command. #69068
+
+ 28 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Fixed aux_get error
+ due to calling getfetchlist() when an ebuild no longer exists. #69051
+
+ 28 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Removed a duplicate
+ loop from the userquery function. #69020
+
+ 27 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> dispatch-conf: Moved temp file
+ creation into a safe directory under /tmp. Made the log file a configurable
+ option that is disabled by default.
+
+ 26 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Added a check to
+ portdbapi.fetchcheck to account for a missing digest.
+
+ 26 Oct 2004; Brian Harring <ferringb@gentoo.org> portage_exec.py, bin/ebuild:
+ bug with the path lookup code (added find_binary func for upcoming additions),
+ and bin/ebuild was bailing due to a missing portage_util import.
+
+ 25 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Wrapped entire
+ lock-holding section of fetch() in a try-finally to ensure that the lock
+ file gets released regardless of exception.
+
+ 25 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> etc-update: Added patch
+ from #48218 to continue on to next file when answering "no" to the
+ interactive replace prompt of menu option -3.
+
+ 25 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Fixed the space/tab
+ usage through the spinner_msgs definition. Removed COMPILER from emerge info
+ output.
+
+ 25 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Converted
+ config.pkeywordsdict from {atom:[keyword]} to {cp:{atom:[keyword]}} to
+ prevent a lot of unnecessary calculation.
+
+ 24 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Added a percentage
+ counter to the cache update phase based on patch from #68694
+
+ 24 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py:
+ s/macos/ppc-macos/ change.
+
+ 24 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage_locks.py
+ portage_db_flat.py: Fixed a couple of race conditions with regard to
+ stating files.
+
+ 23 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py portage_util.py:
+ Added syntax checking for package.mask, package.unmask and packages files.
+
+ 23 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> dohtml: Reimplemented the
+ option processing to remove the dependency on optparse.
+
+ 23 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Made the invalid
+ profile slightly more intelligable and got rid of the duplicate. Moved
+ the profile KEYWORDS.invalid failure so that it only occurs if the
+ corresponding KEYWORD is valid.
+
+ 23 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Added settings
+ parameter to dep_virtual as the virtuals can now change during dep graph
+ creation. #68220
+
+ 23 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Changed repoman to
+ use the first stable profile found for each arch listed in profiles.desc
+ rather than the last profile listed. Added notification on any invalid
+ profile in profiles.desc. Made exception into a repoman error where a
+ ebuild is using a keyword for which no profile can be found.
+
+ 23 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Fixed traceback in
+ repoman on invalid LICENSE syntax.
+
+ 22 Oct 2004; Brian Harring <ferringb@gentoo.org> ebuild.sh: silencing use/has.
+
+ 22 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Added python version
+ to "emerge info" output.
+
+*portage-2.0.51-r2 (20 Oct 2004): Everyone loves finding bugs in stable!
+
+ 20 Oct 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fixed the result
+ checking when ebuilds are called -- this removes the continuing-after failure
+ big discovered by AMD64 today.
+
+ 20 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Fixed a bug where
+ users were warned against emerging by path when a file/dir exists of the
+ same name of the package to be merged. #68372 Added an warning with delay
+ when emerging an ebuild that is masked. Added a check on PORTAGE_GPG_DIR
+ which removes "gpg" from FEATURES on an invalid settings. #68387
+
+*portage-2.0.51 (20 Oct 2004): Everyone loves stable!
+
+ 19 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage.5: patch included
+ to fix a few typos.
+
+ 19 Oct 2004; Nicholas Jones <carpaski@gentoo.org> g-cpan.pl patch included
+ that doesn't recreate inherently-created ebuilds.
+
+ 20 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Added check for
+ digest entries that aren't used within the corresponding ebuild's SRC_URI.
+
+ 20 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Added support for
+ EMERGE_WARNING_DELAY defaulting it to 10. Changed all the hardcoded delays
+ to use it. Needed for the catalyst guys as it includes a number of unmerges
+ of system packages.
+
+ 20 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Changed the
+ /path/to/ebuild warning. Added a check on what ebuild is chosen and
+ a failure if it doesn't match what was specified. Added the same for
+ /path/to/tbz2.
+
+*portage-2.0.51_rc10 (19 Oct 2004): Potential Final #1.
+
+ 19 Oct 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Visual acuity
+ enhancements. Fixed all the spaces in the option handling.
+
+ 19 Oct 2004; Nicholas Jones <carpaski@gentoo.org> emerge.1: Updated for
+ 'f' and 'S'.
+
+ 19 Oct 2004; Nicholas Jones <carpaski@gentoo.org> getbinpkg.py: Potential
+ fix for a missing dict key.
+
+ 19 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Prelink
+ tempfile per pid.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> *.py: Added a protocol
+ change for cPickles to make them more efficient (binary).
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> sandbox: Fixes for some
+ incorrect indexes that cause some boxes to have very random issues.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage_locks.py: Reverted
+ the lock code to the lockf()+hardlock version as the new code has some
+ inexplicable incompatibility with NFS.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage_exception.py: Added
+ a couple exceptions pretaining specifically to packages and digests.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage_checksum.py: Now
+ takes care of missing files better for the partial-digest handling.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed up some
+ of the output lines to use writemsg instead of print. Adjusted the fetch
+ code to handle partial-digests. digestCreate can substitute in old digest
+ entries now for missing files -- the assumption is that they are correct.
+ Portage no longer downloads all parts when FEATURES=cvs is enabled, but
+ does require a complete digest to commit, whether it was created piecewise
+ or en masse. Added 'fetch_check' to portdbapi which helps with with emerge's
+ pretend output for Fetch-Restriction.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Added in support
+ for partial-digests -- It complains, downloads, and adjusts. Sorted the QA
+ categories to make them easier to scan.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Added -F to force
+ all URIs to be downloaded. Added in a green, lowercase 'f' when the fetch
+ restriction is satisfied for pretend. Added Kevin Quinn's patch for some
+ prepstrip sanity and friendliness regarding TEXTRELs.
+
+ 18 Oct 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added a message
+ about use/useq/usev. CCACHE_DIR and CCACHE_SIZE are now properly exported.
+
+ 17 Oct 2004; <genone@gentoo.org> pym/portage.py:
+ Added a followSymlinks parameter to listdir() as otherwise it gets stuck in
+ an infinite loop when it encounters self-referencing symlinks, this behavior
+ was exhibited by the collision-protect feature.
+
+ 17 Oct 2004; Brian Harring <ferringb@gentoo.org> portage-locks.py: Tweaked
+ unlockfile, no point in attempting to relock the file for deletion, if you're
+ not deleting the lockfile (basically moved locking w/in if unlinkfile).
+
+ 17 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge portage_locks.py:
+ Added more information to the --inject deprecation notice. Removed the sleep
+ call from unlockfile as it severely affects performance (apparently only
+ under some schedulers)
+
+ 16 Oct 2004; Brian Harring <ferringb@gentoo.org> portage_locks.py: Corrected
+ a bug involving unlocking + lockf.
+
+ 12 Oct 2004; Brian Harring <ferringb@gentoo.org> portage_exec.py: spawn_sandbox
+ wasn't passing the opt_name down to spawn, it now does.
+
+ 11 Oct 2004; Jason Stubbs; <jstubbs@gentoo.org> emerge: Reverted back to
+ previous command line parsing code as --search options were being mishandled.
+
+ 11 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for the
+ SHA1 digest slipout and the exec missing/broken binary traceback.
+
+ 11 Oct 2004; Nicholas Jones <carpaski@gentoo.org> pym/*: See below.
+
+ 11 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> bin/*: Added catching and
+ propogating of SystemExit exception to all blanket exception handlers.
+
+ 11 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Fixed repoman LICENSE
+ check to accept || () conditions.
+
+*portage-2.0.51_rc8 (10 Oct 2004): RC + Lock cleanup, Happy RC #4
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Added in close()
+ calls to ensure that control-C gets intercepted by portage instead of the
+ children. Added in a re-raise for the SysExit exception inside of the
+ regen and metadata targets.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> cnf/make.conf*:
+ benno@nietvergeten.nl's touchups to make.conf files.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> sandbox/*: Includes one
+ of solar's patches to fix up potential holes in sandbox.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage_exec.py: Added
+ a cleanup routine.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: A could cwd
+ fixes and removed the compat-writing for digests.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> md5check/mirror: brought
+ them more up to date for the digest changes.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Moved the imports
+ around to ensure that portage.py gives output on failure instead of emerge
+ just dying. Added '-1' as a short for oneshot. Added shorter messages for
+ the titlebar. Fixed signal handling more -- Emerge sets up a handler that
+ calls to portageexit() before quitting normally.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Changed around
+ the tarvars to make them STAR friendly. Added ECONF_SOURCE as a way to move
+ econf out of the source directory and into a new build directory -- it
+ defines the path to configure, not the command. Added CTARGET support. Added
+ an rm for the infodir entries installed by autoconf so they don't kill what
+ portage regens and vice versa.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> doins: Added Spanky's
+ recursion patch.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> dolib: Added Spanky's
+ symlink fix and condensed dolib*.
+
+ 10 Oct 2004; Nicholas Jones <carpaski@gentoo.org> doman: Added Spanky's
+ i18n patch.
+
+ 08 Oct 2004; Brian Harring <ferringb@gentoo.org> portage_exec.py: Removed
+ the portage_exec.spawn_bash call for tee logging- instead, transferred in
+ some code that does path lookups (closer to the older portage.spawn call).
+ Path lookup by default is on, but can be disabled via path_lookup=False.
+
+ 08 Oct 2004; Brian Harring <ferringb@gentoo.org> portage_locks.py: Reverted
+ to using flock by default- if it fails (unavailable), -then- use lockf, then
+ hardlink.
+
+ 07 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Updated
+ portdbapi.getfetchsizes function for new digestParseFile return values.
+
+ 05 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> quickpkg: Fixed bug whereby
+ creating a package from within /var/db/pkg/cat and specifying pkg would
+ create a broken package.
+
+ 05 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Modified output for
+ slotted installations. #26139
+
+ 05 Oct 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Refactored argv
+ processing a little bit and made "emerge rsync" to emerge rsync with notice
+ and "emerge --rsync" to emerge --sync with notice.
+
+ 05 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage_util.py: grabfile
+ now handles a compat_level option for comment-based compatability changes --
+ This feature is for migration only and is thus transitory.
+
+ 05 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage_exception: Added
+ a DigestException which is a SignatureException.
+
+ 05 Oct 2004; Nicholas Jones <carpaski@gentoo.org> perform_checksum.py: Added
+ a perform_all() and verify_all() functions that handle the new dict of hashes
+ that digestParse returns -- It creates hashes for all the listed/known
+ formats or verifies them all returning a tuple of ok,reason.
+
+ 05 Oct 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Cleared up
+ a few system-package import-alls (stat,commands) -- If it breaks something,
+ they can fix their code -- They are standard modules. Removed the import
+ for select, as it appears nowhere in usage. Changed the portage_data import.
+ Added exithandler() back into usage, it was disabled -- Also corrected it's
+ handling. Unified the digest-parsing code and made it into an intelligable
+ dict instead of the fixed format. Merged digest functions and added SHA1
+ (arbitrary) handling in a new COMPAT mode using comments until we get the
+ handling transitioned into common usage. digestCreateLines() handles the
+ compatibility line values, and grabfile() has a compat-level handler.
+
+ 05 Oct 2004; Nicholas Jones <carpaski@gentoo.org> man/*: Random touchups.
+
+ 04 Oct 2004; <jstubbs@gentoo.org> pym/portage.py: Added fix for config
+ protection failure when destination is a symlink. #13007
+
+ 04 Oct 2004; <jstubbs@gentoo.org> bin/repoman: Added detection of multiple
+ overlays to repoman.
+
+ 04 Oct 2004; <jstubbs@gentoo.org> bin/repoman: Added repoman check
+ for DEPEND-syntax following LICENSEs.
+
+ 03 Oct 2004; <genone@gentoo.org> pym/emergehelp.py:
+ Add --metadata documentation to --help output.
+
+ 03 Oct 2004; <genone@gentoo.org> cnf/*, man/emerge.1, man/make.conf.5,
+ man/portage.5, pym/emergehelp.py:
+ Changed documentation to use --action instead of action (bug #2365).
+ Also changed ufed references in make.conf to use the correct category.
+
+*portage-2.0.51_rc7 (30 Sep 2004): RC + Lock cleanup, Happy RC #3
+
+ 30 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Rsync fix part 2
+ for the distfiles, local, and packages directory unlinks.
+
+ 30 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge-webrsync: Fix for
+ the missing md5sum causing failure to download. Fixed up a couple messages.
+ Modified the local rsync line.
+
+ 30 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Make more of
+ the chown calls friendly. More output on strange exceptions in aux_get.
+
+ 30 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_template.py:
+ Added some more putput to the corruption message.
+
+ 29 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> output.py: Added unicode-rxvt
+ to the list of legal term types. #65762
+
+ 28 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> etc-update: Added patch to
+ use gsed on BSD from bug 60721.
+
+*portage-2.0.51_rc6 (26 Sep 2004): RC + Lock cleanup, Happy RC #2
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Restart fix for
+ the -a into execv code.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_locks.py: Fixed
+ a traceback for Fat32 users.
+
+*portage-2.0.51_rc5 (26 Sep 2004): RC + Lock cleanup, Happy RC #1
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_data.py: Fixed
+ the BSD lchown issues.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Added the
+ selinux secure dirs patch.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Modified the
+ spinner again, --nospinner provides a basic ticker of one '.' per 100,
+ normal spinner is the twirly one, and the FEATURES=candy spinner is a
+ scrolly message.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_locks.py: Fixed it.
+ Discovered that the hardlocks were failing due to the creation of the lock
+ prior to the link operation which was due to the NFS fcntl lock failure.
+
+ 26 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Added
+ support for per profile package.mask. Included check of packages file
+ to ensure that the profile depends on an adequate portage version.
+
+*portage-2.0.51_rc4 (26 Sep 2004): RC + Lock cleanup
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> bin/clean_locks: A new
+ tool to aid in the maintainence of hardlock-based locks. It can clean
+ all locks from a directory or just the ones pertinent to the running host.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Updated the
+ spinner.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> cnf/*: Added distlocks
+ as a default feature. Added comments on distlocks and maketest and gpg.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_locks.py: Lots
+ of changes. Corrected the lockfile code to be an IOError. Added some
+ helper functions to reduce duplication in the hardlink code. Added a
+ callback to a cleanup function registered with atexit to ensure we clean
+ locks up on normal terminations. Fixed the code to actually work on most
+ NFS systems and hopefully have the fallback (INODE test) working on
+ very broken systems. Added a cleanup function that is interfaced through
+ the clean_locks script and the registered atexit call.
+
+*portage-2.0.51_rc3 (26 Sep 2004): And we have another Release Candidate!
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Modified the
+ spinner.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_flat.py: Fixed
+ a lockfile descriptor leak due to duplicated lock calls.
+
+ 26 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_lock.py: Added
+ more cleanup to the lockfile descriptors.
+
+*portage-2.0.51_rc2 (25 Sep 2004): And we have another Release Candidate!
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_flat.py: Fix
+ for typos.
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_locks.py: Changed
+ all the calls to lockf which wraps fcntl. Made the chown on the locks
+ optional -- if it fails, it'll be annoying, but there's a message. Added
+ code to perform the hardlink-shuffle which uses hardlinks as a locking
+ mechanism (NFSv2 needs this).
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_flat.py:
+ Added locking around the file creation to ensure atomicity.
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_localization.py:
+ A little spot to provide the '_' function and examples and future code.
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_file.py: Added
+ the module to contain file/directory functions that are useful. Additional
+ function 'makedirs' handles creation of directories with recursive perms.
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> getbinpkg.py: Fixed the
+ exception handling to not traceback.
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> etc-update: Typo fix.
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Caused the
+ binary metadata downloading to be a little more verbose. Fixed the
+ sync command's arguments so that it deletes top level files.
+
+ 25 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ Cretin's patch for prelink blacklists. Increased the verbosity of the
+ 'mylines' output to let people know what files are affected with nulls.
+ Added a workaround for a race condition that somehow exists inside of
+ auxget when there is heavy lockfile contention -- Must be a lockfile
+ cleanup issue.
+
+ 25 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Modified env_update
+ to always run ldconfig if makelinks is True, in order to ensure that
+ missing symlinks are created. Added logic to treewalk to check if package
+ is being downgraded and only run env_update with makelinks=False in that
+ case. (#54655)
+
+ 24 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Added the removal
+ of --ask from argv when restarting after an emerge of portage. (#47379)
+
+ 21 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> portage_util.py: Changed
+ varexpand to convert '\'-prepended newline chars to space rather than '\n'.
+
+ 21 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ bintree ebuild locating. Removed the virts_p debug/bug statements.
+
+ 21 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_checksum: Added
+ a fix for checksum tracebacks that tracebacked.
+
+ 21 Sep 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added more
+ variables to vardb.
+
+ 21 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> emerge: Added (slightly
+ modified) patch from bug 64682.
+
+ 16 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Modified
+ getmaskingstatus() to use settings.prevmaskdict rather than reading packages
+ directly in support of cascading profiles.
+
+*portage-2.0.51_rc1 (25 Sep 2004): And we have a Release Candidate!
+
+ 15 Sep 2004; Nicholas Jones <carpaski@gentoo.org> ebuild: On merge, disable
+ the noauto feature explicitly.
+
+ 15 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ 'missing ebuild' for uninstalls of packages not in the tree.
+
+ 15 Sep 2004; Nicholas Jones <carpaski@gentoo.org> man/*: Started adding
+ to the documentation in order to break it an make it look funny. Added a
+ couple entries for missing concepts like 'inherit' and 'useq' and 'hasq'.
+ Cleared up a few things here and there with usage. Added in the metadata
+ target for emerge.
+
+*portage-2.0.51_pre24 (14 Sep 2004): Last _pre before docs and rc/stable.
+
+ 14 Sep 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Extra handling
+ for weird CVS/Repository info on OSX.
+
+ 14 Sep 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fixed a traceback
+ in traceback handling where a value was trying to be extracted from an
+ exception. Handled the case where a binary package does not have an ebuild
+ in a tree or overlay and the verbose overlay output requires it. Change to
+ the CVS checkouts for emerge sync, moved the -P immediately after the co.
+
+ 14 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_exception.py:
+ Added in some spacing between related exception groups.
+
+ 14 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Changed a bunch
+ of lines unnecessarily to start getting the locale strings ready -- I'll
+ probably have bugs due to this because I've been doing dumb things like
+ that recently.
+
+ 14 Sep 2004; Nicholas Jones <carpaski@gentoo.org> man/*: Fixed ka0ttic's
+ email address.
+
+ 14 Sep 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh: Removed
+ the ${T}/successful logic, it's no longer needed. Existed only for the
+ $0 "$@" 2>&1 | tee $PORTAGE_LOG trickery, which is now handled via
+ portage_exec.spawn.
+
+ 13 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for empty
+ categories/portage-tree causing a traceback.
+
+*portage-2.0.51_pre23 (11 Sep 2004): Fixes and stuff.
+
+ 11 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Another fix
+ to the virtuals/use code -- It wasn't using treeVirtuals.
+
+*portage-2.0.51_pre22 (11 Sep 2004): Fixes and stuff.
+
+ 11 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Fixed breakage
+ in cacheddir changes upon stat'ing a broken symlink.
+
+ 11 Sep 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Fixed missing
+ check in autouse function. Fixed out-of-bounds exception on catpkgsplit
+ tuple access in vardbapi.move_ent. Changed to manual stat calls in cacheddir.
+
+ 10 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Removed the
+ circular deps of vardbapi and config.
+
+*portage-2.0.51_pre21 (09 Sep 2004): Fixes and stuff.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Possible fix
+ for autouse() that will prevent recursion and locks.
+
+*portage-2.0.51_pre210 (09 Sep 2004): (pre-pre release for 21)
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> archive-conf: Added patch
+ so that it runs.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> dispatch-conf: Added patch
+ to die when rcs isn't installed but is required by options.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Solar's checks
+ for suid bind issues.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> fixvardbentries: Updated
+ to Jason's current script.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> g-cpan.pl: Added a fix
+ to store the ebuilds in a defined overlay.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> output.py: Added all
+ xterm* terms to the title-list.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ cascade/stack functions -- use.defaults is fully line-incremental now.
+ Removed a lot of cruft commented-code. Added an ebuild-mover into the
+ entry move functions.
+
+ 09 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_util.py: Placed
+ the lex code into a try/except so we can add the filename into the error
+ that is passed back from shlex.
+
+ 08 Sep 2004; Brian Harring <ferringb@gentoo.org> portage.py: Modified
+ config.__init__(clone=1) so that profiles list is preserved, allowing for
+ all profile's bashrc's to be sourced.
+
+ 06 Sep 2004; Brian Harring <ferringb@gentoo.org> portage.py: Fixed
+ fetch logic for when DISTDIR isn't writable, but the file is fully
+ fetched already (#62985).
+
+ 05 Sep 2004; Brian Harring <ferringb@gentoo.org> portage.py ebuild.sh:
+ Added use flag support to RESTRICT; usual syntax.
+
+ 04 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_data.py: Added
+ FreeBSD as a BSD-type OS and merged the Darwin branch with them.
+
+ 04 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_contents.py: The
+ parsing portion of a persistent contents file parser that can return the
+ owner of a particular file or directory by parsing (and storing) data from
+ the contents files.
+
+ 04 Sep 2004; Nicholas Jones <carpaski@gentoo.org> portage_const.py: Added
+ LOCALE_DATA_PATH to the constants for future gettext (internal) support.
+
+ 04 Sep 2004; Nicholas Jones <carpaski@gentoo.org> output.py: Fixed the
+ title changes to no clear the icon title.
+
+ 04 Sep 2004; Nicholas Jones <carpaski@gentoo.org> prepman: No longer
+ gzip's symlinks -- This needs to gain 'target changed' logic.
+
+ 01 Sep 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Cleaned up the imports, cutting down on from blah import *, instead
+ importing only what is strictly needed for backards compatability.
+
+ 01 Sep 2004; Brian Harring <ferringb@gentoo.org> pym/portage_exec.py:
+ Nick caught this- changed setgid/setuid order so it works.
+
+ 01 Sep 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Added Michael Stewart's patch correcting optional args being specified
+ via position- bug #61881.
+
+ 01 Sep 2004; Brian Harring <ferrignb@gentoo.org> pym/portage.py,
+ pym/portage_exec.py, pym/portage_checksum.py: Restructured spawn
+ so that we don't have two versions; all spawn calls trace back to
+ portage_exec.spawn, either through spawn_bash or spawn_sandbox.
+ portage_exec.spawn is strictly an os.execve wrapper now, so bash
+ doesn't have to be involved unless desired (if desired use spawn_bash).
+
+ 31 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/emerge: Debug
+ print statement left in global scope, corrected it.
+
+ 31 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_checksum.py:
+ Solar's patch to check if prelink binary exists prior to executing it.
+
+ 31 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_checksum.py:
+ Only prelink-check when requested -- This is only valid for merge/unmerge
+ operations -- Also happens to fix the access violations in portageq.
+
+ 31 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Adjustments
+ for the prelink-check changes.
+
+ 31 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_exception.py:
+ Made the exceptions more hierarchial. Yes, I'm aware I can't speel.
+
+ 30 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Added
+ solar's patch to make the file.size check display the size of the
+ offender.
+
+ 30 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py,
+ pym/portage_util.py: Removed -all- duplicate function definitions between
+ portage_util and portage. This is just -begging- for a bug where
+ portage.py's definitions are fixed, but portage_util isn't.
+ If you're moving code out of portage.py (good thing) please yank the def
+ from portage.py. Especially if you're importing everything from new
+ home of the module.
+
+ 30 Aug 2004; Jason Stubbs <jstubbs@gentoo.org> pym/emerge: Added python 2.2
+ compatibility fix. (#62128) Added fix to fail nicely on missing
+ /etc/gentoo-release. (#62149)
+
+ 30 Aug 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Fixed two
+ bugs in bindbapi.aux_get() preventing retrieval of information about tbz2s.
+
+ 26 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/etc-update: minor
+ tweak to etc-update to support single quotes in /etc/etc-update.conf
+ bug (#56785). Added Mamoru Komachi (usata)'s fix for osx (#60721).
+
+ 26 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py,
+ pym/portage_exec.py, bin/ebuild.sh: Removed the PORT_LOGDIR $0 $* | tee
+ hack, and re-implemented it using spawn. Spawn has been extended so that
+ fd_pipes can receive a dict of fd # -> fd, and optionally be nonblocking
+ via returnpid. portage.spawn has support for a logfile optional arg- if
+ specified, spawn logs stdout/stderr via tee -i -a to the specified file.
+ Note portage_exec.spawn doesn't currently support this option.
+
+ 25 Aug 2004; <genone@gentoo.org> pym/portage.py, +pym/portage_checksum.py,
+ pym/portage_gpg.py, -pym/portage_md5.py:
+ renamed portage_md5 to portage_checksum which includes support for sha1.
+
+ 24 Aug 2004; Brian Harring <ferringb@gentoo.ogr> bin/ebuild.sh: Tweak to
+ dyn_test to check if $S exists prior to cd'ing to it.
+
+ 24 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py: Fixed a
+ traceback issues in dblink.treewalk when collision-protect is active.
+ Also added specific check/complaint for PORT_LOGDIR='' to the config class,
+ since it should either not be set, or something non-null- a null
+ PORT_LOGDIR triggers a traceback in doebuild do to an attempted chmod.
+
+ 23 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py: Added a
+ macos ranlib hack; dblink.mergeme by default resets each files mtime, which
+ makes static archives merged to the fs worthless (linker notes the files
+ mtime differs from an internal mtime, and bails). This closes out bug
+ (#58848), and will be obsoleted when refcounts are used instead of mtime +
+ md5.
+
+ 21 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh: Expanded
+ CONF_LIBDIR support, so it honors --prefix set values. (#61060)
+
+ 19 Aug 2004; Marius Mauch <genone@gentoo.org> bin/repoman: Added
+ FEATURES and USE to the readonly variable check.
+
+ 17 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage_data.pym:
+ Adding missing imports.
+
+ 17 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Minor
+ tweak to make repoman detect the repolevel correctly in overlays.
+ (#60298).
+
+*portage-2.0.51_pre20 (16 Aug 2004): Fixes and Public Readiness & GPG
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ imports and new modules so that the API remains constant.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_exec.py: Created
+ for external operations and calls. Presently contains spawn. Mostly for
+ prevention of circular imports.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_md5.py: using
+ the spawn call from portage_exec.py to avoid the circular import.
+
+ 16 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Fixed a
+ traceback related to file.size and --fix, added compatability tweaks for
+ xmllint.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fixed the lock
+ handling and unique_array calls.
+
+*portage-2.0.51_pre19 (16 Aug 2004): Fixes and Public Readiness & GPG
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Add predict
+ for gpg verification.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ lock code to use the external module.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_gpg.py: Fixed
+ the writing operations and access violations.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_locks.py: Fixed
+ the code so it acutally works and is used.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_md5.py: Fixed
+ the lock calls.
+
+*portage-2.0.51_pre18 (16 Aug 2004): Fixes and Public Readiness & GPG
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> dolib*: Added LV's
+ CONF_LIBDIR patch to help out the 32/64 bit lib migrations.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: CONF_LIBDIR
+ patch updates. Added a possible fix for the export issues in environment.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> prepall/lib: CONF_LIBDIR
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Adjusted the
+ manifest/gpg code to reduce the output on missing sigs. Changed the GPG
+ homedir to the PORTAGE_GPG_DIR instead of using rsync for the keyring --
+ This requires manual intervention.
+
+ 16 Aug 2004; Nicholas Jones <carpaski@gentoo.org> sandbox: Added the 32/64
+ paths in for 32/64 lib migrations.
+
+ 16 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/cvstree.py
+ pym/portage.py: Round #2 of ignorecvs, now w/ sane regex goodness and an
+ addition to digest(gen|check) to use the same cvs filter for Manifests.
+ (#46070).
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> emerge: message fix for
+ packages.provided.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Made file.size
+ a warning for the time being.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> cvstree.py: Removed the
+ auto-ignore regex as it is broken AND it breaks Manifests due to excess
+ files allowed into them.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> emerge: A couple changes
+ to the select_dep exception handling for the signing code.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> env-update.sh: Added
+ Spanky's env-update shell script version.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Moved more
+ code into seperate modules. Added support for Manifest verification and
+ usage of 'gpg' 'strict' 'severe' to enable various condition responses.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_const.py: Moved
+ all constants to this module. (All uppercase defines)
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_data.py: Contains
+ all calculated information. uid/gid info. system-specific values. All probed
+ information should go here.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_exception.py:
+ Added many exceptions for the GPG verification code. Added many general
+ exceptions to help differentiate from explicit portage exceptions and
+ those issued by python.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_gpg.py: Handling
+ of gpg verification code and keyring management/trust.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_locks.py: Moved
+ the lock code out of portage.py.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_md5.py: Moved the
+ MD5 calculation code out of portage.py.
+
+ 15 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_util.py: Moved
+ writemsg and unique_array into portage_util.
+
+ 13 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh: Added
+ support for ECONF_LIBDIR; if it isn't defined, then --libdir isn't
+ passed to the configure script. If it is defined, then the configure
+ script gets --libdir=/usr/${ECONF_LIBDIR}.
+
+ 13 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/cvstree.py:
+ Added robbat2's patch to ignore files that cvs ignores. (#46070).
+
+ 13 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh: Shifted
+ the add* sandbox function definitions to before profile.bashrc srcing.
+ As bug #60147 demonstrated, profiles occasionally need to adjust
+ SANDBOX_WRITE (current case being for /usr/lib64/{conftest,cf}).
+
+ 13 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/emerge: Related to
+ bug #60256, adjusted format_size so that is always returns a string.
+
+ 13 Aug 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge:
+ Relocated blocker checking code to before pkgsettings.setcpv() is called
+ on it in depgraph.create()
+
+ 13 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Tweaked lockfile, so it attempts a non-blocking lock_ex first, then
+ states it's waiting on lock blar, then attempts a blocking lock. This
+ will be useful for informing the user why portage seems to have hung,
+ and good for debugging.
+
+ 13 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/emerge-webrsync:
+ Added support for snapshot md5sum's (mirrors now carry them).
+ This is used to ensure the fetched snapshot is sane; if it's sane,
+ then we reuse it for sync'ing. This nulls the -n option, so it's been
+ removed. Closes out #15990, but no longer automatically forcing a refetch.
+ Refetches are only forced if the md5 is invalid.
+
+ 12 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Cleaned up fetch a bit more, saner error messages when unable to
+ write to DISTDIR.
+
+ 12 Aug 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge:
+ Fixed the fix for the earlier traceback on installed package not being
+ in PORTDIR to remove duplicate work.
+
+ 11 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh:
+ Added FEATURES="autoconfig" support. (#55476)
+
+ 11 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Added check to lockfile and fetch, if file already is owned by
+ portage group, don't try and chown it. This will close #60079.
+
+ 10 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/emerge: Fixed a
+ traceback issue, an ebuild is no longer in the tree, but is installed
+ and needs to be used in the depgraph- the problem was, emerge
+ assumed the ebuild was in porttree's db, when vartree should be used
+ if the package is known to be installed.
+
+ 10 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Killed a couple of corner cases for non-root fetch and lockfile calls.
+
+ 10 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py
+ bin/ebuild.sh: Add check to ensure that install phase has been
+ ran prior to qmerge phase being attempted. This can happen
+ when the user is using ebuild to step through the phases.
+ Corrected bug in listdir where it would return None, rather then
+ []- all callee's expect a returned list, not None. Same for ftype,
+ cause's a tb if you just haphazardly rely on cachedir's return.
+
+ 09 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Leave /var/tmp with it's own permissions, chowning/chmoding just
+ /var/tmp/portage (#37521).
+
+ 09 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh
+ pym/portage.py: Corrected bug in profile.bashrc support, added aliases
+ for saving/restoring IFS (remove_path_entry and profile.bashrc loop
+ adjust IFS temporarily). Closes #59749.
+
+ 08 Aug 2004; Brian Harring <ferringb@gentoo.org> dispatch-conf:
+ Converted os.rename calls to shutil.move; the former can't cross fs's,
+ the latter can. (#46148)
+
+ 07 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ cache updates so that an env-update forces ld updating.
+
+ 07 Aug 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py
+ pym/portage_dep.py: Added a new parameter to use_reduce so that !arch?
+ checks can be adhered to even when matchall=1 and arch is not is masklist.
+
+ 07 Aug 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py
+ pym/portage_dep.py: Added profile masked use flags to repoman check.
+ Moved || refactoring to a separate function. Reworked use_reduce logic
+ into simpler sections.
+
+ 05 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage_dep.py:
+ What can I say, I can't get enough of bug (#59574).
+ I'm operating under the assumption there still is a bug in the
+ use_reduce logic, soo I've left a fairly massive amount of debugging
+ code in place that's currently disabled. It's *very* useful for
+ tracking exactly what/how use_reduce decides on a operator node.
+
+ 05 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ I introduced a bug in the previous commit, basically
+ portage.settings.archlist list of arch keywords was being actively
+ pruned by repoman as it stepped through arches for dep checking.
+ Basically, needed to make a copy of archlist rather then using the
+ actual archlist object. Should be the final issue for (#59574).
+
+ 05 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py: Fix
+ in the same area, if use="all" (repoman wants -every use flag- checked),
+ it should call use_reduce w/ matchall set appropriately. (#59574)
+
+ 05 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py: And...
+ repoman's arch check got hosed again. The code in dep_check for
+ building a masklist was incorrect, 3 line fix. (#59574)
+
+*portage-2.0.51_pre17 (03 Aug 2004): Fixes and Public Readiness
+
+ 03 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_dep.py: Again
+ fixed the || exceptions to understand nested legal || statements.
+
+*portage-2.0.51_pre16 (03 Aug 2004): Fixes and Public Readiness
+
+ 04 Aug 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Changed the
+ virtual/glibc references to virtual/libc.
+
+ 04 Aug 2004; Nicholas Jones <carpaski@gentoo.org> prepman: No longer runs
+ gzip on .keep files.
+
+ 04 Aug 2004; Nicholas Jones <carpaski@gentoo.org> getbinpkg.py: Added in
+ an active/passive option for FTP connections -- Requires the appending of
+ an asterisk to the HOST portion of the ftp string to use active connections.
+
+ 04 Aug 2004; Nicholas Jones <carpaski@gentoo.org> make.conf*: Updates for
+ the active-connection ftp option.
+
+ 04 Aug 2004; Nicholas Jones <carpaski@gentoo.org> emergehelp.py: Removed
+ the bin/ version and replaced it with a duplicated pym/ version.
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py:
+ Added check to ensure /var/tmp/portage's permissions were sane. (#56665)
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Added
+ explicit check for missing files directory, rather then ignoring it.
+ Also added an explicit commit-time check for CVS/Entries being sane.
+ (#57141).
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: reworked
+ the qacats definition so that the type of bug that borked emerge help is
+ no longer possible.
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py,
+ bin/emerge: Corrected emerge --fetch-all-uri issues, now works. Basically,
+ FEATURES="cvs" emerge -f blar == emerge --fetch-all-uri blar. The fetch
+ option handling in emerge could use some cleanup.
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py: Ongoing
+ cleanup in emerge -fp; this corrects a minor naggle affecting previous
+ releases, where emerge -fp would still attempt to do md5 checks on files.
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py: Corrected
+ logic for fetch(..., ..., use_locks=1,listonly=1) attempting to use locks,
+ when fetch is just printing the src_uri's. (#59394).
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Corrected the
+ borkage I introduced into repoman's help option- it was throwing a traceback
+ due to file.executable's key name being typoed.
+
+ 03 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_dep.py: Enhanced
+ the invalid depend string identification for || (and &&) strings.
+
+*portage-2.0.51_pre15 (03 Aug 2003): Fixes and Public Readiness
+
+ 03 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Corrected
+ typo, trying to remove .backup_metadata.dtd rather then metadata.dtd.
+
+ 03 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_dep.py: Changing
+ from dep_opconvert to use_reduce introduced a bug due to how OR'd lists are
+ managed by the remaining dep handling functions -- Fixed by emulating the
+ format in use_reduce.
+
+ 02 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/repoman, pym/portage.py:
+ Added local caching of metadata.dtd, to prevent flaky connections from
+ flagging a packages metadata.xml as invalid due to xmllint failing to fetch
+ metadata.dtd. Simplified version of patch in (#57210).
+
+ 02 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh,
+ pym/portage.py: Added support for src'ing a profile bashrc. Fex, if
+ /etc/make.profile/profile.bashrc exists, it is sourced prior to ebuild.sh
+ defining any of it's functions. (#58415).
+
+ 02 Aug 2004; Brian Harring <ferringb@gentoo.org> bin/emerge-webrsync: General
+ cleanup; uses the make.conf defined FETCHCOMMAND for fetching (fixing #57887),
+ runs emerge metadata after a successful sync also.
+
+*portage-2.0.51_pre14 (02 Aug 2003): Fixes and Public Readiness
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> do*: Added exit calls
+ on failures and changed the install to use short options for BSD compat.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: unset
+ GLOBIGNORE added. Echo out the confingure command from econf. Moved the
+ maketest code to dyn_preinst so it didn't force-run maketest. Added a
+ patch for keyword expansion (requires portage-2.0.51 for use).
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> emerge: --fetch-all-uri
+ added to force all URIs to be downloaded (works like features=cvs). libc
+ version printing enhancements. Fixed the binary package selection in an
+ alt ROOT. Headers and libtool added to info. --ask removed on a resume.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> prepstrip: Change ewarn
+ to echos to stderr with beeps.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Added to the
+ OK message output for issues that fail.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> make.conf: Typo correction
+ patch added.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> output.py: Added kterm
+ to the titlebar terminals.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Added a message
+ regarding the location of the virtuals file (move to /etc/portage/profile).
+ Added a invalid-mirror message and a missing URI message for fetching. Added
+ the selinux sandbox patch. Removed the old dep_opconvert call as all ?:
+ syntax is gone.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> portage_dep.py: Fixed the
+ use_reduce code to properly handle negative requirements on masked flags.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> tbz2tool.c: Made all the
+ comments to C style.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> libsandbox: Code from
+ Seth Robertson that tracked down all adjuct flags for read operations that
+ did not invoke a write operation.
+
+ 01 Aug 2004; Masatomo Nakano <nakano@gentoo.org> bin/emerge: Added
+ message about ._cfg* files after emerge sync.
+
+ 01 Aug 2004; Masatomo Nakano <nakano@gentoo.org> pym/portage.py: Modified
+ updating /etc/portage/package.* logic to see CONFIG_PROTECT and
+ CONFIG_PROTECT_MASK.
+
+ 01 Aug 2004; Marius Mauch <genone@gentoo.org> bin/emerge:
+ Added a warning for `emerge /path/to/ebuild`
+
+ 01 Aug 2004; Marius Mauch <genone@gentoo.org> bin/emerge:
+ Fixing broken logic for the `emerge rsync` deprecation notice (it only showed
+ up on `emerge --rsync`).
+
+ 01 Aug 2004; Brian Harring <ferringb@gentoo.org> pym/portage.py bin/emerge:
+ Fixed the lockfile/unlockfile functions so that they correctly support having
+ an int passed in (the fd #), or having a file object passed in. Corrected
+ lockfile so that the lock is owned by portage group, with g+w permissions
+ (this is needed since sudo emerge blar can bail, leaving a stale lock that
+ non-root usage cannot remove). Added locking to emerge's emergelog function,
+ preventing log messages from potentially getting mixed together. Added check
+ to fetch function to complain if unable to write to DISTDIR (previously the
+ fetcher just bailed, stepping through each src_uri). Added lockfiles for
+ fetching/md5ing of the src- these lockfiles are stored in a subdirectory
+ (locks_in_subdir=".locks") if specified, and locking is controlled via
+ use_locks (defaults to on). emerge -f no longer requires root/sudo to run
+ (ebuild never had this restriction). (#42969)
+
+ 31 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py bin/emerge:
+ Removed USE-based SLOT support. Removed uselist from getslot methods.
+
+ 29 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Added check for
+ files over 20k in a packages files directory. file.size, repoman treats it
+ as a a failure. Added the repoman manpage entries for file.size, and
+ file.executable (I missed file.executable earlier).
+
+ 28 Jul 2004; Masatomo Nakano <nakano@gentoo.org> pym/portage.py: Fixed a bug
+ emerge doesn't pkg_setup() with -k/-K option. (#25152)
+
+ 28 Jul 2004; Masatomo Nakano <nakano@gentoo.org> pym/portage.py:
+ Added ._cfg* file for updating /etc/portage/packages.* during global
+ update.
+
+ 28 Jul 2004; Masatomo Nakano <nakano@gentoo.org> bin/emergehelp.py,
+ man/emerge.1: Added explanation of --newuse to manpage/help.
+ Added information of --verbose to manpage.
+
+ 27 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py:
+ Reversed the order of profile virtuals (dirVirtuals) so that a cascading
+ profile's virtuals are stacked in the correct order.
+
+ 26 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/emerge:
+ Removed the `which blah` calls- A) stage1 lacks which, B) which searches
+ $PATH- all sane shells do this already when handed a command that
+ isn't absolute path. These which calls were used in
+ commands.getstatusoutput() calls, which starts up a shell with
+ the arg passed to the shell, so "`which blar` args" isn't needed.
+
+ 26 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/repoman:
+ Added file.executable check- ebuilds, digests, Manifest, ChangeLog, and
+ metadata.xml don't need the executable bit set. CVS preserves it upon
+ commit, so we do the check prior to commit. (#55647)
+
+ 26 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/emerge:
+ Removed the hardcoding of uname for emerge info, using which to find it
+ instead.
+
+ 26 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/repoman:
+ Added check to ensure manifest recommit is at least possible when
+ committing, and corrected handling of CVS/Root files for OSX machines.
+ Removed readline import, doesn't seem to be used at all.
+
+ 26 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge pym/portage.py:
+ Refactored slot code into portage.py to remove usage off portage_dep.
+
+ 25 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/dohtml:
+ Corrected a bug in dohtml where it was unable to install files with a space
+ in their name (#58258)
+
+ 25 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge pym/portage.py:
+ Deprecated --inject and added support for package.provided in both the
+ profiles and /etc/portage/profile directory.
+
+ 24 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge pym/portage.py:
+ Added USE flag based SLOT support.
+
+ 24 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge pym/portage.py:
+ Added USE flag based PROVIDE support. (#32114)
+
+ 24 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> src/sandbox-1.1/libsandbox.c:
+ Fixed lchown sandbox bug. (#58084)
+
+ 23 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Corrected a
+ false positive on the ebuild.nesteddie check. Basically it wasn't looking
+ to see if the line was active or not (fex # (die), bash skips, but repoman
+ caught). Aside from that, that check is still capable of missing multiline
+ ebuild.nesteddie instances. (#33011)
+
+ 22 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/ebuild.sh: Re-enabled
+ binary QA interceptors, with a minor twist- the QA_INTERCEPTORS is used to
+ specify what QA interceptors will be defined. These functions are no longer
+ saved in the ebuild's stored env (exist *only* in depend phase), and have been
+ expanded to identify if it's the ebuild, or eclass that's triggering the QA
+ Notice (#54652). The interceptors behaviour when the binary is missing has
+ been corrected to correctly output "missing command $bin: args".
+
+ 21 Jul 2004; Masatomo Nakano <nakano@gentoo.org> bin/emerge: Fixed bug
+ which blocks a package itself with -U option.
+
+ 20 Jul 2004; Masatomo Nakano <nakano@gentoo.org> bin/repoman: Fixed
+ profile cache problem. (#43601, #56170)
+
+ 20 Jul 2004; Marius Mauch <genone@gentoo.org> bin/ebuild.sh:
+ added usev() and hasv() as complement to useq() and hasq().
+
+ 18 Jul 2004; Brian Harring <ferringb@gentoo.org> bin/repoman: Corrected
+ ebuild.allmasked check, so that it checks for an available version across all
+ arches, rather then the last arch processed. Typo fixed also- bugs #57356 and
+ #57068.
+
+ 17 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/repoman: Added patch from
+ #49126 that makes repoman check that a USE flag from use.local.desc applies
+ to the packages that make use of it.
+
+ 14 Jul 2004; Marius Mauch <genone@gentoo.org> bin/emerge:
+ added a deprecation warning for --upgradeonly
+
+ 14 Jul 2004; Marius Mauch <genone@gentoo.org> bin/etc-update:
+ Added a hint to etc-update so people that don't know what to do don't use -3
+ or -5 by accident.
+
+ 12 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge:
+ Adjusted masked binary checking code to exclude --usepkgonly.
+
+ 10 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> man/portage.5:
+ Adjusted documentation for user use.mask to match implementation.
+
+*portage-2.0.51_pre13 (09 Jul 2004): Fixes and Public Readiness
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Included
+ ferringb's logic fix for the repoman code. Fix that prevents vardb from
+ using all files and directories in the vardb as keys instead of only the
+ proper ones. Code touchups.
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> prepstrip: Fixes that
+ result in BSD compat and split the regex -- find doesn't do extended.
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> emerge: included a uname
+ fix for bsd. Added --fetch-all-uri as a way to get all URIs downloaded for
+ a package regardless of conditionals.
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Moved the
+ declaration of ebuild_phase toward the top.
+
+ 09 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge:
+ Fixed incorrect assignment of depgraph.mydbapi[] objects.
+
+ 07 Jul 2004; Marius Mauch <genone@gentoo.org> bin/repoman:
+ Solved a big memory problem in repoman where a full scan required several
+ gigabytes, caused by apparently unused objects.
+
+ 04 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge pym/portage.py:
+ Fixed issue that allowed installed virtuals to overide user virtuals.
+
+ 03 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge: Added masked
+ package removal to binpkg candidates before getting the best. (#55871)
+
+ 01 Jul 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py:
+ Fixed exception catching on module import.
+
+ 27 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> bin/repoman:
+ Fixed year (2003 -> 2004) in copyright lines.
+
+ 27 Jun 2004; Marius Mauch <genone@gentoo.org> pym/portage.py:
+ Added a check for symlinked dirs to the collision-protect code so it doesn't
+ double-check files in symlinked dirs with wrong pathnames.
+
+ 26 Jun 2004; Masatomo Nakano <nakano@gentoo.org> bin/regenworld: Fixed
+ regenworld. It always failed without -h or --help.
+
+ 26 Jun 2004; Masatomo Nakano <nakano@gentoo.org> bin/emerge: Added more
+ messages when emerge fails due to masked package.
+
+ 26 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py:
+ Added pkgsplit check on values returned by vardbapi.cpv_all()
+
+ 26 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Removed a stray dot.
+
+ 25 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> repoman: Changed CVS
+ header regex to "Gentoo Foundation"
+
+*portage-2.0.51_pre12 (21 Jun 2003): Fixes
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Removed the
+ extra spawn of portageq as sandbox handles the python pyo's accesses now.
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixes for
+ the HOME issues. Correction of permissions from 6770 to 2770.
+
+ 21 Jun 2004; Masatomo Nakano <nakano@gentoo.org> pym/portage.py:
+ Fixed problem that 'emerge something' would install all depeneded pkgs
+ even if they are already installed.
+
+*portage-2.0.51_pre11 (21 Jun 2004): Fixes
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Disabled the
+ URL encoding for BINHOST as it will take a lot of work to get it right.
+ Execve try/except added to handle missing binaries and such. Changed the
+ default HOME to be TMPDIR/homedir. Try/except on db close operations. Add
+ in missing unlocks. Hacked in the /var/lib/portage in a chroot fix.
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Added more info
+ into the profile for the stacked profiles.
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: The userland
+ fixes for *BSD. QA Notice fix for IUSE verbosity on global scope stuff.
+ Missing quote fix for QA intercepters. Return 0 in the use_* functions.
+ Removed AA from the readonly list.
+
+ 21 Jun 2004; Nicholas Jones <carpaski@gentoo.org> dohtml: Karl's update
+ which is mostly a rewrite.
+
+ 21 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> bin/emerge:
+ Modified emerge to build up a fakedb regardless of 'empty' in params,
+ and to incrementally add any packages added to the dep graph.
+ (#1343, #8810, #54608)
+
+ 20 Jun 2004; Masatomo Nakano <nakano@gentoo.org> bin/repoman:
+ Fixed problem which fails to detect IUSE value. (#21544)
+
+ 20 Jun 2004; Masatomo Nakano <nakano@gentoo.org> bin/emerge:
+ Added an exception code for broken timestamp.chk. (#54380)
+
+ 20 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> pym/ebuild.sh: Adjusted
+ returns for use_with and use_enable to only return 1 on invalid usage.
+
+ 20 Jun 2004; Masatomo Nakano <nakano@gentoo.org> pym/portage.py:
+ Fixed problems that portage doesn't block with --update option(#52377)
+ and fail to block virual packages(#52506).
+
+ 20 Jun 2004; Masatomo Nakano <nakano@gentoo.org> pym/portage.py:
+ Fixed CONFIG_PROTECT/CONFIG_PROTECT_MASK in /etc/csv.env(#51646).
+
+ 20 Jun 2004; Masatomo Nakano <nakano@gentoo.org> bin/ebuild.sh:
+ Added error message when pkg_config is not defined. (#51167)
+
+ 14 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py:
+ Fixed bug in portdbapi.aux_get where a problem ebuild would cause a lock
+ to not be released.
+
+ 09 Jun 2004; Marius Mauch <genone@gentoo.org> bin/emerge:
+ Changed emerge --info to reflect libc versions other than glibc.
+
+ 08 Jun 2004; Marius Mauch <genone@gentoo.org> pym/portage.py:
+ Added the collision-protect feature that prevents packages from
+ overwriting files they don't own. Has to be enabled with
+ FEATURES=collision-protect as it needs more testing before it
+ can be enabled by default (bug #28228).
+
+ 05 Jun 2004; Marius Mauch <genone@gentoo.org> bin/ebuild.sh:
+ Fix rpm support by changing rpm to rpmbuild (bug #13508).
+
+ 05 Jun 2004; Marius Mauch <genone@gentoo.org> bin/regenworld:
+ Added a --help message ro regenworld (bug #37539).
+
+ 03 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Fixed bug #52720
+ and restored patch for a 35% drop in dep calc time.
+
+*portage-2.0.51_pre10 (02 Jun 2003): Fixes
+
+ 02 Jun 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Added MANPATH
+ to the colon_seperated list -- parsing code NEEDS TO BE FIXED. * and ~*
+ matches allowed for package.use for arch-development -- ~* implies *.
+
+ 02 Jun 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fix for a new
+ typo in the logger function that prevented emerge.log from being written.
+
+ 02 Jun 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: make test
+ only occurs when enabled in FEATURES and not in RESTRICT -- defaults OFF.
+ Added ferringb's local B_* fix for eclasses. Made db vars readonly via bash
+ for non-depend phases after the global scope.
+
+ 02 Jun 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage.py: Reverted
+ adjusted made to config.setcpv on 18 May 2004 due to bug #52720.
+
+ 01 Jun 2004; Marius Mauch <genone@gentoo.org> bin/repoman,bin/regenworld:
+ only messages about broken log entries in regenworld when called with
+ --debug. Fix signing stuff in repoman.
+
+*portage-2.0.51_pre9 (22 May 2003): Speedups and bug fixes
+
+ 22 May 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_template.py:
+ Added in last-three caching for db modules. Ensuring that keys are strings.
+
+ 22 May 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_cpickle.py: Fix
+ that ensures the Unpickler works properly.
+
+ 22 May 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Updates for
+ environment files ordering in ebuild.sh. Added in normalize_path to handle
+ the really annoying "'//' is a legal prefix" issue with os.path.normpath.
+ Applied normalize_path to cacheddir() so that the keys match and we have
+ more cache hits and better performance. Added statistics to to cacheddir
+ available with noise=2. Do not return a blocker when doing a zerolist.
+ Fixed the stacking functions to properly order the incrementals and apply
+ the removals forward. Changed all string.atoi() to int(). Added in the
+ selinux changes for spawning the fetch command. Added a patch that allows
+ ebuild.sh to display 'validcommands'. close_caches() added to allow atexit
+ to close all the DB connections. close_portdbapi_cache() handles the global
+ that has all db instances -- This avoids problems with the API nulling the
+ internal links. Adjusted the db handling for sync() calls and removed some
+ object duplication db calls.
+
+ 22 May 2004; Nicholas Jones <carpaski@gentoo.org> getbinpkg.py: Fix for HTTP
+ redirects (301 and 302) so that the redirect opens a new connection to the
+ move-location server -- This allows us to redirect to a different machine.
+
+ 22 May 2004; Nicholas Jones <carpaski@gentoo.org> emerge: For iuse output we
+ now ensure that the correct db is referenced. The worldfile additions do not
+ occur when a packages is new and updates are not being performed. Patch to
+ add binutils to the emerge info.
+
+ 22 May 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Rearranged the
+ sourcing of the profiles and the special environment files. Added src_test
+ as an optional test method -- Some packages are extremely dumb and need to
+ be prevented from using this via RESTRICT.
+
+ 18 May 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Minor speed
+ improvement in config.setcpv preventing a useless regenerate
+
+ 18 May 2004; Jason Stubbs <jstubbs@gentoo.org> portage.py: Reversed the
+ order of config.getvirtuals' stack_dictlist call for correct ordering.
+
+*portage-2.0.51_pre8 (16 May 2003): Big cleanups & Ebuild QA Stuff.
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> portage_exception.py: New
+ file containing portage exceptions. Added 'CorruptionError' for the db code.
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> portage_util.py: New file
+ that contains utility functions. Allows db_modules to use portage functions
+ without a circular dependency. CODE IS DUPLICATED and needs to be fixed in
+ portage.py to use this new module. grab*, getconfig, varexpand, pickle_*,
+ ReadOnlyConfig
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_*: Modules
+ do not have an __init__ any longer -- module_init() is called by the
+ template after loading the config and setting the 5 variables inside of
+ the class. self.config is a ReadOnlyConfig object which is just a dict
+ that you can't write to. Throws CorruptionError when the read functions
+ return exceptions.
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Reversed the
+ virtuals order so it matches the documented format. When an ebuild does not
+ exist, we now raise a KeyError with a useful string. 'couple minutes' changed
+ to 'couple of minutes' for Seemant. ;)
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> prepstrip, ebuild.5,
+ repoman.1: Typo corrections/text replacements.
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Added deprecation
+ notice to 'emerge rsync' to favor 'emerge sync'. Modified the emerge.log
+ code to not change permissions on the files beyond what is necessary -- NEEDS
+ TO BECOME AN ADDITIVE FUNCTION. Produce a warning instead of a traceback
+ when an ebuild does not exist for -U.
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Touched up the
+ logging stuff at the top. Removed extra_functions.sh. src_compile additions
+ so that it can run make without having a config file requirement.
+
+ 16 May 2004; Nicholas Jones <carpaski@gentoo.org> dobin,dosbin: Removed the
+ duplicated stripping from the helper tools.
+
+ 09 May 2004; Jason Stubbs <jstubbs@gentoo.org> pym/portage_dep.py:
+ fixed bug in use_reduce that caused returned list to be flattened.
+
+ 30 Apr 2004; Marius Mauch <genone@gentoo.org> bin/ebuild.sh:
+ modified ebuild.sh error message on seemants and roger55s request.
+
+*portage-2.0.51_pre7 (26 Apr 2003): Big cleanups & Ebuild QA Stuff.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed masking
+ problems due to the new stacking functions and empty-value stripping.
+
+*portage-2.0.51_pre6 (25 Apr 2003): Big cleanups & Ebuild QA Stuff.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Dropped selinux
+ from the IUSE complainer list.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Made it use the
+ constants defined in portage.py for the world file.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Modifications
+ so that the virtuals are incremented in the proper order and reversed the
+ final values so that the first virtual is the 'best' one. Try to put the
+ INHERITED variable back into the environment before calling out to portage.
+ This makes the ECLASS QA notices actually valid.
+
+*portage-2.0.51_pre5 (25 Apr 2003): Big cleanups & Ebuild QA Stuff.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed name
+ of the world file constant. Fixed the virtuals loading and vartree creation
+ circular dep with a repitition hack. Fixed the virtuals loading function so
+ that it doesn't destroy the virtuals before saving them.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fixed all the
+ references to the world file to use portage constants. Made the verbose
+ output for use flags call unique array to make sure values aren't duped.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Typo fix for
+ inherited, and removed the delay.
+
+*portage-2.0.51_pre4 (25 Apr 2003): Big cleanups & Ebuild QA Stuff.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Creation of
+ a great number of 'constants' that were hard coded in various places and
+ now are created in a cascaded style, for the most part. Exception handling
+ for the loading of modules added along with verbose messages about the
+ exception being handled for user info. PRIVATE_PATH is a new constant that
+ points to the new directory we will be using for portage internal data --
+ It is a secure directory that only group portage may write, read, and scan.
+ PORTAGE_CACHEDIR is deprecated -- The real cache directory is FHS and is a
+ constant -- The dep cache is named specifically now as 'PORTAGE_DEPCACHEDIR'.
+
+ **Changed the stacking functions** so they are quite a bit more sane -- They
+ still need a little help though -- stack_* functions are now used to stack
+ specific types instead of using grab_stacked "super functions" -- The naming
+ is a little rough but intelligable.
+
+ **VIRTUALS modification** The /var/cache/edb/virtuals file is unnecessary
+ as portage now loads the provides from the vartree itself. /etc/portage
+ may have a virtuals file that stacks on top of the var and profile virtuals.
+ This also entails the removal of the virtual-file handling code (yay!).
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fix for the name
+ change for PORTAGE_CACHEDIR to PORTAGE_DEPCACHEDIR.
+
+ 25 Apr 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added checks
+ to ensure that use flags are properly mentioned in IUSE. Adjusted the QA
+ Interceptors (function overrides for common app names) to make sure they
+ don't interfere in weird cases -- Relying on 'type -p' now. Eclasses are
+ checked for illegal inheritance modes (conditional-based). Increased the
+ cache lines for an entry -- Added 'PROVIDE' and 8 empties.
+
+ 22 Apr 2004; Marius Mauch <genone@gentoo.org> bin/repoman:
+ added a CVS Header check to repoman
+
+ 20 Apr 2004; Marius Mauch <genone@gentoo.org> pym/portage.py:
+ fix for getmaskingreason if the mask isn't in PORTDIR's package.mask (#48447)
+
+ 17 Apr 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Fixed for
+ python-2.2 compatibility.
+
+*portage-2.0.51_pre3 (13 Apr 2003): Cleanups and small features.
+
+ 13 Apr 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_*: Fixed the
+ permissions issues regarding the umask problems with DB vars.
+
+ 13 Apr 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for the
+ import urllib call that was misspelled for PORTAGE_BINHOST. Genone's patch
+ that allows FETCHCOMMAND_${PROTOCOL}. getmaskingreadon() from genone's
+ package.mask display patch.
+
+ 13 Apr 2004; Nicholas Jones <carpaski@gentoo.org> output.py: For some reason
+ people have a problem with my bad spelling of semi-common colors, so I added
+ in requested changes for the color 'fuchsia'.
+
+ 13 Apr 2004; Nicholas Jones <carpaski@gentoo.org> cnf/make.conf: Comment
+ fixes for the CHOST line. FEATURES modification.
+
+ 13 Apr 2004; Nicholas Jones <carpaski@gentoo.org> dispatch-conf.conf: Removed
+ the 'a' option.
+
+ 13 Apr 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Catagory searches
+ added if search is prefixed with '@'. jstubbs/spider's fix for binary use
+ flag passing problems worked in. Genone's patch for package.mask comment
+ display. Patch to display warnings when unmerging system packages worked in.
+
+ 13 Apr 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Quieted up
+ some output for use/has internally. Added a patch for the help output.
+ Added functionality to pass down IUSE from eclasses. Made several variables
+ readonly inside of ebuilds:
+ P PN PV PVR PR A AA D EBUILD EMERGE_FROM O PPID FILESDIR EBUILD_PHASE
+
+*portage-2.0.51_pre2 (11 Apr 2003): Release Fixes
+
+ 11 Apr 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Portage can now
+ match categories if the search is prefixed with an '@' -- @app-portage will
+ list all packages in app-portage... '@portage' will match all in app-portage
+ and will match anything with portage in the title -- It's still a regex.
+
+ 11 Apr 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: nostrip in
+ RESTRICT now enables DEBUGBUILD -- stripping and related functionality
+ needs to get cleaned up better.
+
+ 11 Apr 2004; Masatomo Nakano <nakano@gentoo.org> etc-update, ebuild.sh:
+ Fixed infinity loop in etc-update(#19144). Fixed glob problem in
+ ebuild.sh(#37066). Fixed deleting build-info problem with
+ FEATURES="keepwork"(#29044).
+
+ 10 Apr 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Includes the
+ deadlock breaks marked with 'XXX:' to indicate where fixes are needed. Added
+ HTTP encoding to PORTAGE_BINHOST with checks and fallbacks. Fallback for
+ dbkey settings spawned from ebuild. Exception handling for db classes in
+ the case of random corruption. jstubb's fix for the dep code to handle
+ empty lists, added a notice about that being rude.
+
+ 10 Apr 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Made more QA
+ notices and made them slightly more pretty 'QA Notice:'. Made the depend
+ phase trap less violent -TERM not -KILL.
+
+ 10 Apr 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Added IUSE missings
+ a check(#21544).
+
+ 10 Apr 2004; Marius Mauch <genone@gentoo.org> tarball.sh, pym/portage.py:
+ Fixing broken regexp in fixdbentries() (bug 46096), changing version
+ number.
+
+ 10 Apr 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Fixed unsafety
+ temporary file name(#44455).
+
+ 09 Apr 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ reorder ld.so.conf bug(#44028). Portage should skip not existing DIR
+ during unmerge(#25339).
+
+ 09 Apr 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Added
+ jstubbs's patch to add a check invalid DEPEND format to repoman.
+ This should fix #36857.
+
+ 09 Apr 2004; Masatomo Nakano <nakano@gentoo.org> emerge, portage.py,
+ output.py: Fixed some bugs. See #45164, #24299, #34967.
+
+ 01 Apr 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ virtuals in reverse order(jstubbs's patch and my fix).
+ This should close #45468.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_*: Updated
+ all the db modules to be current and correct and updated the testing code
+ to make sure everything is working properly.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> ebuild: Fix for traceback
+ and incorrent ROOT variable when using an alternate root and hand-merging.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Exported the
+ sandbox variables so that they work.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Enhancements for
+ binary downloads -- proper selection for virtuals, etc... Proper slot
+ handling for pretend output with binaries.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> prepman: symlink fix.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> prepstrip: Added the
+ readelf PIC code for the TEXTREL stuff.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Removed some
+ functions: evaluate, dep_listcleanup, dep_getjiggy. Made inheritance for
+ profiles relative from the profile's directory instead of from the profile's
+ base directory. OBSOLETING two functions dep_parenreduce and dep_opreduce in
+ favor of the new code in portage_dep paren_reduce and use_reduce. dep_zapdeps
+ got an overhaul for much more intelligent selection of packages and virtual
+ handling during depgraph generation. Binary tree enhancements and selection
+ enhancements. bindbapi created to do aux_get on binaries. isInjected added
+ to vardbapi to get injected status. SRC_URI uses the new portage_dep code
+ to handle strings now -- nesting should would flawlessly and FEATURES=cvs
+ should get _all_ files.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_cpickle.py:
+ Added pickle loading safety.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> portage_dep: Temp home
+ for the dep resolution code that will be moving from portage.py and emerge
+ until we get the modular structure set up.
+
+ 17 Mar 2004; Masatomo Nakano <nakano@gentoo.org> ebuild.sh, emerge,
+ portage.py, portage_db_anydbm.py, portage_db_cpickle.py,
+ portage_db_flat.py, portage_db_template.py:
+ Improved handling cache files on multi portage trees.
+ Fixed 'BAD COUNTER' error when emerge --inject. (#41062)
+ Added ferringb's patch to avoid sed command. (#40819)
+
+ 12 Mar 2004; Marius Mauch <genone@gentoo.org> bin/repoman:
+ repoman: Added a readonly-variable-assignment check (#44424)
+
+ 06 Mar 2004; Masatomo Nakano <nakano@gentoo.org> repoman, portage.py:
+ Fixed some repoman/portage bugs. repoman shouldn't use /etc/portage/*
+ files. repoman shouldn't use PORTDIR_OVERLAY(#11335). repoman should use
+ each arch profile dir(#43601). portage didn't handle virtual dependency
+ with version (>=virtual/package-1.0) in some places.
+
+ 05 Mar 2004; Marius Mauch <genone@gentoo.org> bin/emerge:
+ Trivial fix for emerge -pv if the download size is a long.
+
+ 03 Mar 2004; Marius Mauch <genone@gentoo.org> bin/repoman,
+ pym/portage.py:
+ Fixing the "letter before endversion" bug (#17172). Replacing
+ keywords.desc with arch.list in repoman (#35398). FEATURES=strict
+ is now sufficient for Manifest validation (#41292).
+
+ 01 Mar 2004; Marius Mauch <genone@gentoo.org> bin/emerge,
+ bin/emergehelp.py, man/emerge.1:
+ Updated docs for --update and removed the "help" action (wasn't working
+ anyway).
+
+ 29 Feb 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ wrong USE in 'emerge info'. This should fix #34260.
+
+ 27 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed info dir
+ regeneration produces errors with a non-C locale and misleading error
+ message. This should fix #41872,#24299.
+
+ 27 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge, emergehelp.py,
+ emerge.1: Added genone's patch for man/help of --tree option.
+
+ 27 Feb 2004; Masatomo Nakano <nakano@gentoo.org> ebuild.sh: Removed
+ /usr/share directory in ${D} when it's empty. This should close #42312.
+
+ 26 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Added new option
+ --newuse. This option is to rebuild a package whose USE has been changed.
+
+ 22 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge, portage.py: speedup
+ when /etc/portage/package.keywords is defined. Moved loading
+ /etc/portage/package.* processs to config class. This should fix #41520.
+
+ 19 Feb 2004; Masatomo Nakano <nakano@gentoo.org> portage.py:
+ Fixed CATEGORY value after preinst phase. This should close #6414. Fixed
+ nested dependency problem and cleaned up dep_zapdeps function.
+ This bug happened with DEPEND='|| ( cat_a/pkg_a flag? ( cat_b/pkg_b ) )'.
+ This should close #41869.
+
+ 13 Feb 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed parsing
+ SRC_URI bug when FEATURES="cvs". This should close #16159.
+
+ 12 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge, pym/portage.py:
+ TGL's patch for correction package size when emerge -v. -- Fixed
+ use.default bug. It occurs when package in use.default exists in system
+ and it's virtual package. This should close #40831.
+
+ 12 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed
+ --ask bugs. It breaks with "--clean". It also breaks when blocker
+ exists. This should close #39865.
+
+ 12 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed
+ --ask bug with --changelog. This should close #41293.
+
+ 11 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emergehelp.py: Added
+ help of F flag with emerge --pretend. This should close #28253.
+
+ 11 Feb 2004; Masatomo Nakano <nakano@gentoo.org> pym/portage.py: Fixed
+ ccache dir permission problem with FEATURES="userpriv".
+ This should fix #22125.
+
+*portage-2.0.50-r1 (09 Feb 2003): Release Fixes
+
+ 09 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix the config
+ code so that it doesn't fail when the profile does not exist -- allows
+ sync'ing without a tree like it should. Parser returns an exception with
+ the parse error now for getconfig(). TGL's patch for another cache issue
+ in class config. Modified the /etc/make.profile message. Fix for the
+ "eclass does not exist" messages on sync.
+
+ 09 Jan 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Fix the repopath
+ so that it cna be run outside of cvs repos.
+
+ 09 Jan 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Add portage's
+ pym path to SANDBOX_PREDICT to stunt any further .pyc/.pyo problems. Add
+ nofetch to the 'successful' kill list to stop the $T definition woes.
+
+ 08 Feb 2004; Masatomo Nakano <nakano@gentoo.org> repoman: repoman should
+ read each arch virtual file. This should close #40813.
+
+ 08 Feb 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed -s/-S
+ bug. "Latest version installed:" was incorrect. This should fix #40847
+
+ 08 Feb 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed ldconfig
+ bug. emerge didn't ldconfig after removing library directory.
+ This should fix #40694.
+
+*portage-2.0.50 (06 Feb 2003): Release -- API change, cleanups, speedups
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> *: repoman got a quick fix
+ from genone. Ed's fix for ask/pretend. Made sure that emerge force-updated
+ the eclass cache before trying to update all the metadata. masking type
+ patch from Genone. masking info patch and regenworld patch added.
+
+*portage-2.0.50_pre22 (04 Feb 2003): Cleanups and stablizing
+
+ 04 Feb 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: TGL's fixes
+ for exec/child/wait problems. Unset GREP_OPTIONS GREP_COLOR. has() and use()
+ no longer attempt to determine if they are to be quiet or noisy -- They
+ default to noisy -- useq() and hasq() are the non-verbose versions.
+ EBUILD_PHASE set to add a hack-ish way around global scope calls in
+ eclasses -- NOTHING SHOULD BE CALLED IN THE GLOBAL SCOPE. Touchup to the
+ inherit() code that should finally allow the removal of the ECLASS and
+ INHERITED settings. Removed tty (use/has) calls. Removed dirname calls --
+ portage.py handles setting the dbkey filename now.
+
+ 04 Feb 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Ed Catmur's
+ (with a little TGL added in) patch for --ask. Added a 'metadata' target
+ that skips the sync and only updates the cache. FEATURES="getbinpkg" added.
+ TGL's exit code fixes. Fixed match code for -S so it doesn't complain about
+ specific and double versions. Unmerge via dbpath fix. Rewrote rsync's
+ options that supports --verbose and --quiet operation now and can force
+ checksumming all files using --debug. Sort the files in the cache update
+ so it's a little more predictable.
+
+ 04 Feb 2004; Nicholas Jones <carpaski@gentoo.org> prepstrip: changed
+ --strip-debug to --strip-unneeded.
+
+ 04 Feb 2004; Nicholas Jones <carpaski@gentoo.org> getbinpkg.py: Updates to
+ enable HTTP/HTTPS authentication.
+
+ 04 Feb 04; Nicholas Jones <carpaski@gentoo.org> portage.py: best_from_dict
+ added to grab the best entry from set of dicts using a list of the keys for
+ priority. jstubb's patch to fix listdir -- splits it into a cache and list
+ setup. jstubb's patch for varexpand to handle $VAR better. Latexer's patch
+ for KernelVersion code to use Makefiles instead of the version.h. Modules
+ are loaded from /etc/portage/modules or defaults, whichever works. Fixed
+ the /etc/make.profile-is-missing traceback. Spawn can be given 3 pipes to
+ redirect stdin,stdout,stderr to specific outputs, terminals, or files.
+ TGL's patch for cache functions in portage.py so that they do not cache at
+ inappropriate times. PORTAGE_TMPFS is now used if set as a temporary file
+ operation area -- recommended to actually be a ramfs/tmpfs filesystem for
+ speed. Genone enhanced the deprecated profile patch.
+
+ 31 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed --skipfirst
+ bug. This closes #36880.
+
+ 29 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: TGL's patch
+ for imporving overlay verbose. This closes #39765.
+
+ 27 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ autouse bug. autouse were ignored.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Output failed
+ cache updates during emerge sync.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> *: VDB_PATH fixes.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Only use
+ custom profiles when not called by repoman. ROOT never changes profile
+ roots, only custom/system profiles var/cache/edb/virtuals. Sandbox fix
+ where sandbox was creating an invalid logfile (not giving a summary)
+ due to a '/' in SANDBOX_LOG. Turned down the Lockfile output. Double
+ check the INCOMPLETE MERGE identifications as it can be caused by cache.
+
+ 24 Jan 2004; <nakano@gentoo.org> emerge: Improved timestamp check
+ when 'emerge sync'. Added catching amiguous error when unmerge.
+ This closes #24325.
+
+ 23 Jan 2004; <nakano@gentoo.org> emerge, portage.py: Fixed 2 bugs.
+ Portage doesn't read local virtuals file, which happens on only cvs
+ version. package is blocked by itself.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py, emerge:
+ Fix from genone for emerge's direct reading of packages and his patch
+ that also adds in /etc/portage/profile as a stacked profile.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Completed
+ inheritence capabilities for portage.config reading some files. Moved a
+ copy of the getvirtuals() function into settings to handle multiple
+ profiles properly.
+
+*portage-2.0.50_pre17/18/19 (21 Jan 2004): Modules for DBs and quick fixes
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> *: Moved all references
+ to var/db/pkg to portage.VDB_PATH --- This will change again -- NEED TO
+ BE MOVED INTO A PATH/CONSTANTS SETUP.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> dosed: Quick fix for
+ the basename missing/misplaced issue.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added
+ /dev/console to PREDICT to attempt a workaround for a serial console
+ bug. dbkey is now set through portage.py/doebuild to allow for modular
+ db code.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: regen doesn't
+ require root anymore. Edited the timestamp check to be a little more
+ friendly -- delete the portdir timestamp and it won't use the alternate.
+ Fix some permission settings. Added some warnings in for cachedirs that
+ are very likely to ruin your system. Cleaned out some of the eclass code
+ that isnt valid any longer.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portageq: Added vdb_path
+ as a target to get the db directory. Quickpkg uses this.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ load_mod() -- grabs a class/function from a module and passes it back
+ without loading the module into the global scope. Added unique_array()
+ which eliminates duplicates from an array. grab_stacked() operates like
+ the other grab* and getconfig functions, but takes a filename and a set
+ of paths that it will apply incrementally or clobbers -- for profile
+ inheritance. getconfig no longer exits on non-existance returns None.
+ Class config now should be passed a profile path and a set of incremental
+ values instead of using the globals -- defaults to using the globals
+ presently and print an error message. Adding support for module configs
+ as a set of strings 'class.subclass.objectmodule':'module.to.use.object'
+ for load_mod and the database modules. Profile inheritance started. Killed
+ the eclass() super-function and replaced it with class eclass_cache that
+ is visible and conceptually simpler -- Also uses the plugable modules.
+ Cleaned out the sync calls for the DBs. MASSIVE simplification of the
+ aux_get code -- removed memory-caching in favor of system cache (actually
+ faster in all cases so far -- P100 and P4-2.2G). Lockfile usage around the
+ cachefile.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_*: Updated
+ the API a little but to have permissions set properly. A little more
+ reorganization and removed the keycount checks.
+
+ 21 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: download size
+ should not be displayed when the package is nomerge with --tree.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Reverted
+ ambiguity package fix in cpv_expand().
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Moved
+ backup timestamp.chk file from portage tree to PORTAGE_TMPDIR.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Reverted the
+ backing up the timestamp.chk fix.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Improved the
+ list of --tree by TGL's patch. This should close #38070.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Removed debug
+ message without --debug. This should close #23840.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Improved
+ timestamp check of rsync. This should close #37403.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Improved
+ regeneration ld.so.cache. This should close #37858.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed bug which
+ emerge doesn't block same package but different version.
+ (example: DEPEND="!<cat/pkg-1.0.0" in cat/pkg-1.0.0.ebuild)
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py:
+ Modified cpv_expand() to check package.mask. This should close #38592.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Escaped
+ regualar expression for replace entry in fixdbentries().
+
+ 18 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py:
+ Fixed AUTOCLEAN delay problem in .50pre* by TGL's patch. This close
+ #38189. Fixed unmerge failture bug when 'ebuild foo-1.0.0 unmerge'.
+ These close #38189, #38366
+
+ 18 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge, portage.py:
+ Fixed "ebuild /foo/bar-1.0.0.ebuild unmerge" and "emerge bar-1.0.0 unmerge"
+ problems. This should close #38420.
+
+ 17 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ "!<=" style block problem. Fixed symlink with absolute path
+ problem in treewalk().
+
+*portage-2.0.50_pre16 (13 Jan 2004): Quick Fixes -- ~arch version
+
+ 13 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Removed an
+ unnecessary depend call that double eclass-using ebuild's cache regen
+ time.
+
+*portage-2.0.50_pre15 (12 Jan 2004): Quick Fixes -- ~arch version
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Unmerge
+ traceback fix.
+
+*portage-2.0.50_pre14 (12 Jan 2004): Quick Fixes -- ~arch version
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fix for
+ traceback on '-S'.
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Fix for
+ traceback on --help.
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> sandbox: Fix for
+ sandboxpids.tmp file accesses.
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Sandbox, as
+ above. Catch invalid package names and print a sane message about it.
+
+*portage-2.0.50_pre13 (11 Jan 2004): Fixes
+
+ 11 Jan 2004; Nicholas Jones <carpaski@gentoo.org> cnf/*: Updated the
+ Advanced masking section to aid the reduction of user complaints and
+ requests for unreasable usage of ACCEPT_KEYWORDS.
+
+ 11 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: A counter
+ fix was fixed to actually check the counters of all CP versions to ensure
+ the new counter is higher than all existing ones. Modified the dblink
+ class to have class lockfiles for the db and tmpdb dirs as well as lock
+ other files before editing. Reorganization of the merge code in dblink
+ so that the tmpdb is filled immediately after preinst and prior to the
+ actual FS merging -- COUNTER and CONTENTS go directly into the tmpdb
+ and not into the infodir.
+
+*portage-2.0.50_pre11/12 (09 Dec 2003): repoman/binpkg/exit conditions
+
+ 09 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: getbinpkgonly
+ fixes for emerge -G world, should behave properly now instead of using
+ ebuild masks. Only downloads immediately before a merge -- fetchonly now
+ applies to binary packages.
+
+ 08 Jan 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Ignore other
+ arches check in repoman when --ignore-other-arches(-I).
+
+*portage-2.0.50_pre10 (06 Dec 2003): API change + enhancements
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fix for
+ dyn_preinst being called before IMAGE was set -- IMAGE is now valid
+ in pkg_preinst. Added suidctl for SELinux.
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Added -P to
+ initial cvs checkout.
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> quickpkg: Fix for
+ the 'tar up /' problem.
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Caught a
+ traceback generated by bad depend atoms for repoman. Fixes from genone
+ for package.*. Fixed the checks for doebuild calls in treewalk that was
+ ignoring exit conditions for ebuilds.
+
+ 04 Jan 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Added PDEPEND
+ dependency check. This closes #24796
+
+ 04 Jan 2004; Masatomo Nakano <nakano@gentoo.org> repoman, portage.py:
+ Added new dependency check to repoman. This closes #36887.
+
+ 03 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Modified
+ to specific port number in emerge sync. This closes #36994
+
+ 02 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ a problem that emerge doesn't block package when it's required.
+ It happens in .50_pre*.
+
+ 02 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ issue with getsize() when --debug.
+
+ 02 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ issue with virtual. This closes bug #9050, #22225, #29499.
+
+ 01 Jan 2004; Masatomo Nakano <nakano@gentoo.org> ebuild, emerge, portage.py:
+ Fixed issue with not cleaning up temp directory. This closes bug #34967.
+
+ 31 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge:
+ Fixed 'emerge sync' issue which continuously connects to same host.
+
+ 31 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Found the line
+ that was causing the package dir to be printed... It was a spawn call.
+
+ 31 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ the symlink corruption in the db from the movefile() bug.
+
+ 29 Dec 2003; Masatomo Nakano <nakano@gentoo.org> portage.py:
+ Fixed bug which emerge stops when no denpendencies exist in || ( )
+ by USE flags. This closes #36568.
+
+ 29 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge, portage.py:
+ Added an ambiguity package check when emerge. This closes bug #22700.
+
+*portage-2.0.50_pre9 (24 Dec 2003): API change + enhancements
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added
+ PORTAGE_TMPDIR to SANDBOX_READ/WRITE to ensure it works. SpanKY's
+ patch for use negation added (use !foo). pkg_setup doesn't die on
+ a non-zero exit status.
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: using os.uname
+ instead of calling out to uname.
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> quickpkg: Added SpanKY's
+ patch for delayed exit/error conditions.
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> xpak.py: chdir's added
+ to the getcwd fix for missing dirs.
+
+ 24 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge: Added OVERLAY
+ directories display for --verbose.
+
+*portage-2.0.50_pre8 (24 Dec 2003): API change + enhancements
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added
+ /proc/self/maps to SANDBOX_PREDICT, and /dev/shm to read/write.
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added automake
+ and autoconf versions to the output of emerge info.
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: Added
+ edit merged file option -- defaults to EDITOR var or "nano -w".
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Use
+ os.uname instead of calling out to uname which might not exist.
+
+*portage-2.0.50_pre7 (22 Dec 2003): API change + enhancements
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: patch to
+ quote most of the path operators that might involve spaces.
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ invalid entries in package.keywords. Character chopping on mirrors
+ fixed again.
+
+ 21 Dec 2003; Masatomo Nakano <nakano@gentoo.org> bin/ebuild, bin/emerge,
+ pym/portage.py: Changed to show disabled USE flags from use.mask when
+ using emerge -vp. And fixed use.mask issue.
+
+ 20 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Rewrote
+ match_from_list -- Simplified and made pkgcmp and match_from_list
+ properly compare package names.
+
+ 20 Dec 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Fix for mysigs
+ traceback when signing.
+
+ 20 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ PYTHONPATH to the specials list -- created a colon_seperated list.
+ Fixed reset() in class config so that you can specify keeping the
+ pkg dictionary when resetting the values.
+
+ 19 Dec 2003; Masatomo Nakano <nakano@gentoo.org> repoman: Added check
+ whether "ebuild foo.ebuild digest" succeeds.
+
+ 19 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ pkg settings being maintained after an unmerge.
+
+ 19 Dec 2003; Nicholas Jones <carpaski@gentoo.org> pym/portage_db_*: Moved
+ to using cPickle instead of marshal. More standardization of the API.
+
+ 18 Dec 2003; Masatomo Nakano <nakano@gentoo.org> repoman: Added virtual
+ dependency check on each arch.
+
+ 17 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed a
+ permission issue involving $T and userpriv. Lockfile touchup.
+
+ 17 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage_db_*: Added
+ templates and db for cache interfaces. Presently have a anydbm and a
+ flat file interface working. See the test for operations.
+
+ 15 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added a call
+ to portageq that causes python to create optimized modules prior to it
+ ending up inside the sandbox. Added more output and logging to sync.
+
+ 15 Dec 2003; Nicholas Jones <carpaski@gentoo.org> prepstrip: 'tree' is not
+ the same as 'true'.
+
+ 15 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: invalid
+ settings in package.keywords caused a traceback -- fixed with error message.
+
+*portage-2.0.50_pre1 (12 Dec 2003): API change + enhancements
+
+ 10 Dec 2003; Nicholas Jones <carpaski@gentoo.org> chkcontents: Uses portage
+ functions to do md5sum calcs.
+
+ 10 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Removed try()
+ as it isn't used, and was deprecated for a long while. Genone's fetching
+ size display added for --verbose. License display added. Added a little
+ debug for IUSE so we can figure out the binary package --verbose IUSE
+ issues that are randomly reported. XXXXXXXXXXXXXXXXXXX's 'buildsyspkg'
+ patch for building only system packages into tbz2s. Unmerge fix for new
+ settings instances. RSYNC_RATELIMIT added.
+
+ 10 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: ADA path
+ variables added to specials for env_update. Error messaeg correction for
+ make.defaults syntax errors. Unmerge now uses the environment file, if it
+ exists, to get the complete environment back to perform unmerge operations.
+ load_infodir() uses pkg settings completely now. Fixed the passing of
+ settings in unmerge and dblink. Fixed an issue regarding unlinking lockfiles
+ while inside of a sandbox.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh, *.sh:
+ Moved helper scripts into bin/functions and made them sourceable -- they
+ now will die in cases where sub-parts fail. dodoc and keepdir are now
+ recursive-capable.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: emerge.log now
+ set as portage:portage with 0660 perms. --debug now enables tracebacks
+ for dep generation instead of moving code out of the try block.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> g-cpan.pl: rac's patch
+ to get arch list from portage's list of arches in the profiles.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Moved a bit of
+ the existing gpg code around -- it might work as is, but requires 'sign'
+ in features. Fixed a potential for repoman to miss updates that should
+ get a new manifest and commit. Fixed digest/manifest generation for
+ non-packagedir runs of repoman.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emergehelp.py, make.conf,
+ getbinpkg.py: Message touch ups.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: load_infodir()
+ uses pkg settings now instead of env and backup. Genone's custom mirror
+ patch included. Added some missing 'strict' flags for recursion in digest*().
+ Refixed the invalidentry stuff that was lost across patch merges. Fix for
+ pkg-keywords from genone included. Genone's deprecated profile patch for
+ reporting to a user that their current profile is deprecated. Message about
+ missing arch.list instead of spouting invalid keywords messages.
+
+ 08 Dec 2003; Masatomo Nakano <nakano@gentoo.org> repoman:
+ Added all arch dependency check. This closes bug #24160.
+
+ 07 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge,portage.py:
+ Fixed bugs. 1.--debug doesn't work 2.Portage breaks files
+ in /var/db/*/*. 3.No stop if dependency problem happens.
+ They are only cvs version problems.
+
+ 01 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed bug which
+ always remakes info dir file.
+
+ 29 Nov 2003; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed issue with
+ ebuild name rule. Fixed typo with variable name.
+ This closes bug #17172,#34666
+
+ 29 Nov 2003; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed issue with
+ lacking the "setting" argument for pkgmerge()
+
+ 29 Nov 2003; Masatomo Nakano <nakano@gentoo.org> emerge: fixed rsync bug.
+ This closes bug #34660.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Migration
+ to non-global settings started -- class config has new functionality and
+ is locked after portage is finished initializing -- changes cannot be made
+ to the global instance of config 'settings' -- reset() is now functional,
+ setcpv() loads PKGUSE from /etc/portage/package.use, load_infodir() loads
+ all small files (under 4k) from the vardb directory of an installed package
+ so that operations have the same post* settings as they had at merge time.
+ Begin modifications to spawn() to allow for files/pipes to be used for
+ IO instead of using getstatusoutput which does not take an environment
+ parameter like execve(). check_config_instance() ensures that the provided
+ parameter is a 'class config' instance -- for ensuring that everything is
+ being passed properly with the changes. Fix for the local FS mirror issue
+ where it removed the first '/' instead of the last one. doebuild() cleanups
+ for readability and pkguse enhancements -- also remove getstatusoutput()
+ usage for depend so that we don't have to modify the active environment.
+ Fix for symlink mtime values returned from movefile. (Nakano) SLOTMOVE
+ added to global update functionality to fix some issues where a package
+ suddenly must become slotted. portdbapi takes a root parameter instead
+ of using settings. Slightly more useful output from depend. binarytree()
+ now takes a pkgdir instead of using settings. Portage will now die if
+ ebuild.sh exits on a signal.
+
+ Moved some functions around and renamed them for general use -- derived
+ from match2 in class portagetree:
+ match_to_list() find all atoms in a list that match a given package.
+ best_match_to_list() determines the most specific match. Needs work.
+ match_from_list() find all packages in a list that match a given atom.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Fixed an issue
+ with searchdesc wanting root permissions if run as non-root. Migrated to
+ the non-global config class. EMERGE_FROM added for the dyn_preinst patch
+ -- Indicates if a merge is occuring from an ebuild or from a binary. Patch
+ for rsync timestamp checking from Nakano.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Save PKGUSE.
+ Pebeneto's patch for dyn_preinst and SELinux added as a fix for binary
+ and ebuild merges. Added a kill for portage during the depend phase so
+ that portage will actually die if you control-C.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> *: MASSIVE set of changes
+ to start using locally defined 'class config' instances. This allows us to
+ start working on some parallelism among other things. Created this way:
+ mysettings = portage.config(clone=portage.settings)
+
+ The Following functions now take a 'config' parameter:
+ spawn(), fetch(), digestgen(), digestcheck(), spawnebuild(), doebuild(),
+ merge(), dep_opconvert(), dep_check(), dblink.__init__()
+
+ package.keywords is now implemented curtasy of genone/max. PKGUSE was
+ rewritten for the global config killing and is also included. X11 man
+ pages now found and zipped correctly. SYS.PATH fixes for the python
+ migration -- issue actually only shows up on 2.2 systems because of how
+ compiled modules are used if found regardless of the original source's
+ existance.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> tabcheck.py: An easier
+ way to make sure that all the python stuff is correctly using tabs and
+ not mixing spaces.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> xpak, xpak.py: Fixes
+ to ensure that it works if the current dir is missing and that the python
+ path gets set properly.
+
+ 22 Nov 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: Fixed
+ calls in vartree method to invalidentry().... made them call call
+ self.dbapi.invalidentry() (there were multiple wrong method calls.)
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> md5check.py: Checks all
+ digests and SRC_URIs for filenames and associated MD5s. Reports collisions
+ between versions/packages, missing, and extra lines in digests.
+
+*portage-2.0.49-r17/18 (10 Nov 2003): Fixes
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> *: Changed portage to
+ be the first path in sys.path for all python scripts. Also enabled
+ optimizations from the scripts to ensure everything imported is built
+ for speed. ebuild: applied fix for the '//' root breaking the db[].
+ prepstrip: etdyn quickfix
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: fix for
+ RESTRICT=nouserpriv. GENTOO_MIRRORS can have paths set to take files
+ from. Fixes for mishandled cache data regarding *pkgsplit(). Fixes for
+ '*' being returned as part of a package split. An 'invalidentry()' fix
+ for a traceback. Nakano's fixes for virtual removals not working properly,
+ sandbox violations during pkg_nofetch, || depend selection. Genone's
+ fixpackages speedup.
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: PORTAGE_TMPDIR
+ fix for distcc. Variable passing bug patch for export_functions. Exit 1
+ added for nofetch to stop sandbox violation. Nakano's --tree patch added.
+ Improved the unmerge messages to denote what kind of unmerge fails. Info
+ pages regex pattern adjusted to allow most any name for a page.
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> repoman: genone's xml
+ linting additions.
+
+ 01 Nov 2003; Robin H. Johnson <robbat2@gentoo.org> pym/cvstree.py:
+ fix bug #32071, by properly escaping a string to not be a regex. Checked
+ thru entire *.py tree and found this is the only mis-use of strings that
+ need to be escaped.
+
+ 31 Oct 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: /lib/modules
+ now gets "unmerge protection." This is half of the config protection
+ functionality. It means that anything in /lib/modules will not be deleted
+ when a package is unmerged (often automatically when a user merges a
+ kernel module ebuild for a new kernel.) This solves the "my module
+ disappeared!" issue. This closes bug #1477.
+
+ 31 Oct 2003; Daniel Robbins <drobbins@gentoo.org> emerge: Should no longer
+ spit out wacky "!!! no match found" warnings when auto-cleaning.
+
+ 30 Oct 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: Only run
+ depscan.sh if it exists on disk. This allows Portage to run inside a stage1
+ where /sbin/depscan.sh doesn't exist.
+
+ 30 Oct 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: Applied fix to
+ allow multi-level "use? ( )" in SRC_URI, closing bug #16159.
+
+*portage-2.0.49-r15/16 (21 Oct 2003): Fixes
+
+ 21 Oct 2003; Nicholas Jones <carpaski@gentoo.org> fix-db.py: was broken
+ for python2.3 -- fixed now.
+
+ 21 Oct 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ lockfiles to prelink md5 checks. Fixed caching bug where cache objects
+ were passed back as pointers instead of copies. Added 'invalidentry'
+ function to handle lockfiles -- It tests/deletes them using unlockfile.
+ Added fix-db.py to the 'databases is broken' messages.
+
+ 21 Oct 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: added CDPATH
+ to unset. SELinux fix for sandbox.
+
diff --git a/ChangeLog.000 b/ChangeLog.000
new file mode 100644
index 00000000..06895ac4
--- /dev/null
+++ b/ChangeLog.000
@@ -0,0 +1,4288 @@
+# ChangeLog for Portage; the Gentoo Linux ports system
+# Copyright 1999-2004 Gentoo Foundation; Distributed under the GPL v2
+# $Id: ChangeLog.000,v 1.3 2004/10/04 13:58:57 vapier Exp $
+
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+ *** THIS IS FOR ARCHIVAL PURPOSES ONLY -- DO NOT MODIFY ***
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: TGL's fixes
+ for exec/child/wait problems. Unset GREP_OPTIONS GREP_COLOR. has() and use()
+ no longer attempt to determine if they are to be quiet or noisy -- They
+ default to noisy -- useq() and hasq() are the non-verbose versions.
+ EBUILD_PHASE set to add a hack-ish way around global scope calls in
+ eclasses -- NOTHING SHOULD BE CALLED IN THE GLOBAL SCOPE. Touchup to the
+ inherit() code that should finally allow the removal of the ECLASS and
+ INHERITED settings. Removed tty (use/has) calls. Removed dirname calls --
+ portage.py handles setting the dbkey filename now.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Ed Catmur's
+ (with a little TGL added in) patch for --ask. Added a 'metadata' target
+ that skips the sync and only updates the cache. FEATURES="getbinpkg" added.
+ TGL's exit code fixes. Fixed match code for -S so it doesn't complain about
+ specific and double versions. Unmerge via dbpath fix. Rewrote rsync's
+ options that supports --verbose and --quiet operation now and can force
+ checksumming all files using --debug. Sort the files in the cache update
+ so it's a little more predictable.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> prepstrip: changed
+ --strip-debug to --strip-unneeded.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> getbinpkg.py: Updates to
+ enable HTTP/HTTPS authentication.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: best_from_dict
+ added to grab the best entry from set of dicts using a list of the keys for
+ priority. jstubb's patch to fix listdir -- splits it into a cache and list
+ setup. jstubb's patch for varexpand to handle $VAR better. Latexer's patch
+ for KernelVersion code to use Makefiles instead of the version.h. Modules
+ are loaded from /etc/portage/modules or defaults, whichever works. Fixed
+ the /etc/make.profile-is-missing traceback. Spawn can be given 3 pipes to
+ redirect stdin,stdout,stderr to specific outputs, terminals, or files.
+ TGL's patch for cache functions in portage.py so that they do not cache at
+ inappropriate times. PORTAGE_TMPFS is now used if set as a temporary file
+ operation area -- recommended to actually be a ramfs/tmpfs filesystem for
+ speed. Genone enhanced the deprecated profile patch.
+
+ 31 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed --skipfirst
+ bug. This closes #36880.
+
+ 29 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: TGL's patch
+ for imporving overlay verbose. This closes #39765.
+
+ 27 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ autouse bug. autouse were ignored.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Output failed
+ cache updates during emerge sync.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> *: VDB_PATH fixes.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Only use
+ custom profiles when not called by repoman. ROOT never changes profile
+ roots, only custom/system profiles var/cache/edb/virtuals. Sandbox fix
+ where sandbox was creating an invalid logfile (not giving a summary)
+ due to a '/' in SANDBOX_LOG. Turned down the Lockfile output. Double
+ check the INCOMPLETE MERGE identifications as it can be caused by cache.
+
+ 24 Jan 2004; <nakano@gentoo.org> emerge: Improved timestamp check
+ when 'emerge sync'. Added catching amiguous error when unmerge.
+ This closes #24325.
+
+ 23 Jan 2004; <nakano@gentoo.org> emerge, portage.py: Fixed 2 bugs.
+ Portage doesn't read local virtuals file, which happens on only cvs
+ version. package is blocked by itself.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py, emerge:
+ Fix from genone for emerge's direct reading of packages and his patch
+ that also adds in /etc/portage/profile as a stacked profile.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Completed
+ inheritence capabilities for portage.config reading some files. Moved a
+ copy of the getvirtuals() function into settings to handle multiple
+ profiles properly.
+
+*portage-2.0.50_pre17/18/19 (21 Jan 2004): Modules for DBs and quick fixes
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> *: Moved all references
+ to var/db/pkg to portage.VDB_PATH --- This will change again -- NEED TO
+ BE MOVED INTO A PATH/CONSTANTS SETUP.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> dosed: Quick fix for
+ the basename missing/misplaced issue.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added
+ /dev/console to PREDICT to attempt a workaround for a serial console
+ bug. dbkey is now set through portage.py/doebuild to allow for modular
+ db code.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: regen doesn't
+ require root anymore. Edited the timestamp check to be a little more
+ friendly -- delete the portdir timestamp and it won't use the alternate.
+ Fix some permission settings. Added some warnings in for cachedirs that
+ are very likely to ruin your system. Cleaned out some of the eclass code
+ that isnt valid any longer.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portageq: Added vdb_path
+ as a target to get the db directory. Quickpkg uses this.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ load_mod() -- grabs a class/function from a module and passes it back
+ without loading the module into the global scope. Added unique_array()
+ which eliminates duplicates from an array. grab_stacked() operates like
+ the other grab* and getconfig functions, but takes a filename and a set
+ of paths that it will apply incrementally or clobbers -- for profile
+ inheritance. getconfig no longer exits on non-existance returns None.
+ Class config now should be passed a profile path and a set of incremental
+ values instead of using the globals -- defaults to using the globals
+ presently and print an error message. Adding support for module configs
+ as a set of strings 'class.subclass.objectmodule':'module.to.use.object'
+ for load_mod and the database modules. Profile inheritance started. Killed
+ the eclass() super-function and replaced it with class eclass_cache that
+ is visible and conceptually simpler -- Also uses the plugable modules.
+ Cleaned out the sync calls for the DBs. MASSIVE simplification of the
+ aux_get code -- removed memory-caching in favor of system cache (actually
+ faster in all cases so far -- P100 and P4-2.2G). Lockfile usage around the
+ cachefile.
+
+ 21 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage_db_*: Updated
+ the API a little but to have permissions set properly. A little more
+ reorganization and removed the keycount checks.
+
+ 21 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: download size
+ should not be displayed when the package is nomerge with --tree.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Reverted
+ ambiguity package fix in cpv_expand().
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Moved
+ backup timestamp.chk file from portage tree to PORTAGE_TMPDIR.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Reverted the
+ backing up the timestamp.chk fix.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Improved the
+ list of --tree by TGL's patch. This should close #38070.
+
+ 20 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Removed debug
+ message without --debug. This should close #23840.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Improved
+ timestamp check of rsync. This should close #37403.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Improved
+ regeneration ld.so.cache. This should close #37858.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed bug which
+ emerge doesn't block same package but different version.
+ (example: DEPEND="!<cat/pkg-1.0.0" in cat/pkg-1.0.0.ebuild)
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py:
+ Modified cpv_expand() to check package.mask. This should close #38592.
+
+ 19 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Escaped
+ regualar expression for replace entry in fixdbentries().
+
+ 18 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py:
+ Fixed AUTOCLEAN delay problem in .50pre* by TGL's patch. This close
+ #38189. Fixed unmerge failture bug when 'ebuild foo-1.0.0 unmerge'.
+ These close #38189, #38366
+
+ 18 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge, portage.py:
+ Fixed "ebuild /foo/bar-1.0.0.ebuild unmerge" and "emerge bar-1.0.0 unmerge"
+ problems. This should close #38420.
+
+ 17 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ "!<=" style block problem. Fixed symlink with absolute path
+ problem in treewalk().
+
+*portage-2.0.50_pre16 (13 Jan 2004): Quick Fixes -- ~arch version
+
+ 13 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Removed an
+ unnecessary depend call that double eclass-using ebuild's cache regen
+ time.
+
+*portage-2.0.50_pre15 (12 Jan 2004): Quick Fixes -- ~arch version
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Unmerge
+ traceback fix.
+
+*portage-2.0.50_pre14 (12 Jan 2004): Quick Fixes -- ~arch version
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Fix for
+ traceback on '-S'.
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> repoman: Fix for
+ traceback on --help.
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> sandbox: Fix for
+ sandboxpids.tmp file accesses.
+
+ 12 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Sandbox, as
+ above. Catch invalid package names and print a sane message about it.
+
+*portage-2.0.50_pre13 (11 Jan 2004): Fixes
+
+ 11 Jan 2004; Nicholas Jones <carpaski@gentoo.org> cnf/*: Updated the
+ Advanced masking section to aid the reduction of user complaints and
+ requests for unreasable usage of ACCEPT_KEYWORDS.
+
+ 11 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: A counter
+ fix was fixed to actually check the counters of all CP versions to ensure
+ the new counter is higher than all existing ones. Modified the dblink
+ class to have class lockfiles for the db and tmpdb dirs as well as lock
+ other files before editing. Reorganization of the merge code in dblink
+ so that the tmpdb is filled immediately after preinst and prior to the
+ actual FS merging -- COUNTER and CONTENTS go directly into the tmpdb
+ and not into the infodir.
+
+*portage-2.0.50_pre11/12 (09 Dec 2003): repoman/binpkg/exit conditions
+
+ 09 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: getbinpkgonly
+ fixes for emerge -G world, should behave properly now instead of using
+ ebuild masks. Only downloads immediately before a merge -- fetchonly now
+ applies to binary packages.
+
+ 08 Jan 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Ignore other
+ arches check in repoman when --ignore-other-arches(-I).
+
+*portage-2.0.50_pre10 (06 Dec 2003): API change + enhancements
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fix for
+ dyn_preinst being called before IMAGE was set -- IMAGE is now valid
+ in pkg_preinst. Added suidctl for SELinux.
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> emerge: Added -P to
+ initial cvs checkout.
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> quickpkg: Fix for
+ the 'tar up /' problem.
+
+ 06 Jan 2004; Nicholas Jones <carpaski@gentoo.org> portage.py: Caught a
+ traceback generated by bad depend atoms for repoman. Fixes from genone
+ for package.*. Fixed the checks for doebuild calls in treewalk that was
+ ignoring exit conditions for ebuilds.
+
+ 04 Jan 2004; Masatomo Nakano <nakano@gentoo.org> repoman: Added PDEPEND
+ dependency check. This closes #24796
+
+ 04 Jan 2004; Masatomo Nakano <nakano@gentoo.org> repoman, portage.py:
+ Added new dependency check to repoman. This closes #36887.
+
+ 03 Jan 2004; Masatomo Nakano <nakano@gentoo.org> emerge: Modified
+ to specific port number in emerge sync. This closes #36994
+
+ 02 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ a problem that emerge doesn't block package when it's required.
+ It happens in .50_pre*.
+
+ 02 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ issue with getsize() when --debug.
+
+ 02 Jan 2004; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed
+ issue with virtual. This closes bug #9050, #22225, #29499.
+
+ 01 Jan 2004; Masatomo Nakano <nakano@gentoo.org> ebuild, emerge, portage.py:
+ Fixed issue with not cleaning up temp directory. This closes bug #34967.
+
+ 31 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge:
+ Fixed 'emerge sync' issue which continuously connects to same host.
+
+ 31 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Found the line
+ that was causing the package dir to be printed... It was a spawn call.
+
+ 31 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ the symlink corruption in the db from the movefile() bug.
+
+ 29 Dec 2003; Masatomo Nakano <nakano@gentoo.org> portage.py:
+ Fixed bug which emerge stops when no denpendencies exist in || ( )
+ by USE flags. This closes #36568.
+
+ 29 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge, portage.py:
+ Added an ambiguity package check when emerge. This closes bug #22700.
+
+*portage-2.0.50_pre9 (24 Dec 2003): API change + enhancements
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added
+ PORTAGE_TMPDIR to SANDBOX_READ/WRITE to ensure it works. SpanKY's
+ patch for use negation added (use !foo). pkg_setup doesn't die on
+ a non-zero exit status.
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: using os.uname
+ instead of calling out to uname.
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> quickpkg: Added SpanKY's
+ patch for delayed exit/error conditions.
+
+ 24 Dec 2003; Nicholas Jones <carpaski@gentoo.org> xpak.py: chdir's added
+ to the getcwd fix for missing dirs.
+
+ 24 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge: Added OVERLAY
+ directories display for --verbose.
+
+*portage-2.0.50_pre8 (24 Dec 2003): API change + enhancements
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added
+ /proc/self/maps to SANDBOX_PREDICT, and /dev/shm to read/write.
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added automake
+ and autoconf versions to the output of emerge info.
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: Added
+ edit merged file option -- defaults to EDITOR var or "nano -w".
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Use
+ os.uname instead of calling out to uname which might not exist.
+
+*portage-2.0.50_pre7 (22 Dec 2003): API change + enhancements
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: patch to
+ quote most of the path operators that might involve spaces.
+
+ 22 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ invalid entries in package.keywords. Character chopping on mirrors
+ fixed again.
+
+ 21 Dec 2003; Masatomo Nakano <nakano@gentoo.org> bin/ebuild, bin/emerge,
+ pym/portage.py: Changed to show disabled USE flags from use.mask when
+ using emerge -vp. And fixed use.mask issue.
+
+ 20 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Rewrote
+ match_from_list -- Simplified and made pkgcmp and match_from_list
+ properly compare package names.
+
+ 20 Dec 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Fix for mysigs
+ traceback when signing.
+
+ 20 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ PYTHONPATH to the specials list -- created a colon_seperated list.
+ Fixed reset() in class config so that you can specify keeping the
+ pkg dictionary when resetting the values.
+
+ 19 Dec 2003; Masatomo Nakano <nakano@gentoo.org> repoman: Added check
+ whether "ebuild foo.ebuild digest" succeeds.
+
+ 19 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ pkg settings being maintained after an unmerge.
+
+ 19 Dec 2003; Nicholas Jones <carpaski@gentoo.org> pym/portage_db_*: Moved
+ to using cPickle instead of marshal. More standardization of the API.
+
+ 18 Dec 2003; Masatomo Nakano <nakano@gentoo.org> repoman: Added virtual
+ dependency check on each arch.
+
+ 17 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed a
+ permission issue involving $T and userpriv. Lockfile touchup.
+
+ 17 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage_db_*: Added
+ templates and db for cache interfaces. Presently have a anydbm and a
+ flat file interface working. See the test for operations.
+
+ 15 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added a call
+ to portageq that causes python to create optimized modules prior to it
+ ending up inside the sandbox. Added more output and logging to sync.
+
+ 15 Dec 2003; Nicholas Jones <carpaski@gentoo.org> prepstrip: 'tree' is not
+ the same as 'true'.
+
+ 15 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: invalid
+ settings in package.keywords caused a traceback -- fixed with error message.
+
+*portage-2.0.50_pre1 (12 Dec 2003): API change + enhancements
+
+ 10 Dec 2003; Nicholas Jones <carpaski@gentoo.org> chkcontents: Uses portage
+ functions to do md5sum calcs.
+
+ 10 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Removed try()
+ as it isn't used, and was deprecated for a long while. Genone's fetching
+ size display added for --verbose. License display added. Added a little
+ debug for IUSE so we can figure out the binary package --verbose IUSE
+ issues that are randomly reported. XXXXXXXXXXXXXXXXXXX's 'buildsyspkg'
+ patch for building only system packages into tbz2s. Unmerge fix for new
+ settings instances. RSYNC_RATELIMIT added.
+
+ 10 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: ADA path
+ variables added to specials for env_update. Error messaeg correction for
+ make.defaults syntax errors. Unmerge now uses the environment file, if it
+ exists, to get the complete environment back to perform unmerge operations.
+ load_infodir() uses pkg settings completely now. Fixed the passing of
+ settings in unmerge and dblink. Fixed an issue regarding unlinking lockfiles
+ while inside of a sandbox.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh, *.sh:
+ Moved helper scripts into bin/functions and made them sourceable -- they
+ now will die in cases where sub-parts fail. dodoc and keepdir are now
+ recursive-capable.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emerge: emerge.log now
+ set as portage:portage with 0660 perms. --debug now enables tracebacks
+ for dep generation instead of moving code out of the try block.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> g-cpan.pl: rac's patch
+ to get arch list from portage's list of arches in the profiles.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Moved a bit of
+ the existing gpg code around -- it might work as is, but requires 'sign'
+ in features. Fixed a potential for repoman to miss updates that should
+ get a new manifest and commit. Fixed digest/manifest generation for
+ non-packagedir runs of repoman.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> emergehelp.py, make.conf,
+ getbinpkg.py: Message touch ups.
+
+ 09 Dec 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: load_infodir()
+ uses pkg settings now instead of env and backup. Genone's custom mirror
+ patch included. Added some missing 'strict' flags for recursion in digest*().
+ Refixed the invalidentry stuff that was lost across patch merges. Fix for
+ pkg-keywords from genone included. Genone's deprecated profile patch for
+ reporting to a user that their current profile is deprecated. Message about
+ missing arch.list instead of spouting invalid keywords messages.
+
+ 08 Dec 2003; Masatomo Nakano <nakano@gentoo.org> repoman:
+ Added all arch dependency check. This closes bug #24160.
+
+ 07 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge,portage.py:
+ Fixed bugs. 1.--debug doesn't work 2.Portage breaks files
+ in /var/db/*/*. 3.No stop if dependency problem happens.
+ They are only cvs version problems.
+
+ 01 Dec 2003; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed bug which
+ always remakes info dir file.
+
+ 29 Nov 2003; Masatomo Nakano <nakano@gentoo.org> portage.py: Fixed issue with
+ ebuild name rule. Fixed typo with variable name.
+ This closes bug #17172,#34666
+
+ 29 Nov 2003; Masatomo Nakano <nakano@gentoo.org> emerge: Fixed issue with
+ lacking the "setting" argument for pkgmerge()
+
+ 29 Nov 2003; Masatomo Nakano <nakano@gentoo.org> emerge: fixed rsync bug.
+ This closes bug #34660.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Migration
+ to non-global settings started -- class config has new functionality and
+ is locked after portage is finished initializing -- changes cannot be made
+ to the global instance of config 'settings' -- reset() is now functional,
+ setcpv() loads PKGUSE from /etc/portage/package.use, load_infodir() loads
+ all small files (under 4k) from the vardb directory of an installed package
+ so that operations have the same post* settings as they had at merge time.
+ Begin modifications to spawn() to allow for files/pipes to be used for
+ IO instead of using getstatusoutput which does not take an environment
+ parameter like execve(). check_config_instance() ensures that the provided
+ parameter is a 'class config' instance -- for ensuring that everything is
+ being passed properly with the changes. Fix for the local FS mirror issue
+ where it removed the first '/' instead of the last one. doebuild() cleanups
+ for readability and pkguse enhancements -- also remove getstatusoutput()
+ usage for depend so that we don't have to modify the active environment.
+ Fix for symlink mtime values returned from movefile. (Nakano) SLOTMOVE
+ added to global update functionality to fix some issues where a package
+ suddenly must become slotted. portdbapi takes a root parameter instead
+ of using settings. Slightly more useful output from depend. binarytree()
+ now takes a pkgdir instead of using settings. Portage will now die if
+ ebuild.sh exits on a signal.
+
+ Moved some functions around and renamed them for general use -- derived
+ from match2 in class portagetree:
+ match_to_list() find all atoms in a list that match a given package.
+ best_match_to_list() determines the most specific match. Needs work.
+ match_from_list() find all packages in a list that match a given atom.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Fixed an issue
+ with searchdesc wanting root permissions if run as non-root. Migrated to
+ the non-global config class. EMERGE_FROM added for the dyn_preinst patch
+ -- Indicates if a merge is occuring from an ebuild or from a binary. Patch
+ for rsync timestamp checking from Nakano.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Save PKGUSE.
+ Pebeneto's patch for dyn_preinst and SELinux added as a fix for binary
+ and ebuild merges. Added a kill for portage during the depend phase so
+ that portage will actually die if you control-C.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> *: MASSIVE set of changes
+ to start using locally defined 'class config' instances. This allows us to
+ start working on some parallelism among other things. Created this way:
+ mysettings = portage.config(clone=portage.settings)
+
+ The Following functions now take a 'config' parameter:
+ spawn(), fetch(), digestgen(), digestcheck(), spawnebuild(), doebuild(),
+ merge(), dep_opconvert(), dep_check(), dblink.__init__()
+
+ package.keywords is now implemented curtasy of genone/max. PKGUSE was
+ rewritten for the global config killing and is also included. X11 man
+ pages now found and zipped correctly. SYS.PATH fixes for the python
+ migration -- issue actually only shows up on 2.2 systems because of how
+ compiled modules are used if found regardless of the original source's
+ existance.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> tabcheck.py: An easier
+ way to make sure that all the python stuff is correctly using tabs and
+ not mixing spaces.
+
+ 28 Nov 2003; Nicholas Jones <carpaski@gentoo.org> xpak, xpak.py: Fixes
+ to ensure that it works if the current dir is missing and that the python
+ path gets set properly.
+
+ 22 Nov 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: Fixed
+ calls in vartree method to invalidentry().... made them call call
+ self.dbapi.invalidentry() (there were multiple wrong method calls.)
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> md5check.py: Checks all
+ digests and SRC_URIs for filenames and associated MD5s. Reports collisions
+ between versions/packages, missing, and extra lines in digests.
+
+*portage-2.0.49-r17/18 (10 Nov 2003): Fixes
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> *: Changed portage to
+ be the first path in sys.path for all python scripts. Also enabled
+ optimizations from the scripts to ensure everything imported is built
+ for speed. ebuild: applied fix for the '//' root breaking the db[].
+ prepstrip: etdyn quickfix
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: fix for
+ RESTRICT=nouserpriv. GENTOO_MIRRORS can have paths set to take files
+ from. Fixes for mishandled cache data regarding *pkgsplit(). Fixes for
+ '*' being returned as part of a package split. An 'invalidentry()' fix
+ for a traceback. Nakano's fixes for virtual removals not working properly,
+ sandbox violations during pkg_nofetch, || depend selection. Genone's
+ fixpackages speedup.
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: PORTAGE_TMPDIR
+ fix for distcc. Variable passing bug patch for export_functions. Exit 1
+ added for nofetch to stop sandbox violation. Nakano's --tree patch added.
+ Improved the unmerge messages to denote what kind of unmerge fails. Info
+ pages regex pattern adjusted to allow most any name for a page.
+
+ 10 Nov 2003; Nicholas Jones <carpaski@gentoo.org> repoman: genone's xml
+ linting additions.
+
+ 01 Nov 2003; Robin H. Johnson <robbat2@gentoo.org> pym/cvstree.py:
+ fix bug #32071, by properly escaping a string to not be a regex. Checked
+ thru entire *.py tree and found this is the only mis-use of strings that
+ need to be escaped.
+
+ 31 Oct 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: /lib/modules
+ now gets "unmerge protection." This is half of the config protection
+ functionality. It means that anything in /lib/modules will not be deleted
+ when a package is unmerged (often automatically when a user merges a
+ kernel module ebuild for a new kernel.) This solves the "my module
+ disappeared!" issue. This closes bug #1477.
+
+ 31 Oct 2003; Daniel Robbins <drobbins@gentoo.org> emerge: Should no longer
+ spit out wacky "!!! no match found" warnings when auto-cleaning.
+
+ 30 Oct 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: Only run
+ depscan.sh if it exists on disk. This allows Portage to run inside a stage1
+ where /sbin/depscan.sh doesn't exist.
+
+ 30 Oct 2003; Daniel Robbins <drobbins@gentoo.org> portage.py: Applied fix to
+ allow multi-level "use? ( )" in SRC_URI, closing bug #16159.
+
+*portage-2.0.49-r15/16 (21 Oct 2003): Fixes
+
+ 21 Oct 2003; Nicholas Jones <carpaski@gentoo.org> fix-db.py: was broken
+ for python2.3 -- fixed now.
+
+ 21 Oct 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ lockfiles to prelink md5 checks. Fixed caching bug where cache objects
+ were passed back as pointers instead of copies. Added 'invalidentry'
+ function to handle lockfiles -- It tests/deletes them using unlockfile.
+ Added fix-db.py to the 'databases is broken' messages.
+
+ 21 Oct 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: added CDPATH
+ to unset. SELinux fix for sandbox.
+
+*portage-2.0.49-r13/14 (10 Oct 2003): Fixes
+
+ 10 Oct 2003; Nicholas Jones <carpaski@gentoo.org> *: Full adaptations
+ for python2.3 implemented. Installation setup for /usr/lib/portage/pym
+ instead of site-packages. Fix for Old-Instance unmerging which stopped
+ happening due to changed path names. Binaries shouldn't merge under
+ fetchonly.
+
+*portage-2.0.49-r11/12 (08 Oct 2003): Internal Only.
+
+*portage-2.0.49-r10 (08 Oct 2003): Fixes
+
+ 08 Oct 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed a
+ seemingly random traceback involving lockfiles -- Categories weren't
+ being created before a lockfile was attempted in the category directory.
+ More enhancements to aid migration to python-2.3. Added writemsg() as
+ a general function for outputting information -- Takes an argument that
+ is interpreted as debug level and prints synchronisly to stderr. Yanked
+ domenu pending a GLEP.
+
+*portage-2.0.49-r9 (07 Oct 2003): Fixes
+
+ 07 Oct 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Atomic lock
+ updates and self.create() fixes. Counter enhancements.
+
+*portage-2.0.49-r8 (05 Oct 2003):
+
+ 05 Oct 2003; Nicholas Jones <carpaski@gentoo.org> *: Changed #! line to
+ use /usr/bin/python to aid in migration.
+
+ 05 Oct 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: More use/has
+ output fixups.
+
+ 05 Oct 2003; Nicholas Jones <carpaski@gentoo.org> emerge: General cleanups.
+ Added in baselayout info to emerge info. --skipfirst isn't a persistent
+ option on resume anymore.
+
+ 05 Oct 2003; Nicholas Jones <carpaski@gentoo.org> fix-db.py: New script to
+ aid in diagnosing and eventually fixing /var/db issues. It makes almost no
+ modifications at the moment.
+
+ 05 Oct 2003; Nicholas Jones <carpaski@gentoo.org> prepstrip: Addition of
+ a condition for etdyn binaries -- they list as shared objects but aren't.
+
+ 05 Oct 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Added non-cvs
+ patch -- repoman can be used outside of cvs trees for scanning/checking.
+ Added a masking fix for packages that use 'arch?' dependencies. Permission
+ fix on stats pickle.
+
+ 05 Oct 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Subversion
+ directories are ignored along with CVS in listdir() when ignorecvs is set.
+ USE_EXPAND is fixed. Global and package counter fixes. ATOMIC VARDB moves
+ are now implemented -- Still need a way to recover broken operations.
+ Counter functions are now implemented in dbapi only. vardbapi now implements
+ aux_get for all possible files listed in the package's info directory. New
+ functions: lockfile()/lockdir(), unlockfile()/unlockdir().
+
+*portage-2.0.49-r7 (26 Sep 2003): Binary package fixes + spacing issues.
+
+ 26 Sep 2003; Nicholas Jones <carpaski@gentoo.org> emerge.sh: Spacing fixes
+ for tab/space mixes. glob fix for getgccversion().
+
+ 26 Sep 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for binary
+ use flag tb.
+
+ 26 Sep 2003; Nicholas Jones <carpaski@gentoo.org> xpak.py: Fix for scan()
+ tb when file is invalid or shorter than XPAK header length.
+
+*portage-2.0.49-r6 (23 Sep 2003): SELinux, DistCC, and pretend output fixes.
+
+ 23 Sep 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: selinux context
+ fixes -- using ${T} now. DISTCC_DIR added by default and given an addwrite.
+
+ 23 Sep 2003; Nicholas Jones <carpaski@gentoo.org> emerge: gccversion() added
+ to help distcc and the version checking calls that break distcc permissions.
+ Fix for create() and the useflag passing from binary packages. When using
+ pkgs, is_newer_ver_installed() no longer trashes ebuild names. Don't look
+ for fetch restrictions with binary packages. Included a modified patch that
+ shows only in-slot versions for packages during pretend output -- In-slot
+ now shows up exactly as a single-slot package would -- New slots show up
+ as new packages -- proper output. Killed debug for everything except regen
+ which now shows the deps being regenerated. Fixed regen to ignore keywords
+ just like sync does already... should fix a few missing cache entry problems
+ on rsync1 and speed up sync times all around.
+
+ 23 Sep 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Additions for
+ distcc support.
+
+
+*portage-2.0.49-r5 (19 Sep 2003): Fixes
+
+ 19 Sep 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Make
+ DISTCC_DIR set if not defined.
+
+ 19 Sep 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Fix for -U
+ introduced bugs with Str+None tracebacks. Mild change to log info -- Added
+ short pkgname before ebuild. Eclassdb changes and flush/save calls.
+
+ 19 Sep 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Unregister
+ signal handling after receiving the signal and resend the signal we got.
+ Run depscan during env-update. Migrated eclass stuff into it's own pickle.
+ Code for moving /var/cache/edb/dep into a pickle for each category added --
+ disabled via hardcoded value presently. Removed some try blocks in favor
+ of detecting the cause of an error first -- Hopefully gives a little speed
+ up. Cache fixes and useful output added. A tbz2 moving bug where an error
+ was printed about files the destination existing already is now fixed. The
+ dircache is cleared on every unmerge now, to ensure the cache does not
+ interfere. bzip2 is spawned with the quiet flag now. Update list is sorted
+ for proper year/quarter order now. -arch isn't an invalid keywork anymore.
+ Generic pickle reading and writing functions added.
+
+*portage-2.0.49-r4 (10 Sep 2003): Fixes
+
+ 10 Sep 2003; Nicholas Jones <carpaski@gentoo.org> *: Added the facility
+ to incorporate binary package use flags when calculating deps. Changes in
+ -r2 and -r3 included quick fixes to SELinux code and the addition of
+ LINGUAS to USE_EXPAND.
+
+*portage-2.0.49-r1 (25 Aug 2003): Fixes
+
+ 25 Aug 2003; Nicholas Jones <carpaski@gentoo.org> emerge: -K traceback fix.
+ Made fetchonly quit traversing the merge code after fetching.
+
+ 25 Aug 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Removed
+ auxcache saving code -- A few bugs and caching problems need to be resolved.
+ Moved a block of code in aux_get inside of an existing conditional -- Should
+ provide a small speedup.
+
+*portage-2.0.49 (22 Aug 2003): GRP downloading, Selinux, General Fixes
+
+ 22 Aug 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Make
+ auxcache saving more friendly.
+
+*portage-2.0.49_pre20/21 (20 Aug 2003): Fixes + security enhancements
+
+ 20 Aug 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ auxcache saving.
+
+*portage-2.0.49_pre19 (20 Aug 2003): Fixes + security enhancements
+
+ 20 Aug 2003; Nicholas Jones <carpaski@gentoo.org> *: Updates to Wayne's
+ modifications on dispatch-conf.
+
+ 20 Aug 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: sfperms
+ added to strip permissions if set in features. selinux context support.
+ Nakano's cleanups for unmerge output. Added distcc and ccache versions
+ into emerge info's output. 'autoaddcvs' FEATURE is documented in make.conf.
+
+ 20 Aug 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Selinux code
+ added. No longer traceback on cp_list for categories. Added in a patch to
+ use a pickle for auxcache storing. Should help slow IO boxes.
+
+*portage-2.0.49_pre18 (15 Aug 2003): Fixes.
+
+ 15 Aug 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Nakano's
+ fix for a glob expansion bug on a tar call.
+
+ 15 Aug 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Nakano's fixes
+ for exiting on a signal and incorrect output for the unmerge screen.
+
+ 15 Aug 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added in
+ patch to shuffle thirdparty mirrors. Nakano's fixes for digests+fetching
+ bugs/messages/errors. Virtual stripping fix.
+
+ 15 Aug 2003; Nicholas Jones <carpaski@gentoo.org> *: Fix to emerge -V
+ and related output. Typo fixes. Parent thread no longer drops root in
+ userpriv. 'autoaddcvs' feature now determines if portage will auto-add
+ files to cvs. Virtuals fix for an empty key line. Added user categories
+ file as /etc/portage/categories.
+
+*portage-2.0.49_pre17 (30 Jul 2003): Resuming/wget GRP, Sandbox updates
+
+ 30 Jul 2003; Nicholas Jones <carpaski@gentoo.org> *: GRP updates to
+ use RESUMECOMMAND to determine how to download GRP binaries. Adjustments
+ to the portage.spawn() code to try and speed it up by eliminating the
+ copy phase (copy-on-write forking). Massive messages for corrupt FS issues.
+ Movefile() checks to ensure we actually complete the moves. Killed the
+ broken pipe message for tbz2 extraction.
+
+*portage-2.0.49_pre16 (29 Jul 2003): Touchups
+
+ 29 Jul 2003; Nicholas Jones <carpaski@gentoo.org> *: Clean up the debug
+ output and quickfix downloading tbz2s.
+
+*portage-2.0.49_pre15 (29 Jul 2003): Fixes
+
+ 29 Jul 2003; Nicholas Jones <carpaski@gentoo.org> repoman: imported time.
+
+ 29 Jul 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Corrected the
+ logic used to determine whether a package or an ebuild is used when given
+ the option.
+
+ 29 Jul 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Changed a
+ lot of calls using 'print' into sys.stderr.write() calls. Added try/except
+ around the source lstat to catch funky errors where the file doesn't really
+ exist -- Presents descriptions to users about what to do. Added more catches
+ for movefile() calls to ensure it dies on failures. Changed the tbz2
+ extraction call to stop the 'cat: broken pipe' message.
+
+*portage-2.0.49_pre14/48-r7 (24 Jul 2003): Fixes and getbinpkg caching
+
+ 22 Jul 2003; Nicholas Jones <carpaski@gentoo.org> *: Typo fixes for
+ the ECLASS_DEPTH comparisons in ebuild.sh. Traceback fixes for blocking
+ packages in depclean and in pretend. Caching added to getbinpkg code --
+ generation of cache supported, but cachefile is staticly located. Langs
+ patch from Nakano in bug #9988 included.
+
+*portage-2.0.49_pre13 (22 Jul 2003): Fixes
+
+ 22 Jul 2003; Nicholas Jones <carpaski@gentoo.org> doman: Doesn't gzip
+ .keep files now.
+
+ 22 Jul 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: USERLAND
+ fix. ** ECLASS depth tracker and additions to the new depend code. **
+
+ 22 Jul 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Fetch restriction
+ now adds a red F to the pretend output. Made the blockers message better.
+ Added 'local' to rsync excludes to allow the category to be added for admins.
+
+ 22 Jul 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed a TB
+ caused by a missing 'strict' reference --- Needs to be fixed better. Fixed
+ a typo in the populate code for bintree/getbinpkg.
+
+*portage-2.0.49_pre11 (16 Jul 2003): GRP, General, VIDEO_CARDS/INPUT_DEVICES
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> quickpkg: SpanKY's
+ friendly edition now included.
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: USE_EXPAND
+ support for expanding bash variables into USE --- VIDEO_CARDS="blah"
+ USE="video_cards_blah". Added a notice about fetching metadata so you
+ can see that it's happening.
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> make.globals*: Added
+ default CHUNKSIZE for binhosts. Added defaults for USE_EXPAND which is
+ used to expand variables into USE from the give names.
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> *: Debug removal.
+
+*portage-2.0.49_pre10 (16 Jul 2003): GRP and General Fixes
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> *:
+ Quick fix for a breakage in the GRP --getbinpkg code.
+
+*portage-2.0.49_pre9 (16 Jul 2003): GRP and General Fixes
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: add
+ LDFLAGS and ASFLAGS. Exports are only done if vars are already set.
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added support for
+ --getbinpkg and --getbinpkgonly --- GRP complement. Fixes for blocking-
+ not-working bug
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Patch to detect
+ incomplete digests.
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: ebuild fetch
+ now checks md5sums (run from ebuild). Support for getbinpkg.
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> xpak.py: Added more in-
+ memory operations support.
+
+ 16 Jul 2003; Nicholas Jones <carpaski@gentoo.org> getbinpkg.py: Supporting
+ code for binary package retrieval.
+
+*portage-2.0.48-r2 (29 Jun 2003): Fixes and Multiple Overlays
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fixed the
+ commands for tar.
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Mode the chdir
+ to fix the spanky bugs down to post_emerge to fix the "can't merge an
+ ebuild file with an absolute path" bug.
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added function
+ suffix_array(array,suffix) which takes an array and adds suffix to the end
+ of each element. Added 'cd / ;' into the getstatusoutput() calls to ldconfig.
+ Added a check so that portage doesn't try to add files/dir from a non-cvs
+ directory. Added 'manifest' target to ebuild/portage to only adjust the
+ manifest. Added Multiple overlay support -- Should be fairly thorough --
+ needs more debug though. Fixed portdbapi::new_protect_filename().
+
+*portage-2.0.48-r2 (29 Jun 2003): Cleanups and Fixes (testing)
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Lots of
+ consistency cleanups. Added more files to the var/db data for future
+ use. Added more die conditions to failure points. Fixed/Hacked a fix
+ into the inherit-not-dieing problem. Set TMPDIR and TMP globally. Added
+ notice for multiple inheritance. Fixed inheritance problem with multiple
+ inheritance clobbering previous list of eclasses. Basic support for
+ multiple overlays added to ebuild.sh.
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> emerge: SRC_URI fix for
+ 'rm /etc/*' problem. Spanky bug: chdir to / to avoid problems when merging
+ from inside a builddir that gets deleted.
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: Added notice
+ for symlinks in cfg_prot setups.
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> repoman: complain if
+ FEATURES=cvs not set.
+
+ 29 Jun 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added in
+ a work around for the 'USE=+useflag' users. Added support for nouserpriv
+ via RESTRICT. Fix the bug with ROOTs with no previous file causing a TB
+ from counter_tick(). Make symlinks follow config_protect just like normal
+ files.
+
+ 10 Jun 2003; Daniel Robbins <drobbins@gentoo.org> ebuild.sh, portage.py,
+ various commands in bin/, cnf/make.conf.mac, cnf/make.globals.mac:
+ Added preliminary Mac OS X/BSD support.
+
+ 06 Jun 2003; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: new eclass
+ dependency implementation to totally isolate eclass dependency tweaks
+ from in-ebuild dependency tweaks. eclasses now absolutely do not touch
+ DEPEND and RDEPEND. Any dependencies added by eclasses are transferred
+ to another variable and added in to DEPEND and RDEPEND after the entire
+ ebuild has been processed, and after RDEPEND has optionally inherited a
+ value from DEPEND due to it being unset. The result of this change is
+ that inherit statements no longer need to be placed strategically in an
+ ebuild so that they are after the DEPEND and RDEPEND, and fix a host of
+ other eclass mis-use/side-effect bugs.
+
+*portage-2.0.48-r1 (29 May 2003): Touchups.
+
+ 29 May 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Quick fixes
+ to a couple of rare bugs. Added some quoting to $S. Removed the DISTCC
+ hosts variable. Moved build-info's creation around so that it actually
+ works for non-portage-compiled merges.
+
+ 29 May 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Quick fix for
+ the files-dir-not-added lack of notification. Added in a fix for a possible
+ security problem with the repoman commit messages and symlink-attacks.
+
+ 29 May 2003; Nicholas Jones <carpaski@gentoo.org> cnf/*: Added in a diff
+ from 'Danny' that contained a SYNC cleanup and expanded explanation. :)
+
+ 29 May 2003; Nicholas Jones <carpaski@gentoo.org> output.py: Fixed the
+ TitleBar and unset TERM issues.
+
+ 29 May 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added new
+ functions to aid in determining virtuals. cpv_all() added to dbapi -- it
+ displays all versions instead of just package names -- cp_all() now calls
+ this function to gain it's data. get_provide() and get_all_provides() added
+ to collect PROVIDE info from vartree packages. getallcpv() added to vartree
+ to reference the dbapi call. Always set ignoring errors on findname now.
+ Cleaned up the virtuals-trimming code. Don't mention the fixpackages script
+ if the user doesn't have any packages.
+
+*portage-2.0.48 (20 May 2003): Cleanups Release.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Tiny cleanups.
+ Fixed the profile information in emerge -V for symlinks that have a
+ trailing '/' in them. Fix 'emerge -s' filesize lookups to use a new
+ function finddigest() from dbapi.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> emergehelp.py: Updated.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: Small
+ fixups for pager issues. Made the nothing-to-do exit message 'happier'.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> extra-functions.sh:
+ Beat the debian-utils requirement out of the functions. Prefers them,
+ but falls back to already-existing tools otherwise.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> fixpackages: 75%
+ overhaul to match the new handling of update code.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> quickpkg: Understands
+ "--help" as an option now.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> man/*: Simple updates.
+
+ 20 May 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: fetch()
+ now calculates md5sums when doing a fetchonly. finddigest() added for
+ finding digests -- gets overlay digests if existing. Binary packages
+ are only updated when explicitly requested via fixpackages as a command
+ or a FEATURES setting. Clear the dircache after portage initializes to
+ reduce memory consumption.
+
+*portage-2.0.48_pre6 (12 Apr 2003): General cleanups and fixes.
+
+ 12 May 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Additions
+ to better handle overlay ebuilds with regard to metadata cache. aux_get
+ calls findname2() which returns (location,in_overlay) -- findname() is
+ a wrapper for findname2(). Extra debugging fixes for findname() issues.
+
+ 12 May 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Code
+ cleanups and a chgrp/chown pass to move all portage-owned files to
+ root ownership -- Two pass to leave specific-group and specific-owner
+ settings alone.
+
+ 12 May 2003; Nicholas Jones <carpaski@gentoo.org> emerge: code cleanups
+ and comment touchups.
+
+ 12 May 2003; Nicholas Jones <carpaski@gentoo.org> emergehelp.py: Updates
+ for --debug, --digest, and --skipfirst.
+
+ 12 May 2003; Nicholas Jones <carpaski@gentoo.org> g-cpan.pl: Added more
+ arches to the KEYWORDS. Made it copy files back to distfiles.
+
+ 12 May 2003; Nicholas Jones <carpaski@gentoo.org> prepstrip: Removed ${D}
+ from the outputted filenames during stripping.
+
+ 12 May 2003; Nicholas Jones <carpaski@gentoo.org> man/* cnf/*:
+ documentation updates.
+
+*portage-2.0.48_pre5 (29 Apr 2003): Cleanups and polish.
+
+ 29 Apr 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Another
+ typo fix.
+
+*portage-2.0.48_pre4 (28 Apr 2003): Cleanups and polish.
+
+ 28 Apr 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Quick fix
+ for a traceback/typo in the 'emerge -C' code.
+
+*portage-2.0.48_pre3 (28 Apr 2003): Cleanups and polish.
+
+ 28 Apr 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: listdir()
+ now takes care of non-existance errors instead of propagating them --- can
+ take EmptyOnError=1 as a param to return [] instead of None. All calls to
+ portage's listdir() have been updated to the new conventions. listdir()
+ ignores .# files from cvs now when ignorecvs=1 is set. Fixes for another
+ world-depleting bug. If findname() is passed a virtual, it now informs
+ the user to report a bug, instead of weird tracebacks. Added code in
+ dblink::unmerge() to remove stale virtual entries when set under trimworld.
+
+ 28 Apr 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: enabled the
+ diff pager again.
+
+ 28 Apr 2003; Nicholas Jones <carpaski@gentoo.org> emerge: --changelog
+ implies --pretend. Spelling fixes. Added --skipfirst to allow the first
+ package in a resume operation to be skipped over --- allows -e to rebuild
+ almost everything, even under weird circumstances. Located another missed
+ world-file-depleting bug in unmerge() calls. Included a patch to fix an
+ off-by-one bug in depclean.
+
+ 27 Apr 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ listdir() running on a non-existant dir -- returns None. Sets generated
+ files to the portage group -- Manifest & digests. Some coloring additions.
+ Handling of 'strict' features added. TEMPORARY addition of 'manifest' USE
+ flag so this can go mainstream now. Fixes in doebuild() to get unmerge
+ working again for ebuild. Debug code added to findname to help figuring
+ out the seemingly random tracebacks -- suspect is pkgsplit(). Unmasking
+ code for package.mask added in -- works just like mask, and can override
+ specific versions or ranges -- One per line: /etc/portage/package.unmask.
+ Security fix for python cPickle code -- mtimedb could create arbitrary
+ execution of code bug. Global update notices/info. Fixes for loops over
+ listdir() that depended upon raised errors to determine code flow.
+
+ 27 Apr 2003; Nicholas Jones <carpaski@gentoo.org> cvstree.py: Added in
+ 'removed' status checks.
+
+ 27 Apr 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Added in more
+ cvs checks. /space/cvsroot is now complained about.
+
+ 27 Apr 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added in
+ PORTAGE_CALLER support to identify it as a 'do_update()' candidate.
+
+ 27 Apr 2003; Nicholas Jones <carpaski@gentoo.org> dodoc: Check sizes to
+ prevent 0 byte files from being added.
+
+*portage-2.0.48_pre2 (10 Apr 2003): Digests & Repoman
+
+ 16 Apr 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Added CVS/Root
+ checks to ensure Manifests will be correct. Fixed local use-flag bug.
+ Commented out the no-stable code, as it can't be implemented well as is.
+
+ 16 Apr 2003; Nicholas Jones <carpaski@gentoo.org> prepstrip: Fixed a
+ problem where files were not being stripped.
+
+ 16 Apr 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added in
+ a call to 'make -n' when under the --debug flag.
+
+*portage-2.0.48_pre1 (10 Apr 2003): Digests & Repoman
+
+ 10 Apr 2003; Nicholas Jones <carpaski@gentoo.org> prepstrip: fix it so
+ that it actually strips and provides reasonable info.
+
+ 10 Apr 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Added short
+ option for pretend. Added pretend capability to the majority of the
+ commit code. Bug fix for local IUSE code. Added in support for removed
+ cvs files.
+
+ 10 Apr 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Changed
+ 'manifest' to 'Manifest'. Removed the requirement that Manifests exist --
+ complain about it, but only die if 'strict' is set.
+
+*portage-2.0.47-r15 (09 Apr 2003): New digests/manifests, touchups.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> bin/*: Fixes for Cross-
+ compiling.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Quick touchups
+ in the category- and repository-level manifest calls.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> cnf/*: Added/sync'd
+ PORTAGE_NICENESS.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed hole
+ in the listdir code that occured on cache expiration in the -r14 changes.
+
+*portage-2.0.47-r14 (09 Apr 2003):
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> bin/*: Removed DEBUGBUILD
+ in favor of FEATURES/RESTRICT settings of nostrip.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> ebuild: Removed root
+ restriction so that digests can be made as non-root.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added niceness
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Added the
+ nostable/allmasked check in. Small cleanups. Move to 'manifests' instead
+ of enhanced digests. Added filters on $Id and $Header. Fixed commitmsg
+ and added short options.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> cvstree.py: More features
+ added. pathdata() provides dir or file info. isadded() gives cvs status.
+
+ 09 Apr 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: listdir()
+ enhancements. Debug removal. Broke up the digest creation functions to
+ make them a little more generic. Added manifest code into the digest
+ calls. Moved code in doebuild() around to allow for non-root calls for
+ devs and repoman. Added 'PORTAGE_CALLER' env var to prevent repeated
+ running of unnecessary functions.
+
+*portage-2.0.47-r13 (02 Apr 2003): Fixes & Security -- Repoman+Digests
+
+ 02 Apr 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added debug to
+ the dep selection code in depgraph.
+
+ 02 Apr 2003; Nicholas Jones <carpaski@gentoo.org> cvstree.py: Added new
+ module to handle cvs information without having to ask 'cvs status' many
+ times to determine file locations.
+
+ 02 Apr 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Major fix ups
+ to ease the introduction of enhanced digests. Intelligent cvs queries
+ and use of the new cvstree module for information about files in the tree.
+ Auto-digests, auto-fetches trivial cvs changes, detects changelogs that
+ exist but have not been added to cvs, and detects '*' in KEYWORDS.
+
+ 02 Apr 2003; Nicholas Jones <carpaski@gentoo.org> *: A typo fix or two.
+ prepstrip: fixup for sed's issues with '\000' (made it \001).
+
+*portage-2.0.47-r12 (27 Mar 2003): Fixes & Security -- Repoman+Digests
+
+ 27 Mar 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Moved all
+ initialization error messages to stderr.write() calls so that the output
+ doesn't get mixed will called data. Added a warning about not being in
+ the portage group. Color touchups. Digest path fixups.
+
+ 27 Mar 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Significant
+ additions to the commit code to nicely handle the changes for enhanced
+ digests. Added --commitmsg and --commitmsgfile flags to allow easier
+ scripting. Added a REPOMAN environment variable to prevent portage from
+ running do_updates(). Added 'grouplist' which makes groupings of subparts
+ from a list of parts. Added do* functions to manage the recursion into
+ the dirs of the repository.
+
+ 27 Mar 2003; Nicholas Jones <carpaski@gentoo.org> xpak.py: Change from
+ lstat to stat... We're not concerned with links. Return 0 on not found.
+
+ 27 Mar 2003; Nicholas Jones <carpaski@gentoo.org> portageq: added new
+ functions: best_visible, mass_best_visible, all_best_visible.
+
+ 27 Mar 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added '--digest'
+ to force recreation of digests from the command line. Fixed portage version
+ comparisions for the 'update portage please' notices.
+
+ 27 Mar 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added an
+ extra rm of the 'successful' file.
+
+ 26 Mar 2003; Alain Penders <alain@gentoo.org> portageq: added
+ mass_best_version method to help GUIs resolve best versions.
+
+*portage-2.0.47-r11 (22 Mar 2003): Fixes & Security -- Winding up 2.0 series.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: listdir()
+ now is capable of recursive calls and listing only files. Used in new
+ additions to digestgen() and digestcheck() for ebuilds and files/* --
+ listdir(dir,recursive=0,filesonly=0). Digests now must contain all files
+ from files/ and also the ebuild -- non-archives are prefixed with '/'.
+ Full tbz2 fixes are now implemented... They can take a while to perform
+ so status thingies are provided. update_ents() provides a batch-update
+ as it would take rediculous amounts of time otherwise.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> : fixpackages calls
+ portageexit() to save the mtimedb state so it actually works. :)
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added
+ 'xtermTitle' calls to emergelog to set the title during phases of merging.
+ Added more emergelog calls to provide more specific information.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> : Added two scripts to
+ aid portage. 'fixdbentries' takes (old, new, path) and does an inteligent
+ sed on all the db entries that should be changed. Used by global moves and
+ in the tbz2 fixes. 'fixpackages' expires the updates timestamp and reloads
+ portage to force do_updates() to run. Added missing Header lines.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> xpak.py: Correct off-by-8
+ bug in last commit. infosize does not contain the full size... Offset
+ begins _after_ the marker -- Added xpaksize for complete offset from EOF.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix for
+ die-on-wheel-group-missing bug. The logfiles don't cause the counter
+ to be incremented and now match the merged package's COUNTER value.
+ get_counter_tick_core(root) does not increment the counter. Sandbox is
+ now working in all enabled cases, instead of just usersandbox. /var/db
+ and binaries (assuming they are RW) are now updated to contain the proper
+ info --- Added a 'fixdbentries' script to perform the updates to the data,
+ and added a 'move_ent' function to class binarytree (not fakedbapi). Added
+ a 'ebuild does not exist' error for the case of ebuilds in a wrongly named
+ directory. Added a notice for invalid tbz2's. Removed the 'make.defaults'
+ missing notice :-/. Duplicated the bintree creation so that it would be
+ available for do_update(). Catch when 'updates' is missing from mtimedb.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> output.py: Added xterm
+ title bar function to set the titles... xtermTitle(mystring). Only set
+ if using color and terminal is [axE]term.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> repoman: Additions
+ courtesy of Gerk and Vladamir... Checks all portage variables. Runs
+ a check against invalid (but still parsable) syntax errors in names.
+ Checks for invalid IUSE from use.desc and use.local.desc. Checks that
+ licenses are valid. Checks for legal keywords with a default set or
+ keywords.desc, if available. 'missingvar' tests moved to aux_get() calls.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> prepstrip: Added test
+ to allow cross-compile-stripping to work properly. Rewrite the script to
+ be whitespace-aware and recursively process directories at level 1.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> prepallstrip: Removed
+ all code from this script and made it a call to "prepstrip $D".
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> g-cpan.pl: Add in chomps
+ for the portageq calls.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Allow
+ --fetchonly of block'd packages.
+
+ 22 Mar 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Cleanups and
+ corrections for sandbox which has been disabled and broken for a couple
+ revisions now. use_{enable,with} die messages removed as they are in sub-
+ shells when used and won't kill the merge --- Moved to echo >&2.
+
+ 21 Mar 2003; Nicholas Jones <carpaski@gentoo.org> xpak.py: Updates to make
+ the xpak code self-sustaining. Added basic documentation to the functions
+ and a description of the format in the comments at the top of the module.
+
+*portage-2.0.47-r10 (13 Mar 2003): Fixes -- Winding up 2.0 series.
+
+ 13 Mar 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Less strict
+ check of permissions when fixing permissions for userpriv -- only requires
+ 02070 and group portage instead of 02770 for check.
+
+ 13 Mar 2003; Nicholas Jones <carpaski@gentoo.org> g-cpan.pl: Fix to the
+ call to portageq.
+
+ 13 Mar 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: Fix for
+ deleted files in a CONFIG_PROTECT situation.
+
+ 13 Mar 2003; Nicholas Jones <carpaski@gentoo.org> emerge: fix for keepwork
+ and keeptemp ** MUST ENSURE THAT CLEAN CLEANS BEFORE A FULL MERGE.
+
+ 12 Mar 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added more
+ conditions on rsync -- Proper error detection. Rsync failures will not
+ cause a cache regeneration. Portage no longer considers masked portages
+ candidates for 'An update to portage'.
+
+*portage-2.0.47-r9 (10 Mar 2003): Fixes -- cvs-src, ebuild.sh, repoman
+
+ 10 Mar 2003; Nicholas Jones <carpaski@gentoo.org> make.conf*: Adjusted
+ the LOGDIR message and change the default location to /var/log/portage.
+
+ 10 Mar 2003; Nicholas Jones <carpaski@gentoo.org> repoman: One more fix
+ for the PORTDIR setting -- '/usr/portage' was matching '/usr/portage.cvs'.
+
+ 10 Mar 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: Added the
+ capability to automerge all files in the list -- with out without prompts.
+
+ 10 Mar 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Added messages
+ on failure to create a depgraph -- Helps with bad DEPEND detection. Made
+ 'emerge sync' stop if it fails, and not update cache.
+
+ 10 Mar 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: added an
+ external extra_functions.sh file with extra functions for portage --
+ it is flag-o-matic and pieces of eutils presently. Removed libdir/incdir
+ from einstall(). Added 'keepwork' to keep the source code after a package
+ is merged. Removed the 'local' declaration of ROOT in dyn_install() --
+ this fixes has_version in src_install(). Fixed the sourcing of environment
+ so that variables are peristent across stages of a merge. Removed the
+ SANDBOX vars from the environment file, as that upsets SANDBOX.
+
+ 10 Mar 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixes to
+ permission problems with cvs-src and ccache (removed nested try's). Log
+ counter fix -- One log per package now.
+
+*portage-2.0.47-r8 (02 Mar 2003): Fixes -- cvs-src, ebuild.sh, repoman
+
+ 02 Mar 2003; Nicholas Jones <carpaski@gentoo.org> *: Fixes to eclass
+ errors and messages -- raise on not found. emerge --debug works for
+ ebuilds with syntax errors now -- needs better implimentation though,
+ debug=0 in params can't be used due to scope limits.
+
+ 28 Feb 2003; Nicholas Jones <carpaski@gentoo.org> *: reorg ebuild.sh again
+ to ensure that aliases are expanded properly. Repoman now determines the
+ proper PORTDIR to set when loading portage to scan the cvs tree. portage.py
+ fixes for cvs-src permission problems with userpriv.
+
+*portage-2.0.47-r7 (27 Feb 2003): Quick fix for eerror() problem.
+
+*portage-2.0.47-r6 (26 Feb 2003): Drop deprecated warnings for new syntax.
+
+ 26 Feb 2003; Alain Penders <alain@gentoo.org> emerge: Drop deprecated
+ warnings for new syntax. Don't make people switch to the new syntax
+ until it's agreed on by everyone.
+
+*portage-2.0.47-r5 (26 Feb 2003): Wicked Fast, BugFree v3.1, UserPriv
+
+ 26 Feb 2003; Nicholas Jones <carpaski@gentoo.org> *: Update docs and help
+ again to drop --system and --world, and pull them from emerge's command
+ line. General cleanups.
+
+ 26 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge/portage.py: Fixes
+ to the cache directory permissions -- all dirs are properly owned by group
+ portage now. Add CCACHE_SIZE setting so we set a value for ccache. If the
+ dirs are set to the wrong perms, make sure they get changed recursively.
+
+ 26 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Rearraged the
+ code blocks so that they are easier to follow -- no more code in between
+ functions. All code follows function definitions now.
+
+*portage-2.0.47-r4 (25 Feb 2003): Wicked Fast, BugFree v3, UserPriv
+
+ 25 Feb 2003; Nicholas Jones <carpaski@gentoo.org> *: Update docs and help
+ to match the deprecation of actions without '--' preceding them.
+
+ 25 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Message
+ updates. Fix secpass for portage user. Set PORTAGE_GID for ebuild.sh to
+ use regardless of GID in use (wheel/portage). Only try and delete things
+ in PORTAGE_TMPDIR if we have perms to do it... see secpass note. Moved the
+ cachedir creation after settings in created so that we can use spawn instead
+ of system for the calls to 'chown/chmod -R'. Fix the note on make.defaults.
+ Fix for the 404 catcher in the fetch code.
+
+ 25 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Move all actions
+ into '--action' form -- Notify of deprecated usages. Moved the functions
+ from the top of emerge down below the command line parser for readability.
+ Kill FEATURES=noauto if we're running emerge -- it can break things. Make
+ -U imply -u so people aren't confused. --debug now enables all debug
+ variables in portage. Fix wheel/portage group requirements messages. Get
+ the current portage version when doing rsync via the portage tree's files
+ and not the loaded cache so that it is aware of changes immediately instead
+ of the next run.
+
+ 25 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Try to change
+ to good a good path at the start of the ebuild to prevent operations from
+ happening in places like home. After the ebuild's install phase, check to
+ see if any unsafe perm combo's exist and die if they do. Fix permissions
+ on the cachedir as we're changing them to root:portage. &> on environment
+ file prevented it from actually creating the file -- changed to 2>. Change
+ 'true' to 'exit 0' to be a bit more explicit about what we're doing.
+
+ 24 Feb 2003; Alain Penders <alain@gentoo.org> repoman: Added nested/sub-shell
+ die testing.
+
+ 23 Feb 2003; Alain Penders <alain@gentoo.org>: Added bin/portageq tool to
+ provide access to portage internal information without using APIs that
+ are changing. All tools that currently access portage information by
+ importing portage.py and poking around in it should switch to using this
+ tool instead. Changed some tools in bin/ to use it, so those won't break
+ either.
+
+*portage-2.0.47-r3 (17 Feb 2003): Wicked Fast, BugFree v2, UserPriv
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> bin/: added dispatch-conf
+ and db-fix.pl to the bins. Looking at dispatch-conf to replace etc-update
+ written by Jeremy Wohl (bug 14079). db-fix.pl is a rescue tool that Blizzy
+ wrote up to recreate/repair counter files in the DB -- shouldn't be needed
+ anymore as portage fixes the counter at every load of the counter, but we
+ will hang on to it just in case.
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: moved the
+ wheelgid references to portage_gid references. Wheel is being deprecated.
+ Added notice to baselayout message that group portage controls everything
+ now. Killed the BASH_ENV settings -- moved the reference to /etc/portage/
+ in case it's desired in some way -- This fixes AROUND ONE HUNDRED reports
+ on 2.0.47-r2. Try/catch invalid tbz2's -- should fix a couple bad tarball
+ bugs. Make the prelink call spawn'd without sandbox. buildpkg/userpriv
+ fix via actionmap (Jasmin Buchert; bug 16106).
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: --upgradeonly
+ added from jrray's patch; added some slot handling. --deep got a short
+ flag 'D'. 'info' can be run by non-root. '--quiet' kills all but package
+ names on searches. Basic slot detection added to the pretend output so
+ that it doesn't always say downgrade. Ignore block list when fetching.
+ Can use RSYNC_EXCLUDEFROM to select a from for rsync to --exclude-from;
+ (Michael Sterrett; Bug 15882). 'emerge rsync' deletes the dbcachedir
+ before it begins updates. Catch exceptions during rsync cache regen.
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: General fixes
+ to the spelling of things. 'cd $PORT_TMPDIR' corrected to the actual vars
+ name. Stripping distcc from PATH if it is there before portage sets it.
+ Same with ccache. If we try to compile with out unpacking, complain. Make
+ sure to chown files to user portage.
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> cnf/*: CFLAGS notes,
+ pentium4 breaks things. Added more descriptions for FEATURES. Added
+ RSYNC_EXCLUDEFROM description.
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> *: Updates to the
+ copyright headers.
+
+*portage-2.0.47-r2 (17 Feb 2003): Wicked Fast, BugFree, UserPriv
+
+ 18 Feb 2003; Alain Penders <alain@gentoo.org> portage-2.0.47-r2.ebuild:
+ If $PORTAGE_TEST is set, skip the beeps/delay messages. Needed to make
+ the regression test scripts bearable :-)
+
+ 17 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed the
+ depcache code once again -- ebuild and cache were never set to the same
+ mtimes. Removed last os.system() call.
+
+ 17 Feb 2003; Nicholas Jones <carpaski@gentoo.org> repoman: catdir fix.
+ Added 'emerge-webrsync' from gentoolkit so users can use snapshots on
+ initial installs.
+
+ 17 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emergehelp.py: Updated
+ it to the current calls and conventions. Added comments about etc-update
+ and emerge-webrsync.
+
+ 17 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Changed the
+ search code around to use compiled re's instead of .lower() searches.
+ Trivial touchups in spacing. Only write worldfile if not --pretend. Fix
+ losing-packages-to-be-merged during merge bug. Allow options to change
+ in a --resume call so that --buildpkg and such may be added.
+
+ 17 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Added a
+ PREROOTPATH to allow special paths to be added prior to root and ebuild's
+ required pathes. ${S} is now generated prior to sourcing an ebuild so
+ that it is available in the ebuild at source-time, as opposed to in the
+ phases.
+
+*portage-2.0.47-r1 (16 Feb 2003): Wicked Fast + UserPriv
+
+ 16 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Changed a
+ few os.system calls to spawn calls. Added userpriv in features check to
+ spawn. HOME is now placed in BUILD_PREFIX/homedir when userpriv is enabled.
+ Valid command for doebuild() moved to the top of the function. Reorganized
+ the directory creation code in doebuild(). HOME is cleaned for every merge
+ if in userpriv. LOG_COUNTER fix for the per-ebuild logs -- Only one value
+ is used per $PF now.
+
+ 16 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Adjusted options
+ to remove --autoclean and make it on-by-default unless killed in FEATURES
+ with 'noclean'. Removed debug for --resume. Added RSYNC_TIMEOUT as some
+ dialup and other users are experiencing problems with rsync never finishing
+ a connection. Added check at the end of an rsync to notify the user when
+ a new version of portage is available. Added --pretend capability/fix to
+ the --resume code. No resume data and a --resume is no longer a failure.
+
+ 16 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Updates to
+ logic of ${T}/successful handling to allow proper cleaning. dyn_clean()
+ will do a recursive dir removal after cleaning specific files. Recursive
+ chown removed. CCACHE_DIR handled in portage.py now. Removed a few comments
+ and unnecessary checks.
+
+ 16 Feb 2003; Nicholas Jones <carpaski@gentoo.org> cnf/*: added comments
+ on FEATURES=noclean,noauto,userpriv,usersandbox
+
+ 15 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Alain changed
+ the .config() call in the search class to a .settings[] -- Speedup.
+
+ 14 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ resume to mtimedbkeys.
+
+ 14 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: --columns
+ flag to support column output in --pretend. --resume support added
+ to restart portage with the package list with which it stopped -- data
+ is stored in mtimedb. Added '--verbose' to 'emerge info' to display
+ all variables in settings.
+
+ 13 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fix to
+ distcc and ccache to prevent them from calling themselves if they
+ catch themselves in the path -- double path problem.
+
+ 13 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixes to
+ the aux_get() code for metacache updates to eclass deps. Debug output
+ removal.
+
+ 13 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: More fixes
+ to the calls to aux_get() for metacache code. Rearranged the option and
+ action arrays. Added --nospinner flag.
+
+ 13 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: Reorg of flags.
+ Addition of --noconfmem to prevent portage from yanking already-merged
+ config files. Extra message in --version about missing gcc and sourcing
+ /etc/profile to get it. Yanked the majority of the rsync cachedb update
+ code -- Moved it to aux_get.
+
+ 13 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Typo fixes.
+ aux_get() now has a metacachedb param for using metadata cache over the
+ initial call to doebuild() -- Should speed up rsync users regen time.
+ Added support for --noconfmem via settings["NOCONFMEM"] in treewalk().
+ Added sys.exit(1) on failure to move files during merge. Comment
+ realignment.
+
+ 11 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Fix the
+ depcache code by adding in a missing stat call after regeneration.
+ Call portageexit() in exithandler() so that mtimedb gets written out
+ on cancelled runs. Add in --quiet option. Currently only kills the
+ processing messages on emerge regen.
+
+ 11 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fix the
+ eclass code to remove the double inherits cause by eclasses managing
+ that on their own.
+
+*portage-2.0.46-r12 (07 Feb 2003): Fixups
+
+ 07 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Move
+ logdir check/generation code so that it's created before 'clean'. Fix
+ the usemask/archkeys bug and a related bug with the var enabled. Fix
+ to movefile() code to ensure symlinks are handled properly.
+
+ 07 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Make per-
+ ebuild logs use the counter to get a chronological list instead of a
+ timestamp based one.
+
+ 07 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: If a package
+ is requested to be updated but is not merged, still add it to world.
+
+ 07 Feb 2003; Nicholas Jones <carpaski@gentoo.org> *: Update to help.
+ Mostly comments on --verbose. Clarification on make.conf* mirrorselect.
+
+*portage-2.0.46-r11 (04 Feb 2003): Fixups
+
+ 04 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: distcc
+ fixups along with ccache fixups from the bug 13897 effort. Added more
+ varaibles to the build data output. Allow CC/CXX to be set if they are
+ not set in environment.
+
+ 04 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Removed an
+ unnecessary call to os.unlink() in movefile that resulted in it failing
+ when moving files across devices. HTML 404 catcher -- if the distfile is
+ a reasonable size, and it's got <title>.*(not found|404).*</title> in it
+ it will be deleted and the next mirror persued.
+
+*portage-2.0.46-r10 (03 Feb 2003): Feature/Function Cleanups
+
+ 03 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Added
+ quotes to fallback checksum code to ensure it works on space-containing
+ filenames. Error message added in writedict. Worldfile-depleeting bug
+ fixed -- 'emerge -e world'+AUTOCLEAN would cause every package in world
+ to be removed from the worldfile to be removed.
+
+ 03 Feb 2003; Nicholas Jones <carpaski@gentoo.org> make.conf: updated the
+ commentary about AUTOCLEAN.
+
+ 03 Feb 2003; Nicholas Jones <carpaski@gentoo.org> etc-update: Added in
+ automerge functionality for trivial changes. Comments and whitespace
+ are just merged without asking when it's enabled.
+
+ 03 Feb 2003; Nicholas Jones <carpaski@gentoo.org> emerge: redundant cmd
+ line flags warning. Show enabled/disabled USE flags on -vp (Masatomo
+ Nakano). Missing changelog fix for --changelog. Added an rsync timeout
+ of 60 seconds and a message on fail due to timeout.
+
+ 03 Feb 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: CC/CXX fix
+ to override profile.env settings. FEATURES=distcc support to get past
+ profile.env's CC settings/lockdown. If CBUILD is defined, it is appended
+ to econf's output in a --build= statement. Added .unpacked marker to
+ the unpack code to ensure a proper unpack phase.
+
+ 01 Feb 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Adjusted
+ the arch.list code to be a general masking setup. /etc/make.profile/
+ and /etc/portage/ have use.mask files that are concatenated. On fetch,
+ if downloader reports failure, then check that filesize<digestfilesize
+ and continue onto the next mirror before dying.
+
+ 27 Jan 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh/portage.py:
+ eclass fixups for newdepend issues where newdepend operates on RDEPEND
+ prior to it being set to default by ebuild.sh. Repoman fix for multi-
+ arch failures by excluding /usr/portage/profiles/arch.list entries from
+ consideration, excluding $ARCH.
+
+*portage-2.0.46-r9 (14 Jan 2003): portage restart fix
+ 15 Jan 2003; Nicholas Jones <carpaski@gentoo.org> emerge: fixed the
+ missing tabs from the cvs diff backport.
+
+*portage-2.0.46-r8 (14 Jan 2003): touchup KV{,ERS} for public stable
+
+*portage-2.0.46-r7 (14 Jan 2003): Backport from cvs and fixes.
+ portage-2.0.46* :: EXCUDES ALL PORTIONS RELATING SPECIFICALLY TO USERPRIV
+
+ 14 Jan 2003; Nicholas Jones <carpaski@gentoo.org> portage.py: Persistant
+ KV and KVERS on depend calls. Sandbox violation of do_upgrade() caught.
+
+ 14 Jan 2003; Nicholas Jones <carpaski@gentoo.org> emerge: --buildpkg
+ touchups and forward porting of some of 2.0.46-r6. Restart on -r0/proper
+ versions of portage due to VERSION not matching pkgsplit output fixed.
+
+ 14 Jan 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: 20% speedup
+ in dep generation by removing all external app calls. Moved KVERS to
+ portage to make it persistent during dep calls. Other code moved into
+ conditionals based on $*!=depend. chmod's swaped with umask.
+
+ 11 Jan 2003; Jack Morgan <jmorgan@gentoo.org> cnf/make.conf.sparc:
+ updated make.conf.sparc to add CFLAGS for sparc32 and sparc64
+
+ 08 Jan 2003; Nicholas Jones <carpaski@gentoo.org> bin/g-cpan.pl:
+ Added from bug 3450 -- Creates and merges perl module ebuilds on-the-fly
+ from cpan and merges them.
+
+ 08 Jan 2003; Mark Guertin <gerk@gentoo.org> cnf/make.conf.ppc:
+ updated make.conf.ppc to remove G3 options for CFLAGS and other
+ small tweaks
+
+*portage-2.0.47 (06 Jan 2003): UserPriv
+
+ 06 Jan 2003; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Forced HOME to BUILD_PREFIX regardless of user. Added in a 'rm -Rf' notice
+ to readonly-fs/Full-Disk notices. Disabled the usepkg on buildpkg function
+ of portage. digraph.hasallzeros() added -- Determines if tree is zero depth.
+
+ 06 Jan 2003; Nicholas Jones <carpaski@gentoo.org> cnf/*: Added in the
+ PORT_LOGDIR option and description. Also added a GENTOO_MIRRORS section
+ back into the make.conf* files so that users are aware that they need to
+ specify ibiblio. Killed the linefeeds in the sparc conf.
+
+ 06 Jan 2003; Nicholas Jones <carpaski@gentoo.org> emerge: options and
+ actions fixup. Added new short options and long options. --buildpkgonly
+ now works and restricts the process to deplists of zero depth. Updated
+ the help for portage, and created a seperate shorthelp function with
+ the terse, options-only, versions of the regular help. Fixed the env_update
+ call after --fetchonly runs.
+
+ 06 Jan 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh:
+ touchups to the user priv and logging code to kill the invalid user
+ messages when portage:portage doesn't exist on the system.
+
+*portage-2.0.47_pre4 (03 Jan 2003): UserPriv Works + Per-Ebuild logging
+
+ 04 Jan 2003; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ tokenize() fixups to remedy the || reduce problems.
+
+ 04 Jan 2003; Nicholas Jones <carpaski@gentoo.org> prepall:
+ Fixup for '//' problem.
+
+ 03 Jan 2003; Nicholas Jones <carpaski@gentoo.org> ebuild.sh:
+ Support for per-ebuild logging via PORT_LOGDIR variable. ebuild.sh
+ now can do usermode compiles _and_ maintain the enviroment with a
+ few minor restrictions like changing portage variables.
+
+*portage-2.0.47_pre3 (02 Jan 2003): Forward port of fixes & New fixes
+
+ 02 Jan 2003; Nicholas Jones <carpaski@gentoo.org> emerge:
+ tbz2 handling improved -- checks current, pkgdir/All/x, pkgdir/x.
+ -r0 removal on current ver to stop people from complaining about it.
+ More info added to 'emerge info' output.
+
+ 02 Jan 2003; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Spaces in filenames fix for prelink-capable systems. Exception caused
+ by invalid or unsatisfiable '||' dependancies caught and warned about.
+ auxdbkey order fix. dbcachedir now ensures a '/' before the cache dir.
+
+ 02 Jan 2003; Nicholas Jones <carpaski@gentoo.org> prep*:
+ Fixes from Azarah to make the included files more proper.
+
+ 26 Dec 2002; Phil Bordelon <sunflare@gentoo.org> man/emerge.1:
+ Added documentation of the --deep option.
+
+*portage-2.0.46-r5 (30 Dec 2002): Touchups and sparc confs
+
+ 30 Dec 2002; Nicholas Jones <carpaski@gentoo.org> *:
+ fix for prelink unmerge problems. small touches to outputs.
+ sparc configs added. Azarah's fixups for the prep* scripts.
+ Changes to 'emerge info' output. tbz2 prefixes PKGDIR/All if the
+ tbz2 doesn't exist in the current dir.
+
+*portage-2.0.46-r3 (24 Dec 2002): Backport of fixes in 2.0.47_pre2
+
+*portage-2.0.47_pre2 (24 Dec 2002): Feature: userpriv compiles
+
+ Tokenizer fixup courtasy of Evgeny Roubinchtein. unalias -a in ebuild.sh.
+ Moved the help() to emergehelp.py. prepallman fixup for missed symlinks.
+ More info provided for portage-user-missing message. FEATURES=sandboxuser
+ not provides sandbox in compile phase along with userpriv. mtimedb
+ exception should actually be caught now.
+
+*portage-2.0.47_pre1 (21 Dec 2002): Feature: userpriv compiles
+
+ 21 Dec 2002; Nicholas Jones <carpaski@gentoo.org> *:
+ ebuild.sh: portage user setup. dyn_setup is always run before calls to
+ unpack,compile,install. emerge: infodirs cleanup, traceback on invalid
+ dir fix. Proper regen on info change. portage.py: uid/gid discovery and
+ check code. PRELINK_PATH and PRELINK_PATH_MASK added and renamed. Made
+ HOME set to BUILD_PREFIX when HOME is unset. Patched in UserPriv compile
+ code and checks and complaints to ensure smooth integration. Reorganized
+ chown calls to ensure things get set right for userpriv and not. Sandbox:
+ UID check to prevent non-root errors patched in.
+
+*portage-2.0.46-r2 (18 Dec 2002): Feature Stable Release Prelink + Bug Fixes
+
+ 18 Dec 2002; Nicholas Jones <carpaski@gentoo.org> portage.py, emerge:
+ Traceback fix for blocking packages in the restart check in emerge. Added
+ missing import for commands in portage.py.
+
+*portage-2.0.46 (18 Dec 2002): Feature Stable Release Prelink + Bug Fixes
+
+ 18 Dec 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ PRELINK_MASK adds ignore paths for prelink.conf. Error message
+ adjustments for appearance/readability. auxdbkey changes.
+
+ 18 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ --changelog displays changelogs of packages on update. gcc version
+ fix for --version. Missing indent in masked output corrected. Some
+ color additions. Prelink code removed -- Users can do it instead.
+
+ 18 Dec 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh:
+ use_{enable,with}() work now. Rearranged auxdbkeys again.
+
+ 17 Dec 2002; Martin Schlemmer <azarah@gentoo.org> bin/ebuild.sh:
+ Regenerate /lib/cpp and /usr/bin/cc in pkg_setup if they are not
+ files to ease the broken pkg_postrm() some gcc have.
+
+*portage-2.0.46_pre2 (15 Dec 2002): Feature Prerelease: prelink
+
+ 15 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge/portage.py:
+ Fixups. PRELINK_MASK code. 'prelink -af' in post_emerge().
+
+ 15 Dec 2002; Mark Guertin <gerk@gentoo.org> cnf.make.conf.ppc:
+ updated incorrect CFLAG option and appended -mabi=altivec info
+
+*portage-2.0.46_pre1 (15 Dec 2002): Feature Prerelease: prelink
+
+ 15 Dec 2002; Nicholas Jones <carpaski@gentoo.org> portage.py: Counter
+ fixups. Prelink code.
+
+ 15 Dec 2002; Nicholas Jones <carpaski@gentoo.org> bin/f*: Made them
+ loop over multiple files instead of just doing one.
+
+ 13 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge/portage.py:
+ Added disabled prelink code. Needs a little more work. Gave portage the
+ ability to restart on upgrades to the portage version. Ebuilds for prior
+ versions will intentionally die on upgrade. USE=build disables it so
+ bootstrap isn't affected.
+
+*portage-2.0.45-r5 (13 Dec 2002): Feature addition: PDEPEND+fixes
+
+ 13 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge/portage.py:
+ Added restart on portage upgrade code and adjusted ebuild to accomplish
+ this until version matches -r5.
+
+*portage-2.0.45-r4 (11 Dec 2002): Feature addition: PDEPEND
+
+ 11 Dec 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh/portage.py:
+ Added [CDEPEND, PDEPEND, REBUILD] to auxdbkeys and updated ebuild.sh.
+ Prevented autoclean on fetchonly.
+
+ 11 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Added support for PDEPEND. Rewrote some dep handling variables for
+ readability and ease of use.
+
+*portage-2.0.45-r3 (09 Dec 2002): Touchups.
+
+ 09 Dec 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fixed
+ use_enable() and use_with() so that they actually work -- also don't
+ have to specify 2nd parameter, 1st is assumed.
+
+ 09 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge: Added previous
+ version/downgrade messages to --pretend. Extra message to notify of dep
+ calculation failure as bad deps can exit portage without error.
+
+ 09 Dec 2002; Nicholas Jones <carpaski@gentoo.org> portage.py: Attempt
+ at fixing the sandbox-crashes-missing-HOME bug. Added a try/catch around
+ the virts/'del x' code to prevent tracebacks on boxes without a virtuals
+ file.
+
+ 06 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge: Fixed 'xfrom'
+ variable-used-before-assignment message on masked ebuilds.
+
+ 06 Dec 2002; Nicholas Jones <carpaski@gentoo.org> portage.py: Disabled
+ writes to DBs when sandbox is enabled.
+
+ 03 Dec 2002; Nicholas Jones <carpaski@gentoo.org> portage.py: Fixed a
+ nice bug where python was writing 'L' at the end of long() types for
+ mtimes.
+
+*portage-2.0.45 (02 Dec 2002): More bug fixes for stable.
+
+ 02 Dec 2002; Nicholas Jones <carpaski@gentoo.org> portage.py, output.py:
+ Added several color options and functions to output.py. 'DO NOT EDIT'
+ notices added to .env generated profile settings files. Touchups and
+ nofetch() call for restricted fetches. Moved some file IO code for
+ SLOTs into a try/catch. { mtimedb fixups. Eclass aux_get() error fix.
+ aux_get() error fix via try/catch with magically-missing ebuild when
+ doing stat on it. Enabled full eclass()/inherit code. Added code to
+ flushmtimedb() entries by key name. } <-- aux_get() fixups. Made
+ starttime into a long... time.time() is apparently overflowing int().
+
+ 02 Dec 2002; Nicholas Jones <carpaski@gentoo.org> bin/*:
+ prep*: Fixed missed man pages and corrected loops to be fairly complete
+ in the included files. quickpkg: Loop to do each in $@ (Peter Sharp).
+
+ 02 Dec 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Yank '++' from searches and make it '\+\+' so that it works. Reformated
+ 'all ebuilds are masked' message to be a little more obvious. env_update()
+ AFTER autoclean... not in autoclean -- Fixes ldconfig issues. Typo fixes.
+
+ 02 Dec 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh:
+ Added has(), general use()-like function -- 'has this_thing $VAR' returns
+ shell true or false. Added has_version(), portage call to determine if
+ a specified DEPEND-atom is installed -- 'has_version ">=mozilla-1.2"'
+ returns shell true or false. Added best_version(), portage call to
+ get the best/most-recently-merged version of a DEPEND-atom statement --
+ 'best_version ">=mozilla-1.0"' prints a string. pkg_nofetch() displays
+ SRC_URIs by default on RESTRICT -- Can be redefined to display custom
+ messages. die() on unpack() failure added. Courtasy of SpanKY: Added
+ use_with() and use_enable() for --with-thing and --enable-thing.
+ 'use_with gd libgd' would print --with-libgd if gd was in USE and
+ --without-libgd if not.
+
+ 19 Nov 2002; Martin Schlemmer <azarah@gentoo.org> cnf/etc-update.conf:
+ Add 'menu' config item and note about it needing dev-utils/dialog, as
+ a lot of users do not know about this nifty feature.
+
+ 14 Nov 2002; Phil Bordelon <sunflare@gentoo.org> man/emerge.1:
+ Cleaned up the more recent edits to the man page to more closely
+ match the previous format, fix various typos, and so on. Expanded
+ the REPORTING BUGS section, and made the PACKAGE MASKING part of the
+ NOTES a stand-alone section.
+
+*portage-2.0.44 (11 Nov 2002): bug fixes and 1.2 rescue/install setup
+
+ 11 Nov 2002; Nicholas Jones <carpaski@gentoo.org> *:
+ bin/*: fixes for spaces-in-filename issues, lots of quotes added. conf/*:
+ touched up comments and warning. Added RSYNC_RETRIES. ebuild.sh: exit now
+ reports the failing ebuild's $CATEGORY/$PF. Added EXTRA_ECONF to econf().
+ emake: added EXTRA_EMAKE. emerge: RSYNC_RETRIES curtasy of Christopher
+ Sharp. Random comment fixes. portage.py: Random touchups. KV extraction
+ fixup for new ROOTs. ARCH missing in profile fix. Fix for packages/All
+ missing dir traceback. INFOPATH/INFODIR fix. Added INFOPATH to specials.
+ portage.py: Touchups to the mtimedb-touching code. Fixes for the broken
+ os.path.normpath() leading '//' bug. Added a modified chuck of Phoen][x's
+ dist size patch.
+
+ 09 Nov 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Fixups for KV.
+
+ 08 Nov 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Fix for missing-glibc-bug in --version.
+
+ 08 Nov 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Fix for cfgdictfile traceback when ROOT != '/'. Fix for missing kernel
+ headers -- checks usr/src/linux, then /usr/include, then if merging
+ from sys-kernel ignore error.
+
+ 07 Nov 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Fix (part 2) for the USE="-*" arch-missing problem.
+
+ 03 Nov 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ eclass() function uses a caching and cPickle storing method to determine
+ currency of eclass-derived depcache entries. All previous methods are
+ already removed. eclass_save() is called via store() now. Stripped some
+ cruft from aux_get(). Error message touchups.
+
+ 03 Nov 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ A couple message touchups.
+
+ 29 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Moved the autoclean section under the --pretend check so it doesn't flip
+ out when running '-f'. Preliminary support for binary-only methods.
+ --usepkgonly (implies --usepkg) to force errors is binaries don't exist.
+
+ 27 Oct 2002; Daniel Robbins <drobbins@gentoo.org> new*: changed "&&" to "||"
+ to provide even better protection against mis-use of these commands.
+
+*portage-2.0.43 (27 Oct 2002): Bug fix release
+
+ 27 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ AUTOCLEAN="yes" on by default. Added in a clean phase after the merge
+ phase so clashing library versions do not remain installed when ldconfig
+ is run. This should close up the symlinks-being-removed bugs.
+
+ 27 Oct 2002; Nicholas Jones <carpaski@gentoo.org> cnf/*:
+ Miscelaneous typo fixes. Added PORTDIR_OVERLAY description in make.conf.
+
+ 26 Oct 2002; J Robert Ray <jrray@gentoo.org> portage.py:
+ Don't act like the download failed if after successfully downloading
+ a file its size doesn't match the file size in the digest. Treat
+ this as a mismatched digest condition instead.
+
+ 26 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Reversed the defaults on env_update() so it does a full ldconfig instead
+ of a non-symlink ldconfig. Fixed the typo in the 'invalid conf' notices.
+
+*portage-2.0.42 (24 Oct 2002): Bug fix release
+
+ 24 Oct 2002; Nicholas Jones <carpaski@gentoo.org> make.defaults.5:
+ Removed this file. It is horribly out of date and completely
+ wrong to boot. Users shouldn't be modifying the 3 lines in this file
+ anyway. They are obvious if you understand conf and defaults.
+
+ 24 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Added missing return statements to select_dep() that caused unmet packages
+ to be ignored. Touchups to 'emerge info' and 'emerge --version' output.
+ Added --delete to --delete-after so that it actually deletes in rsync.
+
+ 24 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Warning touchups. Replaced constants (9) to index("INHERITED").
+
+ 23 Oct 2002; Nicholas Jones <carpaski@gentoo.org> bin/new*:
+ Fix for "running as a root user" bug... code does 'rm -rf /' if
+ variables aren't defined in environment... That's a bad thing.
+
+ 23 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Possible fix for the aux_get() issues and IUSE.
+
+ 22 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ noauto got lost in some weird conflicts of .38, added it back.
+
+ 22 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Primitive logging via emergelog(). countdown(N,str) function does N second
+ countdowns of the action 'str'. Error messages on dependency traceback
+ via try/except on select_dep(). Removed the 'unavailable' warning. Message
+ updates. Added logging of basic actions to /var/log/emerge.log. Added
+ package/to-go counter. 'emerge info' displays a number of useful variables
+ that is good for bug reports.
+
+ 22 Oct 2002; Nicholas Jones <carpaski@gentoo.org> prepallstrip:
+ Bug 9508, fix for MSB architectures strip. Previous check assumed only
+ LSB objects could/should be stripped. (*LSB -> *SB) [Joky@#gentoo-sparc]
+
+*portage-2.0.41 (20 Oct 2002): Bug fix release
+
+ 20 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ stickies=[] lists the variables that will be kept/used as sticky vars,
+ not yet implimented. Fixed several relative symlink bugs by adding
+ abssymlink() to portage to determine real/absolute targets. env_update()
+ modified to fix bug 9308 symlinks bug. Bug 8348, request for error messages
+ instead of tracebacks/dies on parse errors, now caught on a per file basis
+ for system config files, includes descriptive messages. Fix for missing
+ profile traceback in new prepend'd-arch code. Typo fixes in symlink code.
+ DISABLED 'KEYWORD="" == available' code, DEFAULT IS MASKED NOW. Major
+ update to masking code, CONFIG_PROTECT can be layered with _MASKs, and
+ update_protect() now sets the self.protect* variables. Condensed and
+ reordered the unmerge code, now checks existance, cfgprotect, then mtimes.
+
+ 20 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Bug 8767: Added 'buildpkg' to FEATURES to specify always-buildpkg.
+ Updated the --version output to display profile and gcc version.
+ Bug 8083: Eliminate spinner when terminal is not a tty. Bug 7688:
+ fixed search vs. searchdesc differences by adding 'cat/pack' split.
+ Bug 9308: Symlinks were being killed by ldconfig, fixed by changing
+ how/when ldconfig was allowed to set symlinks. rsync command touchups,
+ --delete-after so that a failed rsync won't leave a user
+ without/with-few packages in portage. More warnings to depclean.
+
+ 20 Oct 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh:
+ Added die to gzip in unpack()
+
+ 20 Oct 2002; Nicholas Jones <carpaski@gentoo.org> make.conf*:
+ Added in useful variables and descriptions+warnings of their uses.
+
+ 20 Oct 2002; Nicholas Jones <carpaski@gentoo.org> make.globals*:
+ Added in large "do not edit" message.
+
+ 16 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Fixed an mtimes issue. --update on a package might yank non-cfgprot
+ files during the clean-phase because they didn't have mtimes updated.
+
+ 15 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Added 'IUSE' to the auxdbkey list. Fixed random aux_get() errors
+ caused by random empty files in the dep cache.
+
+ 15 Oct 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh
+ Actually committed the --host portion of econf.
+
+ 15 Oct 2002; Martin Schlemmer <azarah@gentoo.org> portage.py, missingos.c:
+ Remove testsandbox.sh, and comment code in portage.py that still
+ used it to no real use. Add another '\' to the 'missingos_mknod__doc__'
+ string in src/python-missingos/missingos.c to fix failure with gcc-3.3.
+
+*portage-2.0.40 (13 Sep 2002): Bug fix release
+
+ 15 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py, emerge:
+ emerge depclean -- Removes all packages that are not explicitly or
+ dependency merged.
+
+ 15 Oct 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh:
+ depend now prints IUSE. Doesn't do anything with it yet.
+ unpack() -- unzip silently overwrites files ().
+ econf() -- now specifies '--host=${CHOST}'
+
+ 15 Oct 2002; Nicholas Jones <carpaski@gentoo.org> make.globals:
+ Touch ups + warning.
+
+ 15 Oct 2002; Brandon Low <lostlogic@gentoo.org> etc-update:
+ Make etc-update find all the same CONFIG_PROTECT files as portage
+ by importing it's settings from portage.
+
+*portage-2.0.39 (13 Sep 2002): Bug fix release
+
+ 13 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Bug 5926 -- If the fetchonly AND pretend flags are specified, then
+ portage should give a list of all the SRC_URIs so that they can be
+ downloaded or sent into another app. Made sandbox display name in
+ 'ps' as '[$PF] sandbox'.
+
+ 13 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Bug 5926 -- See portage.py for today. (emerge -pf)
+ Typo fixes.
+
+ 13 Oct 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh:
+ Added -q to unzip to make it quiet like the others.
+ Bug 6033 -- Fix for infinate loop in eclasses in portage overlay.
+
+ 12 Oct 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fix for
+ doebuild() so that our rsync mirror will contain full digests and not just
+ partial digests for x86.
+
+ 12 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Added --progress to rsync. This puts the file progress meters
+ back on. Users have requested this, and it's not detrimental.
+ Just creates a lot of output, as the man page says: "It gives
+ bored users something to look at."
+
+ 12 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Bug 6361 -- Added checking on directories to ensure that we can
+ write to them before we try and traceback. Also added pieces to
+ functions so that return conditions are propagated back to emerge
+ so that it actually dies on errors. Message on condition details
+ restart process.
+
+ 11 Oct 2002; Nicholas Jones <carpaski@gentoo.org> make*globals:
+ Removed the tomcat configs from CONFIG_PROTECT
+
+ 11 Oct 2002; Nicholas Jones <carpaski@gentoo.org> doman:
+ Bug 8208 -- Added flags and auto-location support for 'x' manpages.
+ Added not-an-man-page message.
+
+ 11 Oct 2002; Nicholas Jones <carpaski@gentoo.org> dohtml:
+ Bug 8208 -- Added 'js' to the include list, and added '-A' as an
+ append flag. '-a' was a filter-down-to.
+
+ 11 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Bug 8964 -- Fix for read-only traceback in digestgen().
+ Bug 8949 -- Fix for read-only traceback in doebuild()
+ Bug 8284 -- Prepend ARCH _after_ use order processing. Prevents -*
+ from killing the ARCH flag. Bug 7596 -- Set an mtime of 0 into
+ CONTENTS if the file already exists on the FS. Allows the entry
+ to be in the CONTENTS file. Condensed the protect/protect-mask
+ code into one function in class dblink. Revised code to allow
+ multi-level protects and masks.
+
+ 10 Oct 2002; Nicholas Jones <carpaski@gentoo.org> emerge:
+ Bug 8552 -- typo fixes
+
+ 10 Oct 2002; Mark Guertin <gerk@gentoo.org> cnf/make.conf.ppc :
+ Fixed type in reccomended CFLAGS for generic ppc (was 02, corrected
+ to O2)
+
+ 09 Oct 2002; Nicholas Jones <carpaski@gentoo.org> portage.py:
+ Fixed a bug where files less than 2 characters in /etc/env.d
+ weren't checked correctly, and tracebacked env_update()
+
+ 07 Oct 2002; Martin Schlemmer <azarah@gentoo.org> ebuild.sh:
+ Also set $TMP, as MDK among distros sets this, and it causes
+ breakage during bootstrap. This should close bug #8101.
+
+ 07 Oct 2002; Mark Guertin <gerk@gentoo.org> man/ebuild.5 :
+ Updated the man page to include missing functions in portage
+
+ 05 Oct 2002; Mark Guertin <gerk@gentoo.org> cnf/make.conf cnf/make.conf.ppc:
+ Fixed typo (missing "/") in make.conf and make.conf.ppc, bug #7944
+
+ 28 Sep 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: remove
+ deprecated "ld.so" from newdepend.
+
+*portage-2.0.38 (25 Sep 2002): Bug fix release
+
+ 25 Sep 2002; Daniel Robbins <drobbins@gentoo.org> emerge: now "emerge world"
+ and "emerge system" don't replace packages. This closes bug #8282.
+
+ 21 Sep 2002; Daniel Robbins <drobbins@gentoo.org> portage-2.0.38.ebuild:
+ Added additional perm check for /var/cache/edb/dep dirs and fixed perm
+ settings in the ebuild's pkg_postinst(); this should close bug #7719.
+
+ 21 Sep 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Added
+ carpaski's patch to add PF to the sandbox's argv[0], closing bug #8141.
+
+ 19 Sep 2002; Daniel Robbins <drobbins@gentoo.org> emerge: tweaked emerge so
+ that "--pretend" displays don't show "N" all the time.
+
+ 19 Sep 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: tweaked help to
+ not list deprecated options.
+
+ 25 Sep 2002; Maik Schreiber <blizzy@gentoo.org> cnf/make.globals,
+ cnf/make.globals.ppc: Added /opt/jakarta/tomcat/conf to CONFIG_PROTECT. Note
+ by drobbins: this will be removed soon when this gets moved to an /etc/env.d
+ file in the tomcat package.
+
+*portage-2.0.37 (19 Sep 2002): Gentoo Linux 1.4_rc1 version
+
+ 10 Sep 2002; Mark Guertin <gerk@gentoo.org> cnf/make.conf.ppc : Backed down
+ CFLAGS from -O3 to -O2 on ppc as -O3 has proven to be unreliable on all
+ PowerPC-based machines
+
+ 09 Sep 2002; Daniel Robbins <drobbins@gentoo.org> emerge: new parameterized
+ create() engine, security pass fixes ("emerge" as non-root doesn't print
+ "root access required" but shows help instead), emerge --pretend output fixes
+ ("to /" lines are dropped and only displayed if installation root != "/".)
+ New (and currently unofficial and undocumented) "--deep" and "--selective"
+ options that correspond to their respective create() parameters. Using
+ "--deep" will enable "deep emerging" -- updating all deps even if the parent
+ doesn't need updating. The new parametrized create() is also much cleaner
+ than the previous incarnation.
+
+ 09 Sep 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: os.chdir() ->
+ chdir() fix, enhanced fetch() digest corruption handling.
+
+ 06 Sep 2002; Mark Guertin <gerk@gentoo.org> cnf/make.globals.ppc :
+ Updated make.globals.ppc to reflect new CFLAGS for 1.4 release
+
+*portage-2.0.36 (04 Sep 2002): Gentoo Linux 1.4_rc1 version
+
+ 04 Sep 2002; Daniel Robbins <drobbins@gentoo.org> emerge: "--onlydeps" was
+ mostly broken since the most recent emerge code restructure. Now fixed,
+ closing bug #7442.
+
+ 04 Sep 2002: Daniel Robbins <drobbins@gentoo.org> etc-update.conf: added
+ missing etc-update config file.
+
+ 04 Sep 2002: Daniel Robbins <drobbins@gentoo.org> portage.py: removed error
+ detection based on return value for pkg_preinst() and friends when called
+ from merge() and unmerge(), since the value can be unreliable due to the &&
+ shell construct, depmod -a returning a non-zero value, etc. Also fixed
+ env_update() to treat CONFIG_PROTECT and CONFIG_PROTECT_MASK correctly.
+
+*portage-2.0.35 (03 Sep 2002)
+
+ 03 Sep 2002: Daniel Robbins <drobbins@gentoo.org> etc-update,
+ man/etc-update.1: new program for updating config files.
+
+ 03 Sep 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: upgraded
+ inherit() to support $PORTDIR_OVERLAY, closing bug #6033.
+
+ 03 Sep 2002; Daniel Robbins <drobbins@gentoo.org> emerge: calls to "cvs" now
+ use "-z3" compression option, closing bug #5982.
+
+ 03 Sep 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: symlinks to
+ .tbz2's in the $PKGDIR/All directory (from $PKGDIR/$CATEGORY) are now
+ relative, closing bug #6881.
+
+ 03 Sep 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: einstall now
+ sees "GNUmakefile", closing bug #4895.
+
+ 03 Sep 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: typo fixes,
+ closing bug #7263.
+
+ 03 Sep 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: /var/tmp
+ creation now works even if /tmp already exists, closing bug #7376.
+
+ 02 Sep 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fixed a logic error
+ that resulted in non-root emerge failure. This closes bug #7389.
+
+*portage-2.0.34 (01 Sep 2002)
+
+ 01 Sep 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py, ebuild.sh:
+ Azarah's ebuildsh() removed, various other little fixes like pkg_preinst and
+ friends not dying on non-zero return codes.
+
+ 01 Sep 2002; Martin Schlemmer <azarah@gentoo.org> ebuild.sh: add a custom
+ version of the esyslog() function to fix the "Red Star" bug if no logger is
+ running.
+
+*portage-2.0.33_p1 (30 Aug 2002): urgent fix
+
+ 31 Aug 2002; Dan Armak <danarmak@gentoo.org> ebuild.sh: comment out the if
+ clause that only executed inherit() conditional on $PORTAGE_RESTORE_ENV. It
+ didn't work and broke portage 2.0.33 as far as inheriting ebuilds goes.
+
+*portage-2.0.33 (30 Aug 2002)
+
+ 30 Aug 2002; Daniel Robbins <drobbins@gentoo.org> : some additional clean-ups
+ for the make.conf(.ppc) files.
+
+ 30 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: emerge search would
+ die when aux_get() raised a KeyError; we now catch and handle this exception.
+ This closes bug #7280.
+
+ 29 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed typo in
+ move_ent() code that messed up moving packages into previously non-existant
+ category directories in /var/db/pkg.
+
+ 30 Aug 2002; Mark Guertin <gerk@gentoo.org> cnf/make.conf.ppc : Updated
+ cnf/make.conf.ppc with new CFLAGS for 1.4 release
+
+*portage-2.0.32 (29 Aug 2002)
+
+ 29 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: favorites weren't
+ working since 2.0.30; they're working again now. This closes bug #7225.
+
+ 29 Aug 2002; Phil Bordelon <sunflare@gentoo.org> emerge.1: Added a small
+ blurb regarding what to do when emerge --update [world|system] fails because
+ of new features such as || and ?. Hopefully this will assuage the fairly
+ common questions regarding this.
+
+*portage-2.0.31 (29 Aug 2002)
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed a config
+ file protection logic bug detected and identified by Azarah. It basically
+ broke most config file updates and has been broken for around six months.
+ Very surprised no one had encountered this issue before.
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: improved error
+ messages when an unsatisfiable dependency is encountered. Now lets you know
+ if there are masked packages that would satisfy the dep.
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: emerging .tbz2
+ packages and .ebuilds by name now works; this was broken in 2.0.30.
+
+*portage-2.0.30 (28 Aug 2002)
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: rewrote
+ gettimeval() as cpv_counter() and updated it to handle corrupt COUNTER files,
+ closing bug #6763.
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: "emerge search" now
+ displays information for masked packages if possible, closing bug #6823.
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fixed an old gbevin
+ bug where "emerge search" wouldn't show packages whose version string was
+ only one character long, ie. "foo-3". This closes bug #6800.
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: added a missing
+ call to flatten() in dep_check(), allowing recursive sublists in dependencies
+ and SRC_URI variables to work; this closes bugs #7104, #7116, #7122.
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> doman: fixed some typos,
+ closing bug #7152.
+
+ 28 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: major
+ work to emerge: reworked the internal code organization to make depgraph code
+ easier to understand; unified two code paths so that ebuild/.tbz2 choices
+ when "--usepkg" should now be eternally consistent; tweaked portage.py so
+ that dep_expand()'s dbapi argument is optional. In the process of all this,
+ isolated and fixed bug #4508.
+
+ 27 Aug 2002; Martin Schlemmer <azarah@gentoo.org> portage.py: if the dep
+ cache is stale, it is possible that aux_get() will call doebuild(depend) to
+ regenerate it again. This call will cause $T to be set to "", which will
+ break anything that needs $T to be set to a writable location inside the
+ sandbox, so we need to set $T to a valid value again.
+
+ 27 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: improved error
+ handling/detection of bad pkgsplit() and catpkgsplit() calls; should close
+ bug #6803, #6853.
+
+ 26 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fix so that "emerge
+ prune rsync" doesn't complain that you are trying to rsync and prune at the
+ same time. This closes bug #6785.
+
+ 26 Aug 2002; Daniel Robbins <drobbins@gentoo.org> doman fixes; should work
+ for pre-gzipped man-pages and man-pages with multiple "."s in their name.
+ Closes bugs #6770, #6917
+
+ 25 Aug 2002; Martin Schlemmer <azarah@gentoo.org> emerge: fixed an
+ indentation problem of the 'else:' at line 1304.
+
+ 20 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: removed stray
+ "DEBUG:" output, closing bug #6732.
+
+*portage-2.0.29 (18 Aug 2002)
+
+ 18 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge, portage.py,
+ ebuild.sh: making some effort to make output cleaner and less cluttered,
+ particularly with error handling.
+
+ 18 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: updated so that
+ "emerge --inject foo-1.0" fails instead of injecting "null/foo-1.0"; fixed
+ error in help; "emerge --inject" and "emerge" with no specified files or
+ package classes prints out a small warning and exits. Closes bug #6353.
+
+ 18 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: movefile()
+ didn't like bind mounts due to a peculiar quality -- according to their
+ ST_DEV stat() information, they are on the same filesystem, so rename()
+ should work, but it doesn't. We now fall back to copy if rename() doesn't
+ work. Closes bug #6468.
+
+ 18 Aug 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: made significant
+ enhancements and fixes to ebuild.sh's error-handling code. Errors in
+ src_unpack(), src_compile(), src_install() and others should now be correctly
+ detected. Also downgraded our use() function since we are not implementing
+ extended USE functionality. Closes bug #6393.
+
+ 18 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: portdb's
+ cp_all() now skips "CVS" directories, closing bug #6662.
+
+ 18 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: aux_get():
+ exception handler to print informative message when encountering wacky cache
+ entries that we just can't fix (for some reason.)
+
+ 17 Aug 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: removed
+ deprecated "ld.so" dependency from Dan Armak's newdepend() function.
+
+ 17 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: doebuild()
+ running in "depend" mode will set $T to "" to prevent a parent's $T from
+ being inherited; this is important when we run custom portage code from
+ inside an ebuild (such as pkg_postinst)... it allows dep caching to not
+ break. Closes bug #6484.
+
+*portage-2.0.28 (17 Aug 2002)
+
+ 16 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: return errors when
+ two actions like "world" and "system" are specified on the command-line, or
+ when "system" or "world" are combined with package names. Closes bug #6492.
+
+ 16 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: bad string was
+ causing pkg_prerm() and pkg_postrm() to not be called; now fixed. This
+ closes bug #6493.
+
+ 16 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: now calls
+ env-update() after an unmerge() run (to fix library paths, links, etc.)
+ Closes bug #6511.
+
+ 16 Aug 2002; Daniel Robbins <drobbins@gentoo.org> doman: now handles already-
+ gzipped man pages correctly, closing bug #6544.
+
+ 16 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fixed a bug where a
+ dep specified on the command-line with --usepkg would use an old package if
+ it happened to match the dep. Now, it will use the ebuild instead, just like
+ how deps of deps are treated.
+
+*portage-2.0.27 (06 Aug 2002)
+
+ 07 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: removed some
+ beta extended USE functionality to speed up regenerate(); as we are likely
+ not going to need extended USE for a good while.
+
+ 07 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: ebuild.sh now
+ supports "config" (pkg_config) again.
+
+ 06 Aug 2002; Dan Armak <danarmak@gentoo.org> ebuild.sh: change debug-print()
+ to exit if $T is not defined, i.e. if emerge is running in dependency
+ detection mode and isn't actually emerging everything. This fixes bug #4932
+ (the "eclass-debug.log is created in /" problem).
+
+ 06 Aug 2002; Nicholas Jones <carpaski@gentoo.org> ebuild.sh: Fixed a
+ case-check problem that prevented tar.Z from being un-tar'd. This closes bug
+ #6126.
+
+ 06 Aug 2002; Martin Schlemmer <azarah@gentoo.org> portage.py, ebuild.sh:
+ Remove "setup" from 'sandboxactive' in portage.py, as we are not running
+ pkg_setup() in a sandbox anymore. Move the restoring of the old env code
+ to be the first thing in ebuild.sh, just to ensure we dont mess anything
+ up when greping/awking during saving it.
+
+*portage-2.0.26 (06 Aug 2002)
+
+ 06 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: on unmerge,
+ entries are now removed from the world file if 1) the dependency refers to
+ the cat/pkg being unmerged, and 2) the dependency matches the current version
+ being unmerged, and 3) unmerging this package will leave no other packages on
+ this system that will match this world entry. This closes bug #3409.
+
+ 06 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: new global
+ update support. You can now add an entry to a file in
+ /usr/portage/profiles/updates/, something like "move x11-base/xfree
+ x11-base/xfree86". Portage will then update the /var/db/pkg db on user's
+ boxes so that any xfree packages are renamed to xfree86; it will also update
+ the world and virtuals files appropriately. We are naming the update files
+ "3Q-2002", etc. -- for third quarter in 2002. This way, we don't bog
+ Portage down by having it run through all our directives. It will only look
+ at update files whose mtimes have changed. Closes bug #4753, #5463,
+
+ 06 Aug 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: tweaked Azarah's
+ environment-saving patch to not be enabled when $T is not defined -- this
+ closes bug #6070 and should speed up dep calculations too. Also tweaked
+ ebuild.sh so that pkg_setup() is run *outside* of the sandbox. This is
+ important because piping stuff around tends to require temp files to be
+ created; pkg_setup() being in the sandbox prevents this from happening.
+
+ 06 Aug 2002; Martin Schlemmer <azarah@gentoo.org> ebuild.sh : Unset
+ esave_ebuild_env in esave_ebuild_env(), otherwise the sourced copy messes
+ saving of the environment.
+
+ 05 Aug 2002; Phil Bordelon <sunflare@gentoo.org> emerge.1: Updated the man
+ page to match the current version of 2.0.25.
+
+ 05 Aug 2002; Phil Bordelon <sunflare@gentoo.org> emerge.1: Updated the man
+ page to match the current version of 2.0.25.
+
+*portage-2.0.25 (05 Aug 2002)
+
+ 05 Aug 2002; Daniel Robbins <drobbins@gentoo.org> src/sandbox/Makefile:
+ removed -march=i386 added in Azarah's patch; breaks things for PPC, Sparc.
+
+ 05 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: logic error fix for
+ description searching, closing bug #6031.
+
+*portage-2.0.24 (04 Aug 2002)
+
+ 04 Aug 2002; Daniel Robbins <drobbins@gentoo.org> output.py, emerge: rewrote
+ our output.py module (it was weird) and tweaked emerge so that colorization
+ will be disabled if NOCOLOR is set to "yes" or "true" *or* if sys.stdout isn't
+ a tty. This means that if you pipe things to "less", colorization will get
+ automatically disabled. Yay! This closes bug #5714,
+
+ 04 Aug 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: default
+ src_compile now properly uses "die" instead of "return 1." This closes bug
+ #2981.
+
+ 04 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: "=foo/bar-1.0*"
+ now matches "foo/bar-1.0_{alpha|beta|pre|rc}{int}" but not
+ "foo/bar-1.1_{alpha_beta_pre_rc}{int}". This closes bug #5874; gcc-3.2_pre
+ is now considered a "3.2" rather than a very late "3.1" when doing "*"
+ matching.
+
+ 04 Aug 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: Applied
+ carpaski's patch to allow "unpack" to also handle regular .gz or .bz2 files;
+ in which case the unpacked files are placed directly in ${WORKDIR}. Closing
+ bug #5867.
+
+ 04 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: tweaked
+ exithandler() to only do its sandbox clean-up if we happen to be the root
+ user. Closes bug #5859.
+
+ 04 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: search now lists
+ masked packages correctly. Closes bug #5854 (pending QA verification.)
+
+ 04 Aug 2002; Phil Bordelon <sunflare@lsu.edu> emerge.1: The emerge man page
+ now reflects the fact that emerge sync|rsync always does a --clean now. Also
+ bumped the release number to 2.0.23.
+
+ 03 Aug 2002; Martin Schlemmer <azarah@gentoo.org> portage.py, emerge.sh,
+ sandbox.c libsandbox.c: Updated sandbox.c and libsandbox.c to use an internal
+ env variable, $SANDBOX_ACTIVE to determine if sandbox should really be active
+ or not. With it only checking $SANDBOX_ON, some instances NOT running in a
+ sandbox, but that set SANDBOX_ON while an actual sandbox was running, caused
+ the sandbox to activate for this process. Added in support for a more phased
+ calls to ebuild.sh again. This is this time done with support to save the
+ current environment of ebuild.sh to the next call that should handle problems
+ with pkg_setup() setting env variables. Closes bugs #5853, #5817, #5950.
+
+*portage-2.0.23 (01 Aug 2002)
+
+ 01 Aug 2002; Daniel Robbins <drobbins@gentoo.org> portage.py:
+ ${ROOT}var/cache/edb and friends will get created if they don't exist,
+ closing bug #5813.
+
+ 01 Aug 2002; Daniel Robbins <drobbins@gentoo.org> emerge: rewrote the emerge
+ search code, making it fully API-compliant and much more streamlined and
+ compact. This rewrite should fix the problem where emerge search doesn't
+ support Portage overlays (bug #5783.)
+
+ 31 Jul 2002; Phil Bordelon <sunflare@gentoo.org> emerge.1: Documented the
+ fact that emerge clean does not remove unslotted ebuilds. Bumped the man
+ page revision number to 2.0.22.
+
+*portage-2.0.22 (29 Jul 2002)
+
+ 29 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fetch() didn't
+ handle resuming downloads properly when the first attempt aborted
+ prematurely. The fall back to the alternate location would not resume the
+ download. This should now be fixed. Closes bug #5655.
+
+ 29 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, ebuild.sh: I
+ had some code in spawn() from one of Azarah's patches that I forgot to
+ remove; it caused the sandbox to be disabled all the time. I removed this
+ code, and then I tweaked ebuild.sh so that the sandbox runs in a "deny by
+ default" configuration. Before, you could add lines to the main ebuild
+ (outside of a function) and it would bypass the sandbox; no more. Closes
+ bugs #5740, #5744.
+
+ 29 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: --help and
+ --version now work for non-root users as they should. --clean has been
+ deprecated. This closes bug #5658.
+
+*portage-2.0.21 (28 Jul 2002)
+
+ 28 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: Added
+ beta "Portage tree overlay" support. By setting PORTDIR_OVERLAY to point to
+ a local directory tree, you can cause Portage to look for ebuilds in
+ PORTDIR_OVERLAY first before consulting the regular PORTDIR. Using this
+ feature, it's possible to have your PORTDIR set up to rsync but still be able
+ to have locally-created ebuilds in your PORTDIR_OVERLAY tree. For example,
+ you would place your ebuild in PORTDIR_OVERLAY/sys-apps/foo/.
+
+ 27 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: another
+ dep_opconvert() USE-handling bug-fix. Working OK for Azarah now.
+
+ 27 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: small logic
+ error fix in dep_opconvert() to fix up USE handling.
+
+ 27 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: security modes now
+ work correctly; root access now required for merging. The new security pass
+ code was missing a check that is now present.
+
+*portage-2.0.20 (27 Jul 2002)
+
+ 27 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge,
+ repoman: Rewrote a good deal of our dependency-checking code, including all
+ of dep_opconvert(). Results? repoman will now auto-enable all USE variables
+ (even ! use variables will get enabled) resulting in thorough checks of all
+ specified dependencies. DEPEND="foo? bar : oni" and DEPEND="foo? ( bar oni )
+ : ( meep barf )" now works correctly. DEPEND="|| ( foo bar oni )" now works
+ correctly and will try to satisfy "foo" (the first package) if none are
+ installed. DEPEND="!foo? ( bar )" now works correctly; it was not working
+ before. This should generally mean that our dependency system is now working
+ as expected.
+
+ 27 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: changed
+ counter_tick() method so that bulk of code is in the counter_tick_code()
+ helper function; then created a new method for fakedbapi that calls
+ counter_tick(). This fixes "--emptytree" issues with emerge, since emerge
+ still expects counter_tick() to exist as a method.
+
+ 27 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: removed
+ a DEBUG: print and a stray "raise IndexError" that I used for debugging.
+
+*portage-2.0.19 (26 Jul 2002)
+
+ 26 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Portage is now
+ eclass-friendly when it comes to regenerating cache entries. This closes bug
+ #4843.
+
+ 26 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: Closed
+ bug #5524. Packages "emerge inject"ed will no longer get auto-cleaned
+ indiscriminantly. Injected packages now have an official COUNTER so that
+ emerge clean doesn't get confused and schedule the package for removal. Also
+ modularized and improved the counter-handling functions and changed the
+ counter update method so that systems with XFS filesystems that die
+ unexpectedly will no longer get corrupted COUNTER files. This should solve
+ the an entire class of "my counter is corrupt" issues for XFS users.
+
+ 26 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: added exception
+ handler to getcontents() so that it will gracefully ignore (with a warning)
+ corrupt CONTENTS file lines. This closes bug #5464.
+
+ 26 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fixed a single-line
+ indentation error that resulted in "emerge clean" ignoring some files. This
+ closes bug #5597,#4364.
+
+ 25 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: --noreplace is now
+ off by default and works again; --onlydeps appears to be working again; and
+ merge() will merge things as specified in display(), which was not the case
+ before (I rolled 2.0.18 before fixing a few things I forgot about)
+
+*portage-2.0.18 (25 Jul 2002)
+
+ 25 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Close bug
+ #5580; pkg_setup() now gets called during all build-related stages.
+
+ 24 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: rewrote
+ create() function, closing bug #5469. Also added freeze() and melt() methods
+ to portdbapi to enhance performance. create() is now extensively commented
+ and even understandable.
+
+ 24 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: the "rsync --clean"
+ option has been deprecated. Cleaning is now on by default, closing bug
+ #5527.
+
+ 24 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, make.globals:
+ It should now be safe to do what Spider did in the gconf ebuild and add
+ CONFIG_PROTECT and CONFIG_PROTECT_MASK to /etc/env.d entries. Both variables
+ are now incremental, just like USE, and you can use "-path" to turn a path
+ off, or add CONFIG_PROTECT{_MASK}="path" to *add* a path to the list (this
+ will not overwrite "parent" settings. Also added "/etc/env.d/" to
+ CONFIG_PROTECT_MASK in /etc/make.globals. Also, very importantly, /etc/env.d
+ is now hard-coded into CONFIG_PROTECT_MASK as it was in earlier versions of
+ Portage and cannot be removed.
+
+ 24 Jul 2002: Daniel Robbins <drobbins@gentoo.org> emerge, portage.py: two
+ fixes; first, I removed xcache.p support from portage.py. The code was
+ designed based on the false theory that directory mtimes are updated whenever
+ an object inside that directory is modified. That is not the case -- it
+ happens when the directory listing itself changes. Also fixed overly verbose
+ emerge merging error.
+
+ 23 Jul 2002; Phil Bordelon <sunflare@gentoo.org> emerge.1: Updated the man
+ page to match some changes in the latest version of portage, along with some
+ fixes recommended by drobbins.
+
+*portage-2.0.17 (23 Jul 2002)
+
+ 23 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed a bug
+ pointed out by trance -- dep_nomatch() was still using the old (deleted)
+ match() function. Now it's using a new match() method.
+
+*portage-2.0.16 (22 Jul 2002)
+
+ 22 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: changed xcache
+ behavior so that the cache gets totally thrown away when the masks are
+ updated. Also revamped carpaski's code so we can avoid loading xcache from
+ disk if we simply plan to throw it away. This necessitated the creation of a
+ new file in /var/cache/edb: mtimes. This file stores mtimes for various
+ important filesystem objects. Also added support to not regenerate the GNU
+ info directory index if the mtime on /usr/share/info has not changed since
+ previous invocation.
+
+ 22 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: moved
+ security handling code from emerge to portage.py; also moved group "wheel"
+ check to portage.py. Added additional security checks and permissions fixes
+ to the cache handling functions.
+
+ 22 Jul 2002: Daniel Robbins <drobbins@gentoo.org> emerge: fixed a bug
+ reported by woodchip related to merging packages. When using --usepkg, a
+ package wouldn't be used if there was a newer unmasked version of the ebuild
+ available, even if the package in question was the right selection.
+
+ 22 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fixed create() code
+ and consolidated some functions. My goal is to simplify the emerge code
+ until it's clean, at which point we can begin adding new features to emerge
+ like more SLOT-friendly decision making.
+
+ 22 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: was able to
+ remove 130 or so lines of code by depreciating the match() function (replaced
+ by the match2() method.) I also rennovated the binarytree code to take
+ advantage of fakedbapi.
+
+ 22 Jul 2002; Nicholas Jones <carpaski@gentoo.org> portage.py: added the
+ xcache.p fix and updated the version to 2.0.16pre (from 2.0.12) -- Also added
+ in a try/except inside the store() (atexit) for xcache.p to give hints
+ instead of tracebacks.
+
+ 22 Jul 2002; Nicholas Jones <carpaski@gentoo.org> emerge: added the
+ description searching code and added a spinner to the search.
+
+ 21 Jul 2002; Phil Bordelon <sunflare@gentoo.org> emerge.1: Finished the
+ rewrite of the emerge man page.
+
+ 21 Jul 2002; Phil Bordelon <sunflare@gentoo.org> emerge: Readded the sync
+ help to the list of help options now that emerge --help sync works again.
+
+*portage-2.0.15 (16 Jul 2002)
+
+ 15 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emake: no longer falls back
+ to plain old "make" if parallel make fails. I believe it's best to fix the
+ problem (turn parallel make off in the ebuild) rather than tweak emake to
+ avoid it.
+
+ 15 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: rewrote some code,
+ cleaning things up and removing redundant functions. Starting to
+ de-cruftify.
+
+ 15 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fix for permissions
+ when updating the cache using server-generated entries.
+
+*portage-2.0.14 (15 Jul 2002)
+
+ 15 Jul 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: ccache bug fix;
+ removed extra "!". Ccache should now get enabled properly. Also, INHERITED
+ variable is now getting added to the dep cache entries for future
+ eclass-friendly caching.
+
+ 15 Jul 2002: Daniel Robbins <drobbins@gentoo.org> portage.py: Portage now
+ *persistently* caches xmatch() calculations. This appears to speed things up
+ but we will need to limit the size of the new xcache.p in future versions of
+ Portage.
+
+ 15 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: Portage
+ now has keyword-based masking enabled. It also has server-side caching
+ enabled to eliminate "emerge pre-Calculating dependencies... delay" for
+ end-users. There is now an undocumented "regen" option for emerge that tells
+ Portage to ensure that all entries in /var/cache/edb/dep are up-to-date.
+ This is intended mainly for developers, as the server-side caching feature
+ should ensure that all dep cache entries are up-to-date for end-users.
+
+ 15 Jul 2002; Daniel Robbins <drobbins@gentoo.org> repoman: repoman now checks
+ for ebuilds that generate output as well as ebuilds that return a non-zero
+ error code when sourced. For this test to detect all failures, you need to
+ wipe out your /var/cache/edb/dep/* before running repoman. This design quirk
+ is necessary to preserve existing emerge behavior.
+
+ 13 Jul 2002: Daniel Robbins <drobbins@gentoo.org> portage.py: Removed
+ Azarah's ebuildsh() function as it breaks pkg_setup() again. pkg_setup()
+ needs to be called as part of the same process as any other ebuil.sh command
+ so that environment vars set in pkg_setup() are preserved through the rest of
+ the build process.
+
+ 13 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: changed calling
+ convention for doebuild("depend").
+
+ 13 Jul 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: removed
+ erroneous "local dbkeys" that was outside of a function. This fixes some
+ cache update problems. Added INHERIT to our cache entries so we can
+ correctly update the cache for eclass ebuilds.
+
+ 12 Jul 2002; Dan Armak <danarmak@gentoo.org> make.globals, make.globals.ppc:
+ remove default KDE2DIR, KDE3DIR settings and comments. The kde eclasses will
+ now handle the case where they are not defined. This will be used with kde
+ 3.1 and later, and the difference between their default value and them not
+ being defined is important.
+
+*portage-2.0.13 (11 Jul 2002)
+
+ 11 Jul 2002; Daniel Robbins <drobbins@gentoo.org> tarball.sh: our tarball
+ script didn't clean the src/sandbox directory before creating our distribution
+ tarball. This resulted in src/sandbox/sandbox (the executable) being distributed,
+ and the "make" in the ebuild thinking everything was up-to-date. The result?
+ Everyone in the world got a sandbox compiled with gcc 3.1. This has been
+ fixed, closing bug #4867, #4851.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: removed some
+ bogus code that snuck in. pkg_setup() is no longer called when installing a
+ tbz2. All tbz2 stuff should be done in pkg_pre/postinst().
+
+*portage-2.0.12 (10 Jul 2002)
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> ccache support is now
+ controlled via a "ccache" FEATURES variable, which is enabled in make.globals
+ my default. ccache support can now be turned off by adding a
+ FEATURES="-ccache" to /etc/make.conf. Also, CCACHE_DIR correctly detected
+ and utilized.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: "emerge --help
+ rsync" now works correctly and displays rync help rather than rsyncing. This
+ closes bug #4438, #4629.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Portage now
+ prints a friendly error if PORTAGE_TMPDIR doesn't exist or is not a
+ directory. This effectively closes bug #4360.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: the "inject",
+ "sync" and "rsync" actions no longer allow "--pretend" or "-p" to be
+ specified. This closes bug #4352.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> sandbox.c: use realpath()
+ to expand the PORTAGE_TMPDIR, /var/tmp, /tmp paths. This allows write access
+ to these directories even if /var or /var/tmp is a symlink, for example.
+ Without this fix, access to these directories will be denied by the sandbox,
+ creating a bunch of problems. Closes bugs #4256, #2379, #4625, #2931, #4829.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> megadigest, megadownload,
+ megatouch, pkgsearch: removed from the bin/ directory; deprecated.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge, quickpkg: remove
+ hard-coded references to "/usr/portage" in "emerge search", quickpkg. Now
+ correctly uses PORTDIR instead. Closes bug #4836.
+
+ 10 Jul 2002; Daniel Robbins <drobbins@gentoo.org> emerge: emerge now checks
+ to see if the "wheel" group exists before running; if it doesn't, it exits
+ with a polite error message. Closes bug #4736.
+
+ 08 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: changed the
+ unmerge() code so that it doesn't use mtimes to test whether a symlink
+ should be unmerged, since mtimes and symlinks are weird partners. Instead,
+ we save unmerging of our symlinks until the end of the code, and unmerge
+ them only if their target no longer exists. This closes bug #4491.
+
+ 08 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: check whether
+ ebuild actually exists immediately before running pkg_postint() and
+ pkg_preinst() from the dblink merge() method. Also change all PKG_TMPDIR
+ references to PORTAGE_TMPDIR plus suffix, closing bug #4447, #4853.
+
+*portage-2.0.11 (07 Jul 2002)
+
+ 07 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: rewrote
+ portdbapi's xmatch() and visible() to fix significant bugs. Logic errors in
+ both methods caused ~ deps to not work correctly. After the rewrite,
+ dependency checking is now 44% faster.
+
+ 07 Jul 2002; Daniel Robbins <drobbins@gentoo.org> repoman, portage.py: Added
+ new DEPEND and RDEPEND.badmasked categories to repoman. repoman now checks
+ dependencies of masked packages using *all* ebuilds, rather than trying to
+ match them against all visible ebuilds. DEPEND.bad and RDEPEND.bad (used to
+ be ".unsolvable") now only tally visible ebuilds, not masked ones.
+
+*portage-2.0.10 (06 Jul 2002)
+
+ 05 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, repoman: Added
+ new capabilities to repoman -- the ability to detect unsolvable DEPEND and
+ RDEPEND variables, missing DESCRIPTION, LICENSE, KEYWORDS and SLOT. Fixed
+ repoman so that adding a comment with quotes in it doesn't break things.
+ Added a few tiny extensions to portage.py to support the new repoman
+ features.
+
+ 03 Jul 2002; Martin Schlemmer <azarah@gentoo.org> ebuild.sh: some ebuilds
+ like gcc do not use $S to build the package in, and this causes generated .la
+ files (libtool) to contain $WORKDIR in them. We thus export $WORKDIR in
+ ebuild.sh as well, to go along with fixes to the libtool-portage patch.
+
+ 02 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: pkg_setup() now
+ gets called before a tbz2 is installed, and pkg_preinst() and postinst() get
+ called at the right times as well.
+
+ 01 Jul 2002; Phil Bordelon <sunflare@gentoo.org> emerge: "emerge --help
+ rsync" does an rsync instead of printing help. Until this is fixed, I
+ removed it from the list of detailed help options.
+
+*portage-2.0.9 (01 Jul 2002)
+
+ 01 Jul 2002; Daniel Robbins <drobbins@gentoo.org> Added missing .match()
+ method to portdbapi.
+
+ 01 Jul 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Added new
+ operator for dependencies: DEPEND="foo? bar : oni" will use oni if foo isn't
+ set. Added "||" support back after removing it from my working copy; looks
+ ok.
+
+ 29 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, make.globals,
+ make.globals.ppc: internalized definitions of BUILDDIR and PKG_TMPDIR in
+ order to make things work as expected when one sets PORTAGE_TMPDIR. The new
+ config file var expansion algorithm made this change necessary.
+
+ 29 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fix doebuild()
+ so that pkg_setup() gets called when a .tbz2 package is being built. This
+ closes bug #3673.
+
+ 29 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: tweaked the
+ aux_get() code to automatically regenerate cache files if they have the
+ incorrect number of entries. Added an additional fix to this code on 01 Jul
+ 2002.
+
+ 29 Jun 2002; Martin Schlemmer <azarah@gentoo.org> portage.py: merge in some
+ of the missing ld.so.preload fixes again.
+
+ 29 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: new version
+ with highly-optimized dependency calculation caching, particularly for
+ portdbapi. Includes new three-level caching portdbapi xmatch() method.
+
+ 27 Jun 2002; Grant Goodyear <g2boojum@gentoo.org> ebuild.sh: Added keepdir()
+ function so that it no longer has to be hardcoded in ebuilds.
+
+*portage-2.0.8 (27 Jun 2002)
+
+ 27 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge: in an attempt to
+ provide a predictable release of Portage, I'm reverting the "emerge
+ --pretend" "fix" in Portage-2.0.6. It ignores custom USE settings when
+ calculating child deps, which makes things tricky for users. We'll use the
+ "expected" (old) behavior for now until we have a solution for this USE
+ issue.
+
+ 27 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed handling
+ of ! deps in match(), closing bug #4219. Thanks Spidler!
+
+ 27 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: disabled USE
+ regeneration on reset() for performance purposes.
+
+*portage-2.0.7 (26 Jun 2002)
+
+ 26 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: add a friendly
+ error handler for aux_get() so that flaky ebuilds don't cause it to trip up
+ with a cryptic traceback; users will get a friendly error message instead.
+ Also, temporarily disable keyword-based masking, since it currently slows
+ down Portage by quite a bit since it causes a much greater set of ebuilds to
+ be cached.
+
+*portage-2.0.6 (25 Jun 2002)
+
+ 25 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: rewrote the
+ config file code to make things more sane, consistent, and made infinite
+ loops during variable expansion a thing of the past. This closes bug #3952.
+
+ 25 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge, portage.py,
+ ebuild.sh: "emerge --pretend" and "emerge search" now work for the root user
+ as well as any users in the "wheel" group. emerge will now gracefully exit
+ if "emerge search" is run by someone not in the "wheel" group. This closes
+ bug #4121.
+
+ 25 Jun 2002; Martin Schlemmer <azarah@gentoo.org> bin/{dolib.so,preplib.so}:
+ Also change "strip --strip-unneeded" to "strip --strip-debug" for these.
+ Look at bugs #2702,#3929,#4027 for more info.
+
+ 25 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge: "emerge -u" now
+ correctly scans dependencies of packages, even if they are up-to-date, to
+ determine if any of their dependencies need updating. Previously, up-to-date
+ packages were not scanned in this way, which was a bug.
+
+ 24 Jun 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: Portage will now
+ automatically take advantage of ccache if the >=dev-util/ccache-1.9 ebuild is
+ installed. Removing /var/cache/ccache hole in the sandbox.
+
+*portage-2.0.5 (24 Jun 2002)
+
+ 23 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: basic keyword-
+ based masking is now active. New support for KEYWORDS in ebuilds and
+ ACCEPT_KEYWORDS in profiles.
+
+ 23 Jun 2002; Daniel Robbins <drobbins@gentoo.org> conf files: removed
+ references to non-functional FTP_PROXY and HTTP_PROXY and added a note about
+ how to use the correct vars (ftp_proxy and http_proxy.) Closes bug #1664.
+ Also added note about RSYNC_PROXY, closing bug #2332.
+
+ 23 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: removed
+ "dependency too short" checks which weren't working and were causing deps
+ like "mc" and "ed" to be rejected as invalid rather than being expanded.
+
+ 23 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge: upgraded "clean"
+ code to be more robust, consistent. Closes bug #3967.
+
+*portage-2.0.4 (20 Jun 2002)
+
+ 20 Jun 2002; Daniel Robbins <drobbins@gentoo.org> in the 2.0.4 ebuild itself:
+ added back tbz2tool symlink which was mistakenly removed. Also changed the
+ way we compile portage.py stuff so that we remove the previously compiled
+ files, just in case clock skew cause them to seem more recent than they
+ really are. Python byte-code compilation moved to pkg_postinst()
+
+ 20 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed up the
+ fetch() code so that invalid digests don't cause a traceback.
+
+ 20 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: some of the new
+ transplanted virtuals code assumed that profiledir was set, which is not
+ required. This code has now been fixed to not make that assumption.
+
+*portage-2.0.3 (20 Jun 2002)
+
+ 20 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed two typos
+ pointed out by stroke and g2boojum. These fix unmerge and some aspect of
+ virtuals handling, which was previously causing a traceback.
+
+ 19 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge: emerge -eup world
+ now will ignore world entries if it isn't really installed locally; in 2.0.1,
+ --emptytree would auto-enable all world entries, leading to inconsistent
+ package lists between --emptytree and without.
+
+*portage-2.0.2 (19 Jun 2002)
+
+ 19 Jun 2002; Daniel Robbins <drobbins@gentoo.org> make.conf.ppc,
+ make.globals.ppc: integrated these files into our sources.
+
+ 19 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed a bug
+ where ROOT="" would not get properly converted to ROOT="/".
+
+ 18 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge: Portage 2.0+ has
+ fixed "!" depend matching support, but some code in emerge was designed to
+ anticipate the incorrect behavior. This emerge code has been fixed to work
+ correctly. This closes my part of bug #3834.
+
+ 18 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: fixed
+ bug #2444, where emerge fails when "--emptytree" and "--onlydeps" are used at
+ the same time.
+
+ 18 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: new
+ fakedbapi for doing emptytree calculations; emptytree upgrades in emerge.
+ "emerge -upe world" now works correctly, accounting for items in the world
+ profile. Yay! Bugs #3832 and #1911 fixed.
+
+ 18 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge:
+ Integrated new aux_get() method into our portdbapi. aux_get() provides a
+ standardized way to get cached information about ebuilds, and is now fully
+ integrated into Portage and emerge search.
+
+ 18 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed a bug
+ where dep_nomatch() was testing for None rather than a "zero" condition,
+ causing dep_nomatch() to choke on match()'s [] return value.
+
+ 17 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge: added an exception
+ handler to catch invalid regular expressions and avoid a traceback.
+
+ 17 Jun 2002; Daniel Robbins <drobbins@gentoo.org> sandbox.c: added
+ /var/cache/ccache to sandbox "write ok" list, closing bug #3028.
+
+*portage-2.0.1 (16 Jun 2002)
+
+ 16 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: fixed a
+ virtuals expansion bug that would cause virtuals to be consulted too early.
+
+*portage-2.0 (16 Jun 2002)
+
+ 16 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, ebuild.sh,
+ emerge: turbo-ified Portage, new Portage db API and many other fixes.
+ Unmerging now works again (bug introduced several releases ago.) I
+ originally wanted to hold off on releasing 2.0, but since several major bugs
+ are fixed, we need to get these fixes out to our users ASAP. We will be
+ releasing 2.1 in about a week which should include additional refinements.
+
+ 16 Jun 2002; Daniel Robbins <drobbins@gentoo.org> repoman: New repoman
+ commit/check QA tool for developers.
+
+ 10 Jun 2002; Dan Armak <danarmak@gentoo.org> make.conf: Update the ibiblio
+ mirror path; it is now www.ibiblio.org/pub/Linux/distributions/gentoo.
+
+ 10 Jun 2002; Martin Schlemmer <azarah@gentoo.org> ebuild.sh : Some users have
+ $TMPDIR to a custom dir in their home ...this will cause sandbox errors with
+ some ./configure scripts or libtool, so set it to $T.
+
+ 10 Jun 2002; Martin Schlemmer <azarah@gentoo.org> portage.py : Merge in the
+ ld.so.preload changes. Also updated spawn() to only run sandbox if
+ buildphase is one of clean, unpack, compile or install. This should fix the
+ handler not detecting some instances of sandbox running. Updated ebuildsh()
+ to set buildphase="" on spawn exit.
+
+ 10 Jun 2002; Martin Schlemmer <azarah@gentoo.org>
+ portage.py.ldsopreload,testsandbox.sh : Add support to test if another
+ sandbox is running, if so dont delete /etc/ld.so.preload on kill. I did not
+ commit this to portage.py, as it is a bit more changes than we originally
+ though.
+
+ 05 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: doebuild() now
+ has proper logic for digest generation. Digest will now get regenerated if
+ "ebuild digest" is run, even if "digest" is in FEATURES.
+
+ 04 Jun 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fixed typo in
+ "inject" documentation.
+
+ 02 Jun 2002; Martin Schlemmer <azarah@gentoo.org> bin/dosym: changed the
+ command used from "ln -sf" to "ln -snf" as it created a symlink in the target
+ directory if the linkname already existed (only if the target is a
+ directory). Im guessing this should be fixed in the python merged code if
+ symlinks are not unlinked before the new is merged into place .. will add a
+ bug later.
+
+*portage-1.9.14 (01 Jun 2002)
+
+ 01 Jun 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: when a file to
+ be merged is identical to the one currently on disk (using the md5 test), we
+ now at least correctly update the target's mtime and atime so that cleaning
+ will work correctly.
+
+ 27 May 2002; Daniel Robbins <drobbins@gentoo.org> bin/do*: changed "return"s
+ to "exit 1". Closes bug #3078.
+
+*portage-1.9.13 (21 May 2002)
+
+ 21 May 2002; Grant Goodyear <g2boojum@gentoo.org> emerge.1: Updated man page.
+ Thanks to carpaski@twobit.net.
+
+ 20 May 2002; Daniel Robbins <drobbins@gentoo.org> emerge: a fix for dep
+ regeneration; stale dep cache entries should now be properly regenerated.
+
+*portage-1.9.12 (16 May 2002)
+
+ 16 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: the settings
+ for A and AA were swapped; this has now been fixed, closing bug #1634.
+
+ 15 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed up some
+ quirks in the new fetch code which were reported by Wout Mertens. Thanks
+ Wout!
+
+*portage-1.9.11 (13 May 2002)
+
+ 13 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: addition of
+ third-party mirroring code. "mirror://sourceforge/foo.tar.gz" will use the
+ /usr/portage/profiles/thirdpartymirrors file to define the mirror it will
+ download from. Multiple mirrors for a single keyword can be specified on a
+ single line. This code was based on the good work of Ryan Phillips.
+
+ 13 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: (entry on behalf
+ of jnelson) -- we now have new KV detection/setting code that uses
+ /usr/src/linux/include/linux/version.h to determine the kernel version -- the
+ right way of doing things. KV is set to "" if the kernel is not available or
+ not configured.
+
+ 13 May 2002; Daniel Robbins <drobbins@gentoo.org> emerge: "abspath[x]" =>
+ "abspath(x)" typo fix. Also added 2-liner to allow for "emerge unmerge" to
+ specify "foo/bar-1.0" rather than requiring "=foo/bar-1.0." Also fixed
+ problems when specifying the names of actual ebuilds in /var/db/pkg to
+ unmerge.
+
+*portage-1.9.9 (06 May 2002) ??
+
+ 08 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: An empty
+ USE_ORDER (due to an out-of-date /etc/make.globals) would cause USE to always
+ be empty. I added a reasonable default USE_ORDER if USE_ORDER is not found
+ in any of the config files, fixing this problem.
+
+ 06 May 2002; Daniel Robbins <drobbins@gentoo.org> emerge: post bug #1841
+ cleanups; converted from .hasnode() to .dep_match() (correct) in
+ getworldlist().
+
+*portage-1.9.8 (06 May 2002)
+
+ 06 May 2002; Daniel Robbins <drobbins@gentoo.org> emerge: 2 fixes that seemed
+ to get fried/zapped: bug #1841 and fixing an emerge sync error code to be
+ more understandable.
+
+*portage-1.9.7 (06 May 2002)
+
+ 06 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: initial
+ bunch of robustness/error-handling fixes. Emerge should now report a
+ comprehensible error message for errors in DEPEND and RDEPEND rather than
+ giving a traceback. Fixed dep_depreduce() to catch errors rather than
+ passing them on to dep_bestmatch() (which doesn't check for errors and
+ assumes correct input)
+
+ 02 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: typo fix for
+ S_ISFIFO call; thanks woodchip!
+
+*portage-1.9.6 (02 May 2002)
+
+ 02 May 2002; Daniel Robbins <drobbins@gentoo.org> make.conf: SYNC variable
+ correctly set to use our DNS round-robin system (rsync.gentoo.org).
+
+*portage-1.9.6_pre2 (01 May 2002)
+
+ 01 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: config file
+ protection upgrade; we now record md5sums of previously-merged config protect
+ files in /var/cache/edb/config; we use this information to avoid merging
+ files that have been merged by us before (if it is safe to do so). This
+ doesn't solve the problem of rolling back to a previously-merged version of
+ a config file; we need to add cvs headers to every config file to get that
+ to work.
+
+*portage-1.9.6_pre1 (01 May 2002)
+
+ 01 May 2002; Daniel Robbins <drobbins@gentoo.org> emerge: added "inject"
+ capability to artificially satisfy a dep -- for situations when you don't
+ want Portage to do it for you because you've taken care of it already.
+
+ 01 May 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: totally
+ rewrote emerge's unmerge code. The original code (added by Bevin) was a bit
+ too cryptic and "big" for my taste. Also added two new capabilities to
+ portage.py's vartree: .getslot() and .gettimeval(). getslot() returns the
+ slot value of a cat/pkg-v, if any, and gettimeval() returns a "time value"
+ (based on mtime/COUNTER value) that can be used to determine the order in
+ which packages got merged. The purpose of these improvements were to revamp
+ the existing Portage code that could only unmerge a db entry if there was a
+ corresponding ebuild file. This conflicted with the ability to "inject"
+ packages (see above), so it needed to be changed. Also fixed some bugs along
+ the way.
+
+ 01 May 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: einstall now
+ accepts arguments, closing bug #2275. Thanks seemant! :)
+
+ 01 May 2002; Daniel Robbins <drobbins@gentoo.org> make.globals: switch SYNC
+ var from cvs.gentoo.org to rsync.gentoo.org, and gentoo-x86-portage to
+ gentoo-portage.
+
+ 30 Apr 2002; Daniel Robbins <drobbins@gentoo.org> emerge: now checks for
+ errors (caused by bad deps) returned by create() and syscreate().
+
+*portage-1.9.5 (29 Apr 2002)
+
+ 29 Apr 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: added jnelson's
+ KV_extract.awk script which extracts the kernel version from the actual
+ kernel sources Makefile, making our KV setting much more robust! Thanks Jon
+ :)
+
+ 29 Apr 2002; Daniel Robbins <drobbins@gentoo.org> emerge: correctly fixed
+ emerge search examples to use single quotes (to turn off globbing.) This
+ closes bug #1609.
+
+ 29 Apr 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: virtual entries
+ for no-longer-installed packages now get automatically removed on unmerge.
+ This closes bug #2255 and #1891 (Thilo Bangert's comment on #1891 is also
+ fixed.)
+
+*portage-1.9.4 (29 Apr 2002)
+
+ 29 Apr 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Added support
+ for RESTRICT="nomirror". If "mirror" is defined in FEATURES and "nomirror"
+ is defined in RESTRICT, then files will not be fetched.
+
+ 29 Apr 2002; Daniel Robbins <drobbins@gentoo.org> emerge: Fixed docs for
+ "unmerge", added docs for "--oneshot". Closes bugs #2156 and #2182.
+
+ 29 Apr 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: Fix for USE
+ troubles; confirmed by Azarah as working :) Also, we now strip the path
+ from "KV" as we should.
+
+*portage-1.9.4_pre1 (26 Apr 2002)
+
+ 26 Apr 2002; Daniel Robbins <drobbins@gentoo.org> tarball.sh: no longer
+ necessary for VERSION to equal "@portage_version@" to get the version
+ auto-set. VERSION can now be set to anything and tarball.sh will get it
+ right.
+
+ 26 Apr 2002; Daniel Robbins <drobbins@gentoo.org> emerge: I've started work
+ on revamping/improving the "blocks" system to get ready to fix bug #1891.
+ Already fixed a bug where "blocks" ("!" deps) print out the wrong blocking
+ package name. This is now fixed. Blocks need additional testing.
+
+ 26 Apr 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, ebuild.sh, use:
+ "use" is now a bash builtin function rather than an external python-based
+ command. This appears to fix the USE inconstencies, as it should, thereby
+ closing bug #2000.
+
+*portage-1.9.3 (24 Apr 2002)
+
+ 24 Apr 2002; Jon Nelson <jnelson@gentoo.org>: portage.py, chkcontents:
+ Emulate fchksum's md5 checksum routine. Closes bug #2787.
+
+ 23 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: emerge: invalid
+ short options result in an exit. Closes bug #2025.
+
+ 22 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: emerge: rsync zlib
+ compression enabled by default.
+
+*portage-1.9.2 (21 Apr 2002)
+
+ 21 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: signal
+ handler now zaps /etc/ld.so.preload if it's there -- this prevents it
+ from hanging around and causing sandbox badness.
+
+ 21 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: emerge: fixed an
+ error where --emptytree mode wouldn't really have a fully empty tree,
+ due to the emptytree.inject() coming before the emptytree.root=None;
+ the inject() caused a recalc of the USE vars, which caused the tree
+ to become partially populated and it wasn't cleared. This closes bug
+ #1897.
+
+ 21 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: package
+ building now executes the "setup" stage along with the unpack, compile,
+ install stages so that global variables can be shared. This fixes an issue
+ with woodchip's new apache ebuild and closes bug #1813.
+
+*portage-1.9.1 (16 Apr 2002)
+
+ 16 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: tiny (and forgotten)
+ quick fix.
+
+*portage-1.9.0 (16 Apr 2002)
+
+ 16 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: fetching
+ should now try *all* alternate download locations, closing bug #1544.
+ Yay!
+
+ 15 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: emerge: "emerge R" now
+ works correctly, closing bug #1094.
+
+ 15 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: ebuild.sh: *'s and ?'s in
+ DEPEND and SRC_URI syntax should no longer get glob-expanded to files in
+ /usr/portage. This fixes some cryptic bugs. It also closes bug #1473.
+
+ 15 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: emerge --debug
+ now works again. Closes bug #1437.
+
+ 15 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: moved argument
+ check to the beginning of the doebuild() function to prevent "ebuild
+ foo.ebuild fart" from causing the md5sums to be checked before recognizing
+ that "fart" is not a valid command. Closes bug #1823.
+
+ 15 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: 'USE="-foo"
+ emerge bar' should now work correctly and consistently. Fixes to the config
+ class. Closes bug #1455.
+
+ 15 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: applied
+ jnelson's patch to properly kill all children when interrupted with ^C
+
+ 15 Apr 2002; Donny Davies <woodchip@gentoo.org>: make.conf: added a
+ RESUMECOMMAND for lukemftp.
+
+ 15 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: fixed up some
+ "zing" logic inside the merge code (fixing variable being used before
+ assignment errors)
+
+ 15 Apr 2002; Jon Nelson <jnelson@gentoo.org>: src/sandbox/Makefile,
+ src/sandbox/problems/Makefile, src/sandbox/problems/sandbox_dev_fd_foo.c,
+ src/sandbox/sandbox.c: Cleaned up Makefiles somewhat to take advantage of GNU
+ Make, added '/dev/zero' and /dev/fd/' (<- note trailing slash) to the list of
+ items accessible safely from the sandbox. Added sandbox_dev_fd_foo.c to test
+ for /dev/fd/<xx>. The test is almost verbatim from the autoconf test suite.
+
+ 13 Apr 2002; Martin Schlemmer <azarah@gentoo.org>: ebuild.sh:
+ Export $S and $D in dyn_compile and dyn_install, as our patched
+ version of libtool uses these to fixup .la files.
+
+*portage-1.8.19 (09 Apr 2002)
+
+ 08 Apr 2002; Geert Bevin <gbevin@gentoo.org>: emerge: Removed --all switch to
+ emerge unmerge and clea. Added emerge prune which is the same as old emerge
+ unmerge. Emerge unmerge removes all instances again without any proctedtion,
+ as before. Added reporting of Omitted versions due to dep selectors.
+ Renamed Removing and Keeping to Selected and Protected
+
+ 08 Apr 2002; Geert Bevin <gbevin@gentoo.org>: emerge, portage.py: Better
+ unmerge and clean reporting. Added homepage output to emerge --search.
+ Bugfix when specifying a package without category that doesn't exist.
+
+*portage-1.8.18 (07 Apr 2002)
+
+ 07 Apr 2002; Geert Bevin <gbevin@gentoo.org>: make.globals, emerge:
+ Simplified unmerge functionality. Deprecated the CLEANMODE var,
+ emerge clean now removes both revisions and slots automatically,
+ emerge unmerge now removes all versions and revisions by default.
+ Both understand world and system targets, and the --all option which doesn't
+ check which packages are old and outdated.
+ Documentation fixes.
+ AUTOCLEAN var addition and added the autoclean functionality.
+
+*portage-1.8.17 (05 Apr 2002)
+
+ 05 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: no longer
+ print out the counter number after a merge. This information should not
+ need to be known by end-users.
+
+ 05 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: sandbox.c: patched to
+ allow access to /dev/vc from sandbox, allowing vim and screen to compile
+ correctly from console.
+
+ 05 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: fixed a bug
+ that prevented md5 digests from being compared on archives.
+
+ 04 Apr 2002; Daniel Robbins <drobbins@gentoo.org>: portage.py: Parse errors
+ in /etc/env.d files no longer cause a traceback.
+
+*portage-1.8.16 (04 Apr 2002)
+
+ 04 Apr 2002; Geert Bevin <gbevin@gentoo.org> portage.py, emerge : Forgot to
+ commit my changes, this is an assembled version of both drobbins's and my
+ changes
+
+*portage-1.8.15 (04 Apr 2002)
+
+ 04 Apr 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Fixed a
+ semi-long standing bug where I was comparing atimes rather than mtimes when
+ seeing if dep caches were stale. This fixes a bug originally reported by Dan
+ Armak.
+
+*portage-1.8.14 (04 Apr 2002)
+
+ 04 Apr 2002; Geert Bevin <gbevin@gentoo.org> emerge:
+ Fixed short options for --all, --safe and clean.
+
+*portage-1.8.13 (04 Apr 2002)
+
+ 04 Apr 2002; Geert Bevin <gbevin@gentoo.org> portage.py, emerge:
+ Added emerge --all clean and emerge --safe unmerge.
+ Made the counter updates atomic so that multiple merges can happen without
+ risking counter clashes.
+ Updated --help.
+ Fixed short options bug that prevented two seperate short options to be
+ specified successively.
+
+*portage-1.8.12 (04 Apr 2002)
+
+ 04 Apr 2002; Geert Bevin <gbevin@gentoo.org> portage.py, emerge:
+ implemented "emerge clean" with oldrevs, oldversions and oldslots options for
+ the make.conf/make.globals CLEANMODE variable.
+
+ 03 Apr 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Added an
+ indentation fix to prevent merge from dying if a file attempts to install
+ itself on top of an existing directory. Closes bug #1498.
+
+*portage-1.8.11.1 (03 Apr 2002)
+
+ 03 Apr 2002; Geert Bevin <gbevin@gentoo.org> portage.py: important fixes
+ for movefile() -- changed the order of ownership / permissions settings since
+ suid/guid bits were overwritten, added support back for 'ebuild config' since
+ it was accidentally left out
+
+*portage-1.8.11 (02 Apr 2002)
+
+ 02 Apr 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: important fixes
+ for movefile() -- ownership now preserved across filesystems, mv -f fallback
+ for special files, other optimizations and robustness improvements. Important
+ fixes all-round.
+
+ 02 Apr 2002; Geert Bevin <gbevin@gentoo.org> emerge:
+ fixed bad indentation of a part of the code that made unmerging multiple
+ packages behave badly
+
+*portage-1.8.10 (01 Apr 2002)
+
+ 01 Apr 2002; Daniel Robbins <drobbins@gentoo.org> make.globals: removed USE
+ settings from make.globals.
+
+ 01 Apr 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: In trying to fix
+ the glibc merge bug, we rewrote movefile() and it now runs blazingly fast. I
+ also tweaked the code to remove the need for an ">>> Updating mtimes..."
+ stage. This is all done dynamically now. *Much* faster. And hopefully
+ solid for glibc upgraders.
+
+*portage-1.8.9.4 (01 Apr 2002)
+
+ 31 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: adapted
+ movefile() which should preserves timestamps and ownership on files and
+ symlinks it moves.
+
+*portage-1.8.9.3 (31 Mar 2002)
+
+ 31 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: promising
+ rewrite of movefile() not only will probably fix glibc merge bug but also
+ speeds up merging at least 20x! Calling "mv" for every file really make
+ things super-slow!
+
+*portage-1.8.9.2 (31 Mar 2002)
+
+ 31 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: desperate attempt
+ to fix movefile() bug... a hack really. glibc merges still dying.
+
+*portage-1.8.9.1 (31 Mar 2002)
+
+ 31 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: it appears that
+ movefile() (using "/bin/mv") can still die if moving a new symlink on top of
+ an existing library symlink. Upon failure, we now use a fallback mechanism
+ to use "/bin/sln" to create the new symlink safely.
+
+*portage-1.8.9 (30 Mar 2002)
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: tiny cosmetic
+ fix for digest generation.
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> emerge: entries in the
+ world profile will be ignored if at least one version of the package in
+ question isn't already merged. Prevents "--update world" from remerging
+ packages that have since been unmerged.
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> various: changing all
+ references from /usr/bin/python to /usr/bin/python2.2.
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> db-update.py: moving this
+ script here from FILESDIR.
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: stuff doesn't
+ get added to the world profile if it is already an essential ("*") package in
+ the system profile. Keeps things clean and flexible.
+
+*portage-1.8.9_pre38 (30 Mar 2002)
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: resolve_key()
+ didn't call load() on mapped virtuals, resulting in inconsistent resolution
+ of virtual keys. Now fixed; thanks to woodchip for the bug report.
+
+*portage-1.8.9_pre37 (30 Mar 2002)
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: specific
+ provides (dev-lang/python-2.2) will be converted to their generic form
+ (dev-lang/python) before being recorded.
+
+*portage-1.8.9_pre36 (30 Mar 2002)
+
+ 30 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: new
+ virtuals fixes and a db-upgrade.py script in the ebuild to solve another
+ virtuals problem.
+
+*portage-1.8.9_pre35 (29 Mar 2002)
+
+ 29 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: digest
+ generation fixes; emerge --update will now update dependents even if the main
+ package hasn't been updated. getdict() fix, fixing a traceback.
+
+*portage-1.8.9_pre34 (28 Mar 2002)
+
+ 28 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Added an indent
+ fix for the new virtuals code, eliminating a traceback. Tweaked digest handling,
+ fixing a cosmetic error.
+
+*portage-1.8.9_pre33 (28 Mar 2002)
+
+ 28 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: tweaked digest
+ creation in doebuild() to hopefully avoid creating digests twice. I hope I
+ didn't break anything in the process.
+
+ 28 Mar 2002: Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: "emerge
+ update" is now "emerge --update"; "world" added back. New world
+ implementation that works like this ... if you type "emerge media-gfx/gimp",
+ media-gfx/gimp will be added to the "world" favorites file in
+ /var/cache/edb/world. This world file is added to the system profile in
+ order to create the set of "world" packages to merge. You can manually put
+ specific deps (for pinning) in /var/cache/edb/world and they won't get
+ overwritten. To prevent a package that you specify on the emerge
+ command-line from being added to the world profile, use the "--oneshot"
+ option, which tells emerge that it should be merged once but not updated.
+
+ 28 Mar 2002: Daniel Robbins <drobbins@gentoo.org> portage.py: New virtuals
+ implementation; new virtual info is recorded in /var/cache/edb/virtuals;
+ virtuals data is created by merging the profile virtual info with the new
+ edb/virtuals file. Note: We no longer add virtual package entries to
+ /var/db/pkg. This change solves the bug where virtual files get auto-updated
+ by pkg-update, and also solves the bug where doing an "emerge --update world"
+ will cause ssmtp to be merged in order to satisfy the virtual/mta dep (which
+ you already have satisfied by postfix, for example). Now, postfix will be
+ updated if necessary, but that's it. :)
+
+*portage-1.8.9_pre32 (22 Mar 2002)
+
+ 22 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed a bug
+ related to scanning for available binary packages, which would cause emerge
+ to die.
+
+ 21 Mar 2002; Dan Armak <danarmak@gentoo.org> portage.py: added ECLASSDIR
+ (=$PORTDIR/eclass) to settings exported by python side to bash side.
+ ebuild.sh: remove ECLASSDIR setting to use the one now provided by
+ portage.py. Also, clean inherit() and make it use debug-print().
+
+*portage-1.8.9_pre31 (21 Mar 2002)
+
+ 21 Mar 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: Added Dan
+ Armak's patch to enable eclasses. :)
+
+ 21 Mar 2002; Grant Goodyear <g2boojum@gentoo.org> portage.py:
+ Added a drobbins patch to at line 469. Should fix emerge rsync
+ problem when /etc/make.profile doesn't exist.
+
+*portage-1.8.9_pre30 (20 Mar 2002)
+
+ 20 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: emerge
+ --emptytree now works again and I added a new --nodeps option to emerge as
+ well.
+
+*portage-1.8.9_pre29 (20 Mar 2002)
+
+ 20 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: CONTENTS files
+ now record the correct path when ROOT!="/".
+
+*portage-1.8.9_pre28 (20 Mar 2002)
+
+ 20 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: an
+ /etc/make.profile dir is now optional and portage will work if it's missing
+ or is a broken symlink.
+
+ 20 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fix load()
+ method in packagetree() class.
+
+*portage-1.8.9_pre27 (19 Mar 2002)
+
+ 19 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py:
+ /etc/make.profile/packages wasn't correctly masking core system packages;
+ fixed.
+
+*portage-1.8.9_pre26 (18 Mar 2002)
+
+ 18 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: configuration
+ settings don't get loaded from ${ROOT}/etc anymore, just /etc. This
+ simplifies the creation of a new build image.
+
+ 18 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Don't expect a
+ digest file if SRC_URI is set to "" or undefined.
+
+ 18 Mar 2002; Daniel Robbins <drobbins@gentoo.org>: RDEPEND was getting set
+ to DEPEND even if there was an RDEPEND="" in the ebuild. This has now been
+ fixed and RDEPEND will only get to DEPEND if RDEPEND has unset (not "unset
+ or null", as it was before this fix.)
+
+ 18 Mar 2002; Daniel Robbins <drobbins@gentoo.org>: emerge: circular
+ dependencies error will result in the digraph dependencies being printed to
+ stdout, greatly simplifying debugging.
+
+ 18 Mar 2002; Geert Bevin <gbevin@gentoo.org>: src/sandbox/problems: Added
+ several sample implementations to reproduce reported bugs.
+
+ 18 Mar 2002; Geert Bevin <gbevin@gentoo.org>: libsandbox.c: All paths are now
+ checked for multiple successive slashes anywhere, this closes bug 827.
+ Performance should be slightly improved for other apps on the system for who
+ the sandbox is not turned on.
+
+ 14 Mar 2002; Daniel Robbins <drobbins@gentoo.org>: output.py: quick fix to
+ turn off white color output -- not good for terminals with white background.
+ This closes bug #1135.
+
+ 11 Mar 2002; Daniel Robbins <drobbins@gentoo.org>: Applied karltk's version
+ information patch. Portage.py now contains version information, and this
+ info is reported by "emerge --version". Thanks Karl! :)
+
+*portage-1.8.9_pre25 (11 Mar 2002)
+
+ 10 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge: roll
+ back portagetree incremental db optimizations to fix an important bug (no
+ package.mask calculations being done.) Emerge will now abort if a dependency
+ can't be satisfied rather than printing just a warning.
+
+*portage-1.8.9_pre24 (09 Mar 2002)
+
+ 09 Mar 2002; Daniel Robbins <drobbins@gentoo.org> emerge: fixed missing
+ "--clean" option so "--clean rsync" should work again. Also converted emerge
+ to work with our new db layout (db objects are in the portage module now).
+
+ 09 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Added USE
+ ordering, a concept envisioned by Vitaly Kushneriuk. The idea is to allow
+ customization of how Portage resolves USE variables. The default is
+ "env:conf:auto:defaults" (set in the USE_ORDER variable -- this default is
+ now in make.globals but as always you should set your custom USE_ORDER in
+ make.conf if desired.) So, my default, USE settings will be calculated as
+ follows. The USE variables will be grabbed from the
+ /etc/make.profile/make.defaults file (this is "defaults".) Then, the
+ /etc/make.profile/use.defaults file will be consulted. This file lists (one
+ per line) a USE variable and a corresponding dependency. If the dependency
+ is satisfied, the USE variable is auto-enabled and added to our working list
+ (this is "auto"). Then /etc/make.conf is consulted, so that the user has the
+ option of force-enabling (with USE="foo") or force-disabling (with
+ USE="-foo") any USE variables as desired (this is "conf".) Then, the
+ environment is consulted, allowing easy modifications from the command-line
+ (this is "env"). Also added is the ability for USE settings to be
+ dynamically regenerated in an efficient way as packages are merged. So,
+ right after xfree is emerged, the "X" use variable can be immediately
+ auto-enabled. Thanks to Vitaly for providing the vision for this.
+
+*portage-1.8.9_pre23 (08 Mar 2002)
+
+ 09 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: our portage
+ tree and /var/db/pkg tree now uses incremental caching rather than doing
+ an exhaustive scan on startup. This should speed up this respective code
+ by 2-30x depending on how many packages you're emerging. This involved
+ quite a few changes to the code, and there could be some bugs, although I
+ tried to be very careful. These changes could also break code that access
+ internal .tree[] dictionaries directly.
+
+ 08 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: SRC_URIs with
+ USE-enabled ( ) clauses in them weren't working because I was iterating
+ through multi-level lists without flatten()ing them. Now fixed.
+
+ 07 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: We no longer
+ depend upon a file being unmerged. We try to unlink during unmerge() in a
+ "try" clause, with an exception for OSError. If the directory is immutable
+ then Portage continues gracefully. This closes a bug reported by Verwilst --
+ unmerging an old baselayout would die when it tried to delete /dev/shm.
+ Fixed in Portage to eliminate these kinds of problems in the future.
+
+*portage-1.8.9_pre22 (07 Mar 2002)
+
+ 07 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: I had
+ sys.exit() in doebuild()'s fetch section. Converted to "return 1" and
+ "return 0" to be emerge --fetchonly friendly. Thanks to Dan Armak for the
+ bug report.
+
+*portage-1.8.9_pre21 (07 Mar 2002)
+
+ 07 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: fixed symlink
+ merge bug related to "safe" emerges. This should fix problems of Portage
+ dying when merging certain things. I'm hoping that this fix will give us a
+ solid merge implementation. It should. Thanks to Bart Verwilst for tracking
+ down a merge problem that I could reproduce.
+
+*portage-1.8.9_pre20 (06 Mar 2002)
+
+ 06 Mar 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh, others: users
+ can now forcefully disable stripping of their ebuild binaries by adding a
+ RESTRICT="nostrip" to their ebuild. Additionally, the DEBUG variable has
+ been renamed to DEBUGBUILD to prevent namespace collisions. This closes bug
+ #868.
+
+ 06 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py : Fixed a
+ long-standing bug where the pkg_preinst() and pkg_postinst() functions being
+ called came from the existing package ebuild in /var/db/pkg rather than the
+ new ebuild being merged. pkg_prerm() and pkg_postrm() still use the ebuild
+ in /var/db/pkg, which is correct. Thanks to Dan Armak for tracking down this
+ bug.
+
+*portage-1.8.9_pre19 (05 Mar 2002)
+
+ 05 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py : Fixed two bugs
+ reported by Dan Armak relating to incomplete (not missing) message digests.
+ They should now get regenerated automatically is "digest" is in FEATURES and
+ not confuse the fetch code.
+
+*portage-1.8.9_pre18 (04 Mar 2002)
+
+ 04 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py : Bug fix in
+ dep_bestmatch(); rev comparison now works correctly and dep_bestmatch will
+ properly handle 2-digit revisions in particular. This closes bug #952.
+
+ 04 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py : Thanks to a
+ bug report by Bruce Locke, the long-standing bug where symlinks with
+ different mtimes would still get unmerged is now fixed. This allows glibc
+ (of all things) to be unmerged safely. We needed this fix. Closes bug #964.
+
+ 03 Mar 2002; Daniel Robbins <drobbins@gentoo.org> portage.py : KDEDIR ->
+ KDEDIRS (fixing my typo)
+
+*portage-1.8.9_pre17 (27 Feb 2002)
+
+ 27 Feb 2002; Daniel Robbins <drobbins@gentoo.org> emerge : --help
+ documentation is now up-to-date; short options tweaked.
+
+ 26 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py : Fixed an
+ unmerge error caused by digests now being recorded in lowercase. unmerge now
+ compensates for 100% backwards compatibility. Moved "continue" outside of
+ "try" block since this is disallowed in Python. This fixes a python warning
+ during fetch.
+
+ 26 Feb 2002; Geert Bevin <gbevin@gentoo.org> bin/dohtml : Added support for
+ installing .gif files too since quite some docs still ship with those instead
+ of .jpg or .png.
+
+*portage-1.8.9_pre16 (25 Feb 2002)
+
+ 25 Feb 2002; Daniel Robbins <drobbins@gentoo.org> emerge : emerge syntax
+ changed back to "classic" style; replaced dots with spinner, did a major code
+ cleanup and removed pieces that will be rewritten for 1.8.9 final. emerge
+ documentation isn't up-to-date at all; I'm holding off on the --help rewrite
+ until after 1.8.9 features have been finalized (soon!)
+
+ 25 Feb 2002; Daniel Robbins <drobbins@gentoo.org> : Added RESTRICT variable
+ to ebuilds. If RESTRICT="fetch" is set in the ebuild, it means that the
+ files listed in SRC_URI are simply filenames and that the real files must be
+ downloaded manually. This allows us to deal with realplayer, since
+ overriding dyn_fetch is no longer an option now that we have the fetch code
+ in python. Also added a cosmetic tweak to emerge during info file
+ regeneration.
+
+ 25 Feb 2002; Daniel Robbins <drobbins@gentoo.org> cnf/* : updated ${x} ->
+ ${URI} in $FETCHCOMMAND.
+
+ 24 Feb 2002; Daniel Robbins <drobbins@gentoo.org> Fixed another fetch bug
+ where the download wouldn't cycle to alternate mirrors (it'd get stuck on
+ the first download location)
+
+*portage-1.8.9_pre15 (24 Feb 2002)
+
+ 24 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: some fixing of
+ the merge code; added automatic digest generation when "digest" is in
+ FEATURES; made the fetch() code not depend on a pre-existing digest. This
+ should fix all known digest/fetch issues.
+
+*portage-1.8.9_pre14 (23 Feb 2002)
+
+ 23 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: If you have a
+ file that's hosted directly on our master ibiblio mirror, you can specify
+ it in SRC_URI as "http://mirror/myfile.tar.bz2". "http://mirror" will be
+ expanded to the first mirror defined in GENTOO_MIRRORS, or our master ibiblio
+ mirror if no mirrors are defined. Groovy. This closes bug #627.
+
+ 23 Feb 2002; Daniel Robbins <drobbins@gentoo.org> make.globals, emerge,
+ portage.py: wget is no longer hardcoded; FETCHCOMMAND is enabled again, but
+ uses ${FILE} and ${URI} instead of ${x} and ${y} now. Added download
+ resuming, which requires the definition of RESUMECOMMAND (added to
+ make.globals). Updated spawn() so that when it's called as spawn(foo,free=1)
+ as an argument, sandboxing is turned off. Replaced all calls to
+ os.system(foo) with spawn(foo,free=1), since os.system() messes with signal
+ handling. Added a default SIGINT signal handler to portage.py so that ^C
+ interrupts are handled correctly (portage will immediately exit with a return
+ code of 1). This has been tested and works for ebuild and emerge. These
+ additions should also close bug #407 and #760.
+
+ 23 Feb 2002; Daniel Robbins <drobbins@gentoo.org> emerge: spython -> python
+ fix; resolution of cvs merge conflict. Removed edepend assignment bug
+ reintroduced in Geert's commit; added comment explaining why the new code is
+ needed so it doesn't get removed again ;)
+
+ 22 Feb 2002; Geert Bevin <gbevin@gentoo.org> emerge: removed spurious cvs
+ conflict lines fixed bug in the cleanup code where different slots weren't
+ handled too well
+
+*portage-1.8.9_pre13 (22 Feb 2002)
+
+ 22 Feb 2002; Daniel Robbins <drobbins@gentoo.org> various: fix /bin/sh
+ symlink merge problems and massively simplified movefile() code. Added back
+ some emerge code so that "emerge --search rsync" doesn't run rsync.
+
+*portage 1.8.9_pre12 (22 Feb 2002)
+
+ 22 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: everything
+ should now generate *lowercase* md5sums, fixing problems with digest
+ backwards compatibility.
+
+ 22 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: changed
+ position of digest generation call so that "ebuild digest" now works if the
+ sources have not yet been downloaded.
+
+*portage 1.8.9_pre11 (22 Feb 2002)
+
+ 22 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: unmerging now
+ works correctly.
+
+*portage 1.8.9_pre10 (22 Feb 2002)
+
+ 22 Feb 2002; Daniel Robbins <drobbins@gentoo.org>: "emerge" didn't like the
+ new portage.py (fixed); A merge database bug (fixed). Fixing the merge bug
+ should also result in merges happening much faster than before, maybe up to 3
+ times as fast. We no longer resolve symlinks when testing protection paths.
+
+*portage 1.8.9_pre9 (21 Feb 2002)
+
+ 21 Feb 2002; Daniel Robbins <drobbins@gentoo.org>: moved entirety of Portage
+ download/digest code from ebuild.sh (bash) to portage.py (python). No
+ support for custom FETCHCOMMANDs yet, but that's coming soon. Good news is
+ that it appears to work well and allowed some cleanups and optimizations to
+ doebuild(). SYNC support added. See cnf/make.conf for more info --
+ basically, "emerge rsync" (now callable via "emerge sync" as well) supports a
+ configurable "Portage server" that begins either with "rsync://" or "cvs://".
+ "emerge sync" is now not only a clean front-end, but a configurable front-end
+ to the Portage update process. I also removed dependency checking from
+ 'ebuild'. This allowed me to removed some redundant code from portage.py,
+ and seemed fine to do since 'ebuild' is more and more becoming a low-level
+ developer tool.
+
+ 21 Feb 2002; Daniel Robbins <drobbins@gentoo.org>: rewrite of cumulative USE
+ setting code so that the new FEATURES (what used to be called MAINTAINER) is
+ now cumulative and supports "-" and "-*" options. FEATURES is expanded using
+ all config files, while USE ignores make.globals but uses everything else.
+ Optimization of a couple parts of doebuild(). Upgraded expandpath() and used
+ it in one place where it was removed accidentally (in the new merge code.)
+ Master category list is now stored externally in
+ ${PORTDIR}/profiles/categories for ease of maintenance.
+
+ 21 Feb 2002; Daniel Robbins <drobbins@gentoo.org> emerge: now supports the
+ EMERGE_OPTS make.conf variable for enabling emerge options by default.
+ Closes bug #605.
+
+ 21 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: dep_match() now
+ works with * deps (again? Looks like the code got ripped out somehow); this
+ closes bug #490.
+
+ 21 Feb 2002; Daniel Robbins <drobbins@gentoo.org> global change from
+ "spython" -> "python", now that Portage is slick enough to update shared
+ libraries correctly.
+
+ 21 Feb 2002; Grant Goodyear <g2boojum@gentoo.org> bin/chkcontents,
+ man/chkcontents.1: New script to compare what's in a package's CONTENTS file
+ with what's actually on the filesystem. Useful for discovering that a
+ package "collision" has occurred.
+
+ 21 Feb 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh, portage.py:
+ Dependencies should be no longer checked during the "unpack" stage. This
+ closes bug #231. Added the $KV kernel version variable to ebuild.sh so that
+ it's available for all ebuilds. This closes bug #599.
+
+ 21 Feb 2002; Daniel Robbins <drobbins@gentoo.org> ebuild.sh: S now defaults
+ to ${WORKDIR}/${P} if it isn't defined. That's right. Defining S is now
+ optional :) This should eliminate around 1000 lines from our ports tree.
+
+ 20 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py: Fixed some
+ major bugs in the new merge/config protect code. Merging and config
+ protection should now work.
+
+ 18 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge,
+ ebuild.sh : Rewrote merge code. Should merge symlinks only *after* the
+ target has been merged (needs testing). Added lots of comments. Split
+ dblink.merge() into 2 new functions -- .walktree() and .mergeme().
+ Cleaned/optimized merging a good deal. Added special "-*" USE variable to
+ unset *all* USE variables defined up until that point.
+
+ 18 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py, emerge,
+ ebuild.sh : Fixed USE bug (config.reset() threw away our cumulative USE),
+ streamlined turbo dep calculations by moving edb cache entry creation to
+ ebuild.sh. Started coding new dblink.merge() method that should be much
+ cleaner, faster and merge symlinks safely.
+
+ 17 Feb 2002; Daniel Robbins <drobbins@gentoo.org> portage.py : Added
+ cumulative USE variable support. The final USE var is calculated
+ cumulatively starting with make.profile, then make.conf, and then the
+ environment. Any "-foo" option in USE will turn off a previously-defined USE
+ setting. So, if you want to use the profile-default USE settings except turn
+ "X" off, you add 'USE="-X"' to /etc/make.conf and that's it. This greatly
+ simplifies USE variable maintenance since developers can now easily add new
+ USE variables that default to 'on'. Simply add the USE variable and then add
+ it to make.profile. It will then be included in everyone's USE variables
+ automatically unless they explicitly "-newvar" in /etc/make.conf or in the
+ local environment. This also enables easy one-shot disabling of USE
+ variables. For example, to merge xchat without GNOME support (when "gnome"
+ is in your /etc/make.conf USE variable), simply type "USE="-gnome" emerge
+ net-irc/xchat". This is a lot easier than temporarily tweaking
+ /etc/make.conf.
+
+ 17 Feb 2002: Daniel Robbins <drobbins@gentoo.org> emerge : Added a quick hack
+ to cache ebuild dependency info using extended attributes on XFS filesystems.
+ Gives a factor of 10 speedup for dependency calculations. Will look into a
+ generic caching solution that should offer similar performance increases on
+ all filesystems. Note: the fact that this hack is on CVS means that emerge
+ is currently in a hyper-experimental state and shouldn't be used right now.
+
+ 16 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge : added support for 'emerge
+ cat/pkg-version' instead of always having to require 'emerge cat/pkg'
+
+ 15 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge : reimplemented the display
+ of cleaned packages to clearly show all versions that are about to be removed
+ and which versions are going to stay
+
+ 13 Feb 2002; D.Robbins <drobbins@gentoo.org> emerge :
+ added --emptytree option
+
+ 13 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge, portage.py :
+ fixed little bug where emerge --clean rsync wasn't correctly handled anymore
+ implemented all new functionalities of emerge --clean, this adds --slots,
+ --versions and --all options together with world and system modes
+
+ 12 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge, portage.py :
+ changed emerge --zap to emerge --clean
+ removed parts of the already implemented slots functionality to be able to
+ fall back to a more flexible implementation. Binary compatible slots will now
+ mostly influence emerge during the --clean operation
+
+ 12 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added fallback check in case UNMERGE_DELAY hasn't been defined in
+ make.globals or make.conf
+
+*portage 1.8.9_pre8 (18 Feb 2002)
+
+ 12 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ changed the rebuild code to use depgraph instead, dramatically reducing code
+ duplication
+
+ 11 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ changed indentation of a code part that wasn't at the right level. It got the
+ count of the non slot packages during --zap completely wrong
+
+*portage 1.8.9_pre7 (11 Feb 2002)
+
+ 11 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ fixed bug in packagetree.dep_match() where a ~ dependency is returned as a
+ string instead of as a list
+
+ 11 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ - removed support for --all and world in 'emerge --unmerge', by default now
+ all matching packages are removed since with the new slots functionality
+ old package versions should not exists anymore
+ - colored package name red too when a blocking package is found during
+ pretend operation
+ - changed emerge invocation arguments to be in a new universal interface
+ format this has been decided to be :
+ 'emerge --action --option --option [packageset]'
+ some features however don't respect this, but that's since they are not
+ package installation related and are easier to use as straight commands
+ eg: emerge rsync
+ - added UNMERGE_DELAY var to make.globals and support it in emerge to obtain
+ the number of seconds to wait
+ - support for NOCOLOR="yes" as wel as NOCOLOR="true"
+ - major speedups for emerge -search
+ - added formatted package descriptions of the matches from emerge --search
+ that nicely wrap at 80 chars
+ - rewrote retrieval of package descriptions to support descriptions that are
+ specified on multiple lines
+ - added support for 'noslot' to --zap, --update and --rebuild
+
+ 11 Feb 2002; G.Bevin <gbevin@gentoo.org> sandbox.c, libsandbox.c :
+ added checks to see if the files where information is written to are really
+ regular files and not symlinks
+
+*portage 1.8.9_pre6 (10 Feb 2002)
+
+ 10 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added support for 'emerge --unmerge world' which removes all old package
+ versions from the system
+ made 'emerge --unmerge' take binary compatibility slots into account, this
+ prevents that packages with different versions but also different slots, are
+ being unmerged
+ added support for "--verbose" in "emerge rebuild" and "emerge world" to
+ provide details about packages that aren't in the local tree anymore and to
+ notify the user about which packages don't support slots
+
+ 9 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added support for the rebuild mode which rebuilds all the packages on your
+ system for which a corresponding package could be found in to portage tree
+
+ 9 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ renamed getEbuildPaths() or vartree to getebuildpaths()
+ fixed bug in the merging of binary packages
+
+ 7 Feb 2002; G.Bevin <gbevin@gentoo.org> xpack.py :
+ added additional argument to tbz2.getfile() which allows default content to
+ be provided when the requested file couldn't be found in the tbz2 archive
+
+ 7 Feb 2002; G.Bevin <gbevin@gentoo.org> ebuild.sh :
+ added SLOT information as the third entry in the temporary deps file that is
+ generated during ebuild depend,
+
+ 7 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ obtain SLOT information from the deps file instead of using the slotgrab()
+ function, removed slotgrab() function, updated some comments
+
+ 7 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added SLOT information to the generated edepend var for binary packages
+
+*portage 1.8.9_pre5 (6 Feb 2002)
+
+ 6 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ fixed bugs where the old instance wasn't unmerged correctly if slots are
+ identical, but ebuild version numbers not
+
+ 6 Feb 2002; Grant Goodyear <g2boojum@gentoo.org> cnf/make.conf :
+ Copied proxy lines from make.globals (bug 431).
+
+ 6 Feb 2002; Vitaly Kushneriuk <vitaly@gentoo.org> portage.py :
+ added missing SLOT param to merge(...).
+
+*portage 1.8.9_pre4 (6 Feb 2002)
+
+ 6 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ fixed some bugs in the handling of PROVIDES and virtual packages together
+ with slots, they used code that wasn't upudated to the new dblink constructor
+ virtuals now use "" as slot, resulting in normally to same behaviour as what
+ has been done before.
+
+ 5 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ sorted the packages to unmerge since this makes package names with revision
+ endings appear before plain version numbers. This makes the unmerge code
+ first remove the old and non slot aware packages before removing the newer
+ alternative which is in fact exactly the same apart from the revision
+ identifier.
+
+*portage 1.8.9_pre3 (5 Feb 2002)
+
+ 5 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ only let the backward compatibility algorithm kick in during unmerge since
+ it's impossible to correctly detect is in general.
+
+*portage 1.8.9_pre2 (5 Feb 2002)
+
+ 5 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ fixed bug in the backward compatibility algorithm
+
+*portage 1.8.9_pre1 (5 Feb 2002)
+
+ 4 Feb 2002; G.Bevin <gbevin@gentoo.org> ebuild.sh, emerge, portage.py :
+ added binary compatibility slots, this also contains additional code to keep
+ the unmerging of packages backwards compatible.
+
+ 4 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ added back support for the "ebuild help" command which seems to have
+ disappeared somewhere along the updates
+
+ 4 Feb 2002; G.Bevin <gbevin@gentoo.org> make.conf, make.globals :
+ added description and default entry for the imlib USE variable
+ added flag to prozilla to disable prozilla's waiting for a user's keypress
+ when a failure occurs
+
+ 4 Feb 2002; G.Bevin <gbevin@gentoo.org> output.py :
+ bugfix, write read() function instead of red(), doh !
+
+ 4 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge, portage.py :
+ implemented the ! dependency which prevents incompatible packages to be
+ installed on the same system at the same time
+
+ 4 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ most emerge invocation options now have alternative short flags
+
+ 4 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ emerge now doesn't unmerge the last version of an installed version by
+ default anymore, to really remove all instanced of packages the --all flag
+ has to be used, the --safe flag is deprecated
+
+ 3 Feb 2002; G.Bevin <gbevin@gentoo.org> output.py, emerge,make.globals :
+ all output can now be turned to black and white by using the functions in
+ output.py, this determines the mode by checking to NOCOLOR variable in
+ make.conf or make.globals
+
+ 3 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ made it possible to run emerge --help and --search as non root
+
+*portage 1.8.8-r1 (1 Feb 2002)
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py, ebuild.sh, ebuild.5 :
+ added support for a pkg_setup() function which is executed before anything
+ else and can be typically used for package configuration actions or required
+ system checks
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ implemented the noauto MAINTAINER flags for all relevant ebuild commands
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ make env-update disregard backup files
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added --pretend support instead of interactively asking to proceed,
+ also added a delay before unmerging though to be sure
+
+*portage 1.8.8 (1 Feb 2002)
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added --safe switch to complement the --unmerge option
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ rewrote the packagename without category support to also graceously handle
+ deps specifiers at the beginning, this shouldn't be used in the ebuilds, but
+ are very handy when using emerge --unmerge
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added emerge --unmerge support
+
+ 1 Feb 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ added packagename without category support in the dep_match function
+
+*portage 1.8.7 (30 Jan 2002)
+
+ 30 Jan 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ integrated and slightly adapted Brent Rahn's code to support package names
+ without category
+
+ 30 Jan 2002; G.Bevin <gbevin@gentoo.org> ebuild.sh :
+ integrated and fixed Azarah's patch to fix the wrongly generated archive size
+ in the digests
+
+*portage 1.8.6-r3 (28 Jan 2002)
+
+ 28 Jan 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ disabled warnings about non existant config file paths
+
+ 28 Jan 2002; G.Bevin <gbevin@gentoo.org> emerge :
+ added verwilst pkgsearch code, which was turned into a seperate class and
+ refactored for clarity and execution speed
+
+ 28 Jan 2002; G.Bevin <gbevin@gentoo.org> portage.py :
+ renamed _xxx vars to _prepart in Vitaly's code addition
+
+*portage 1.8.6-r2 (27 Jan 2002)
+
+ 24 Jan 2002; Vitaly Kushneriuk <vitaly@gentoo.org> portage.py :
+ Fixed version compare code Also added test script to test future versions.
+
+*portage 1.8.6-r1 (24 Jan 2002)
+
+ 24 Jan 2002; Karl Trygve Kalleberg <karltk@gentoo.org> dojar:
+ Fixed typos.
+
+*portage 1.8.6 (23 Jan 2002)
+
+ 22 Jan 2002; G.Bevin <gbevin@gentoo.org> libsandbox.c :
+ added an additional check for SANDBOX_ON to optimize the speed in the execvp
+ function call. Also removed error messages being printed when the PATH var
+ isn't set.
+
+ 20 Jan 2002; Karl Trygve Kalleberg <karltk@gentoo.org> dojar :
+ added dojar shell command as a java JAR handler
+
+ 17 Jan 2002; Daniel Robbins <drobbins@gentoo.org> :
+ The package chosen by "emerge sys-apps/shadow" now matches that chosen in an
+ emerge update or emerge system. I forgot to add some "*" dep code to the
+ dep_nomatch() method; this is now fixed.
+
+*portage 1.8.5 (13 Jan 2002)
+
+ 13 Jan 2002; G.Bevin <gbevin@gentoo.org> ebuilds.sh, portage.py:
+ added fine grained maintainer settings
+
+*portage 1.8.4 (13 Jan 2002)
+
+ 12 Jan 2002; Daniel Robbins <drobbins@gentoo.org> :
+ "emerge sys-apps/bash/" now works. (trailing "/" stripped to make
+ tab-completion users happy) This fixes bug #119
+
+ 12 Jan 2002; Daniel Robbins <drobbins@gentoo.org> :
+ Portage should no longer bomb out if the current working directory doesn't
+ exist (has been deleted from underneath).
+
+ 12 Jan 2002; Daniel Robbins <drobbins@gentoo.org> :
+ added "--world" option for "emerge update". This tells Portage to update
+ the base system *as well as* upgrade any packages that are currently
+ installed but have new versions available. This is your standard full system
+ update command. This fixes bug #122
+
+ 12 Jan 2002; Daniel Robbins <drobbins@gentoo.org> :
+ Added an expandpath() cache which speeds up merging dramatically.
+
+*portage 1.8.3 (11 Jan 2002)
+
+ 11 Jan 2002; Mikael Hallendal <hallski@gentoo.org> ebuild.sh:
+ added functions econf and einstall. Also made src_compile having a default
+ implementation.
+
+*portage 1.8.2 (07 Jan 2002)
+
+ 07 Jan 2002; G.Bevin <gbevin@gentoo.org> :
+ sandbox included in portage
+
+*portage 1.8.1 (30 Dec 2001)
+
+ 29 Dec 2001; Daniel Robbins <drobbins@gentoo.org> :
+ "emerge update" is now functional! Although the algorithm really should be
+ sound, it is still considered in testing since we may need to tweak some
+ dependencies.
+
+ 27 Dec 2001; Daniel Robbins <drobbins@gentoo.org> :
+ Removed objprelink from the default USE variable.
+
+*portage 1.8.0 (22 Dec 2001)
+
+ 22 Dec 2001; Daniel Robbins <drobbins@gentoo.org> :
+ I messed up the "transparent .so library" update. Included is the correct
+ fix, which seems to allow glibc to update on my system without any tricks.
+ I just merged a new glibc while in X, without using any of glibc's old
+ pkg_postinst/pkg_preinst hacks.
+
+ 21 Dec 2001; Daniel Robbins <drobbins@gentoo.org> make.defaults.5, make.conf.5 :
+ Moved make.defaults.5 to make.conf.5 and updated contents.
+
+*portage 1.7.8 (21 Dec 2001)
+
+ 21 Dec 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ ebuild install doesn't throw away the compile directory if ebuild has been
+ changed and MAINTAINER is set; we now use mv -f to move files into location
+ on the filesystem, making our library install method even more robust. It
+ should now be totally safe to upgrade glibc while in X and playing music
+ with xmms and surfing the Web and compiling 20 applications at once :)
+
+* portage 1.7.7 (14 Dec 2001)
+
+ 14 Dec 2001; Aron Griffis <agriffis@gentoo.org>: portage.py :
+ movefile() now unlink()s the destination file first which solves shared
+ library install problems.
+
+* portage 1.7.6 (13 Dec 2001)
+
+ 10 Dec 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ env_update() now generates an /etc/csh.env file in csh shell format.
+
+* portage 1.7.5 (13 Dec 2001)
+
+ 10 Dec 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ added a little fix so a ~ dep isn't satisfied by a *much* later installed
+ version; i.e. ~media-libs/freetype-1.3.1 satisfied by
+ media-libs/freetype-2.0.5 being installed.
+
+ 30 Nov 2001; Daniel Robbins <drobbins@gentoo.org> ebuild :
+ added a KeyboardInterrupt handler so ^C'ing a running ebuild process doesn't
+ produce a Python traceback.
+
+* portage 1.7.4 (29 Nov 2001)
+
+ 29 Nov 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ removed an unnecessary quirk in the code preventing virtual packages from
+ being in any other category but "virtual".
+
+ 25 Nov 2001; Daniel Robbins <drobbins@gentoo.org> emerge :
+ info file detection code has been improved.
+
+* portage 1.7.3 (20 Nov 2001)
+
+ 20 Nov 2001; Daniel Robbins <drobbins@gentoo.org> pdb, pdb.cgi, xpak :
+ used /usr/bin/python instead of /usr/bin/spython. Fixed.
+
+* portage 1.7.2 (13 Nov 2001)
+
+ 13 Nov 2001; Aron Griffis <agriffis@gentoo.org> :
+ emake will now try to build in parallel, and if it fails, will retry in
+ non-parallel mode.
+
+ 13 Nov 2001; Daniel Robbins <drobbins@gentoo.org> ebuild.sh :
+ an ebuild that used an archive with a name that was part of another archive
+ would cause Portage to mess up the digest check. No longer.
+
+ 31 Oct 2001; Donny Davies <woodchip@gentoo.org> make.conf, make.globals :
+ comments about merging the fetch programs before trying to use them.
+
+* portage 1.7.1 (30 Oct 2001)
+
+ 30 Oct 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ I accidentally broke "=" deps by being sloppy when I added "*" deps. Trivial
+ fix applied.
+
+* portage 1.7 (29 Oct 2001)
+
+ 29 Oct 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ strange typo fix in the empty() digraph method.
+
+* portage 1.6.12 (29 Oct 2001)
+
+ 29 Oct 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ "*" deps now implemented. "=sys/foo-1*" matches the latest 1.x version/rev of
+ sys/foo, but will not match a 2.x version.
+
+ 26 Oct 2001; Daniel Robbins <drobbins@gentoo.org> portage.py :
+ various new categories added.
+
+Portage 1.6.11, released 18 Oct 2001
+====================================
+
+ *portage.py; device nodes are now not unmerged at all.
+
+
+Portage 1.6.10, released 18 Oct 2001
+===================================
+
+ *ebuild.sh: A and AA fix; now any A="foo" lines in the ebuild are ignored,
+ allowing ebuilds with them to continue working.
+
+ *portage.py: remove gnome-apps, gnome-office, gnome-libs, add gnome-extra
+ categories.
+
+ *ebuild.sh, portage.py: You can now use USE variables in SRC_URI to
+ conditionally include archives. In MAINTAINER mode, all archives are
+ automatically included so that maintainers can check SRC_URIs and also
+ generate complete digests. A new file-based DEPEND and RDEPEND-passing
+ mechanism has been added.
+
+ *ebuild.sh Now adds filesize to the digest files
+
+Portage 1.6.9, released 15 Sep 2001
+===================================
+
+ *portage.py
+ unmerge() now does not touch device nodes. Unlinking them or touching them
+ in any way is bad practice.
+
+
+Portage 1.6.8, released 12 Sep 2001
+===================================
+
+ *portage.py
+ movefile() will now unlink() destfile if it is a symlink. Should fix
+ problems where file gets created at symlink target rather than replacing
+ the symlink.
+
+ *queryhost.sh (agriffis)
+ Parallel pinging and other fixes.
+
+Portage 1.6.7, released 05 Sep 2001
+===================================
+
+ *portage.py
+ (last-minute fix)
+ CONFIG_PROTECT unmerge protection is now observed for symlinks, fifos and
+ device nodes.
+
+ *portage.py
+ Fixes for unmerging CONFIG_PROTECTed files. Protected files are now *not*
+ unlinked from the filesystem. Messier but safer, and simplifies package
+ upgrades.
+
+ *emerge
+ Emerge output cleanups for GNU info directory generation. New --verbose
+ mode; new CONFIG_PROTECT scanning feature to let people know when there are
+ config files to be updated. New "--help config" docs to explain how to
+ do it.
+
+Portage 1.6.6, released 01 Sep 2001
+====================================
+
+ *portage.py
+ Upgraded directory merging over existing objects. Existing symlinks that
+ point to existing directories will be kept and used as is; directories will
+ be used as-is; any other objects (broken symlinks, files) will be copied
+ to origfilename.backup and a ne directory will be created in its place.
+
+Portage 1.6.5, released 31 Aug 2001
+====================================
+
+ *emerge
+ Fixes for handling multiple ebuilds, packages and/or dependencies on
+ the command-line.
+
+ *portage.py
+ An optimization to the digraph class so that the firstzero() method finds
+ matches in close to the order that keys were added to the digraph.
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..fd8cfcc8
--- /dev/null
+++ b/TODO
@@ -0,0 +1,60 @@
+# TODO list for Portage; the Gentoo Linux package system
+# $Id: TODO,v 1.11 2004/09/09 08:02:53 carpaski Exp $
+
+#
+# Add your name to the top of any item you are working actively on
+# and then commit. Be sure you have a current copy of this file.
+#
+
+Legend:
+ '*' Just do it. '#' Tricky
+ '!' Difficult '@' Restricted in some way
+
+ File "/usr/lib/portage/pym/portage_locks.py", line 46, in lockfile
+ myfd = os.open(lockfilename, os.O_CREAT|os.O_RDWR,0660)
+ OSError: [Errno 13] Permission denied: '/var/tmp/portage/tmpfs/aux_db_key_temp'
+
+
+
+
+* Clean should only produce output for 'emerge clean'
+
+# Stop using mtimes for packages. Have portage look up all files in the
+ vardb to ensure that a file isn't duplicated and unmerge it if not.
+ Potentially slow... Need some way to speed it up... hash of filenames?
+
+# Virtuals. /var/cache/edb/virtuals -- Effectively remove it.
+ /etc/portage/virtuals is a user-modifiable version that acts like an
+ incremental applied on top of an ON-DEMAND virtual calculation system.
+ Virtuals should be calculated from /var/db/pkg EVERY time it is requested.
+
+# Repoman needs to ignore all user-set info in /etc/portage
+ It's not relevant to deployed users and will probably be a general gotcha.
+
+# Multiple rsync repos.
+ bug 28796 -- Enable metadata caches for them.
+
+# STICKIES and related enhancements:
+ bug 9379, bug 13616, Aether's config code
+
+# Determine file lock status before starting downloads -- Prevent races/deletes
+ Patches exist for this. Integrate and find all colliding descriptors/cmds.
+ Create a fileIO layer? (wget and other external calls are a problem)
+
+* Add category support to searches... emerge -s @catgory
+
+@ rsync - track changes based in subtrees to reduce filetree expense.
+ Possible plans:
+ Use md5's of tree file list + md5 of subtree -- client-side burden.
+ Maintain hash of changes on rsync1 -- Server-side burden. **
+ Implement CVSUP. **
+
+# 'emerge sync' timestamp awareness -- Make sure IP is associated and not
+ used at random as servers may differ. bug 21794
+
+! Rename all undocumented variables used in bash to prefixed values that
+ are not easy to accidently duplicate. BUILDDIR --> PORTAGE_BUILDDIR or
+ something like that. Prevent ebuilds from clobbering system variables.
+
+
+
diff --git a/bin/archive-conf b/bin/archive-conf
new file mode 100755
index 00000000..6e198f49
--- /dev/null
+++ b/bin/archive-conf
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/archive-conf,v 1.7 2004/10/04 13:57:36 vapier Exp $
+
+#
+# archive-conf -- save off a config file in the dispatch-conf archive dir
+#
+# Written by Wayne Davison <gentoo@blorf.net> with code snagged from
+# Jeremy Wohl's dispatch-conf script and the portage chkcontents script.
+#
+
+import os, sys, string
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage, dispatch_conf
+
+FIND_EXTANT_CONTENTS = "find %s -name CONTENTS"
+
+MANDATORY_OPTS = [ 'archive-dir' ]
+
+try:
+ import fchksum
+ def perform_checksum(filename): return fchksum.fmd5t(filename)
+except ImportError:
+ import md5
+ def md5_to_hex(md5sum):
+ hexform = ""
+ for ix in xrange(len(md5sum)):
+ hexform = hexform + "%02x" % ord(md5sum[ix])
+ return string.lower(hexform)
+
+ def perform_checksum(filename):
+ f = open(filename, 'rb')
+ blocksize=32768
+ data = f.read(blocksize)
+ size = 0L
+ sum = md5.new()
+ while data:
+ sum.update(data)
+ size = size + len(data)
+ data = f.read(blocksize)
+ return (md5_to_hex(sum.digest()),size)
+
+def archive_conf():
+ args = []
+ content_files = []
+ md5_match_hash = {}
+
+ options = dispatch_conf.read_config(MANDATORY_OPTS)
+
+ for conf in sys.argv[1:]:
+ if not os.path.isabs(conf):
+ conf = os.path.abspath(conf)
+ args += [ conf ]
+ md5_match_hash[conf] = ''
+
+ # Find all the CONTENT files in VDB_PATH.
+ content_files += os.popen(FIND_EXTANT_CONTENTS % (portage.root+portage.VDB_PATH)).readlines()
+
+ # Search for the saved md5 checksum of all the specified config files
+ # and see if the current file is unmodified or not.
+ try:
+ todo_cnt = len(args)
+ for file in content_files:
+ file = file.rstrip()
+ try:
+ contents = open(file, "r")
+ except IOError, e:
+ print >> sys.stderr, 'archive-conf: Unable to open %s: %s' % (file, e)
+ sys.exit(1)
+ lines = contents.readlines()
+ for line in lines:
+ items = string.split(line)
+ if items[0] == 'obj':
+ for conf in args:
+ if items[1] == conf:
+ stored = string.lower(items[2])
+ real = string.lower(perform_checksum(conf)[0])
+ if stored == real:
+ md5_match_hash[conf] = conf
+ todo_cnt -= 1
+ if todo_cnt == 0:
+ raise "Break"
+ except "Break":
+ pass
+
+ for conf in args:
+ archive = os.path.join(options['archive-dir'], conf.lstrip('/'))
+ if options['use-rcs'] == 'yes':
+ dispatch_conf.rcs_archive(archive, conf, md5_match_hash[conf], '')
+ dispatch_conf.rcs_archive_post_process(archive)
+ else:
+ dispatch_conf.file_archive(archive, conf, md5_match_hash[conf], '')
+ dispatch_conf.file_archive_post_process(archive)
+
+# run
+if len(sys.argv) > 1:
+ archive_conf()
+else:
+ print >> sys.stderr, 'Usage: archive-conf /CONFIG/FILE [/CONFIG/FILE...]'
diff --git a/bin/chkcontents b/bin/chkcontents
new file mode 100755
index 00000000..eebf868c
--- /dev/null
+++ b/bin/chkcontents
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/chkcontents,v 1.11 2004/10/04 13:56:50 vapier Exp $
+
+# Very simple program to compare the md5sums of a package as listed
+# in VDB_PATH/category/package/CONTENTS with the md5sums of the
+# actual programs on the system (and makes sure that symlinks point to
+# the right files).
+
+import string, os.path, os, sys
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+import portage
+
+def CONTENTScheck(path):
+ try:
+ contents = open(path, "r")
+ except IOError, e:
+ print "Unable to open %s: %s" % (path, e)
+ sys.exit(1)
+ lines = contents.readlines()
+ for line in lines:
+ items = string.split(line)
+ # items is a list w/ size depending on the type of item listed in item[0]
+ # if items[0] = 'dir' then items[1] is the path of a directory
+ # if items[0] = 'obj' then items[1] is the path of a file,
+ # items[2] is the file's md5sum,
+ # items[3] is the file's size
+ # if items[0] = 'sym' then items[1] is the path of a symbolic link,
+ # items[2] is '->'
+ # items[3] is the file the symlink should point to
+ # items[4] is the symlink mtime
+ if (items[0] == 'obj'):
+ md5stored = string.lower(items[2])
+ # fchksum.fmdft(file) returns the file's md5sum and the file's size
+ md5real = string.lower(portage.perform_checksum(items[1])[0])
+ if (md5stored != md5real):
+ if md5real:
+ print "%s has md5sum of %s instead of %s" % (items[1], md5real, md5stored)
+ else:
+ print "%s is missing!" % items[1]
+ elif (items[0] == 'sym'):
+ link = items[1]
+ target = items[3]
+ if (not os.path.islink(link)):
+ print "%s is not a symbolic link" % link
+ continue
+ actualtarget = os.readlink(link)
+ if (os.path.normpath(actualtarget) != os.path.normpath(target)):
+ print "%s points to %s, not %s" % (link, actualtarget, target)
+
+
+if __name__ == '__main__':
+ import sys
+ if (len(sys.argv) != 2 or sys.argv[1] == "--help"):
+ print "This program compares md5sums in the file VDB_PATH/category/package/CONTENTS"
+ print "with the md5sums of the actual files on the filesystem"
+ print "(and makes sure that symlinks point to the right files)."
+ print "\nUsage: chkcontents path/to/CONTENTS"
+ sys.exit(1)
+ CONTENTScheck(sys.argv[1])
+
diff --git a/bin/clean_locks b/bin/clean_locks
new file mode 100755
index 00000000..aa6669c1
--- /dev/null
+++ b/bin/clean_locks
@@ -0,0 +1,36 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/clean_locks,v 1.1 2004/09/26 10:44:31 carpaski Exp $
+
+import os,sys
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage_locks
+
+if not sys.argv[1:] or "--help" in sys.argv or "-h" in sys.argv:
+ print
+ print "You must specify directories with hardlink-locks to clean."
+ print "You may optionally specify --force, which will remove all"
+ print "of the locks, even if we can't establish if they are in use."
+ print "Please attempt cleaning without force first."
+ print
+ print sys.argv[0]+" /usr/portage/distfiles/.locks"
+ print sys.argv[0]+" --force /usr/portage/distfiles/.locks"
+ print
+ sys.exit(1)
+
+force = False
+if "--force" in sys.argv[1:]:
+ force=True
+
+for x in sys.argv[1:]:
+ if x == "--force":
+ continue
+ for y in portage_locks.hardlock_cleanup(x, remove_all_locks=force):
+ print y
+ print
+
+
+
+ \ No newline at end of file
diff --git a/bin/dispatch-conf b/bin/dispatch-conf
new file mode 100755
index 00000000..2db6a329
--- /dev/null
+++ b/bin/dispatch-conf
@@ -0,0 +1,311 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dispatch-conf,v 1.7.2.10 2005/05/12 15:20:22 jstubbs Exp $
+
+#
+# dispatch-conf -- Integrate modified configs, post-emerge
+#
+# Jeremy Wohl (http://igmus.org)
+#
+# TODO
+# dialog menus
+#
+
+from stat import *
+from random import *
+import os, shutil, sys, string, re, commands, atexit
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage, dispatch_conf
+
+FIND_EXTANT_CONFIGS = "find %s/ -iname '._cfg????_*' | sed -e 's://:/:g'"
+DIFF_CONTENTS = 'diff -Nu %s %s'
+DIFF_CVS_INTERP = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "# .Header:.*"'
+DIFF_WSCOMMENTS = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"'
+
+# We need a secure scratch dir and python does silly verbose errors on the use of tempnam
+oldmask = os.umask(0077)
+SCRATCH_DIR = None
+while SCRATCH_DIR is None:
+ try:
+ mydir = "/tmp/dispatch-conf."
+ for x in range(0,8):
+ if int(random() * 3) == 0:
+ mydir += chr(int(65+random()*26.0))
+ elif int(random() * 2) == 0:
+ mydir += chr(int(97+random()*26.0))
+ else:
+ mydir += chr(int(48+random()*10.0))
+ if os.path.exists(mydir):
+ continue
+ os.mkdir(mydir)
+ SCRATCH_DIR = mydir
+ except OSError, e:
+ if e.errno != 17:
+ raise
+os.umask(oldmask)
+
+# Ensure the scratch dir is deleted
+def cleanup(mydir=SCRATCH_DIR):
+ shutil.rmtree(SCRATCH_DIR)
+atexit.register(cleanup)
+
+MANDATORY_OPTS = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ]
+
+class dispatch:
+ options = {}
+
+ def grind (self, config_paths):
+ confs = []
+ count = 0
+
+
+ self.options = dispatch_conf.read_config(MANDATORY_OPTS)
+
+ if self.options.has_key("log-file"):
+ if os.path.exists(self.options["log-file"]):
+ shutil.copyfile(self.options["log-file"], self.options["log-file"] + '.old')
+ os.remove(self.options["log-file"])
+ else:
+ self.options["log-file"] = "/dev/null"
+
+ #
+ # Build list of extant configs
+ #
+
+ for path in config_paths.split ():
+ if not os.path.exists (path):
+ continue
+
+ confs += self.massage (os.popen (FIND_EXTANT_CONFIGS % (path,)).readlines ())
+
+ if self.options['use-rcs'] == 'yes' and ((os.system( "which rcs >/dev/null 2>&1" ) == 256)
+ or (os.system( "which ci >/dev/null 2>&1" ) == 256)
+ or (os.system( "which co >/dev/null 2>&1" ) == 256)
+ or (os.system( "which rcsmerge >/dev/null 2>&1" ) == 256)):
+ print >> sys.stderr, 'dispatch-conf: Error finding all RCS utils and use-rcs=yes in config; fatal'
+ return False
+
+
+ #
+ # Remove new configs identical to current
+ # and
+ # Auto-replace configs a) whose differences are simply CVS interpolations,
+ # or b) whose differences are simply ws or comments,
+ # or c) in paths now unprotected by CONFIG_PROTECT_MASK,
+ #
+
+ def f (conf):
+ mrgconf = re.sub(r'\._cfg', '._mrg', conf['new'])
+ archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/'))
+ if self.options['use-rcs'] == 'yes':
+ mrgfail = dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf)
+ else:
+ mrgfail = dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
+ if os.path.exists(archive + '.dist'):
+ unmodified = len(commands.getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0
+ else:
+ unmodified = 0
+ if os.path.exists(mrgconf):
+ if mrgfail or len(commands.getoutput(DIFF_CONTENTS % (conf['new'], mrgconf))) == 0:
+ os.unlink(mrgconf)
+ newconf = conf['new']
+ else:
+ newconf = mrgconf
+ else:
+ newconf = conf['new']
+
+ same_file = len(commands.getoutput (DIFF_CONTENTS % (conf ['current'], newconf))) == 0
+ same_cvs = len(commands.getoutput (DIFF_CVS_INTERP % (conf ['current'], newconf))) == 0
+ same_wsc = len(commands.getoutput (DIFF_WSCOMMENTS % (conf ['current'], newconf))) == 0
+
+ # Do options permit?
+ same_cvs = same_cvs and self.options['replace-cvs'] == 'yes'
+ same_wsc = same_wsc and self.options['replace-wscomments'] == 'yes'
+ unmodified = unmodified and self.options['replace-unmodified'] == 'yes'
+
+ if same_file:
+ os.unlink (conf ['new'])
+ self.post_process(conf['current'])
+ if os.path.exists(mrgconf):
+ os.unlink(mrgconf)
+ return False
+ elif unmodified or same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split ():
+ self.replace(newconf, conf['current'])
+ self.post_process(conf['current'])
+ if newconf == mrgconf:
+ os.unlink(conf['new'])
+ elif os.path.exists(mrgconf):
+ os.unlink(mrgconf)
+ return False
+ else:
+ return True
+
+ confs = filter (f, confs)
+
+ #
+ # Interactively process remaining
+ #
+
+ for conf in confs:
+ count = count + 1
+
+ newconf = conf['new']
+ mrgconf = re.sub(r'\._cfg', '._mrg', newconf)
+ if os.path.exists(mrgconf):
+ newconf = mrgconf
+ show_new_diff = 0
+
+ while 1:
+ if show_new_diff:
+ os.system((self.options['diff']) % (conf['new'], mrgconf))
+ show_new_diff = 0
+ else:
+ os.system((self.options['diff']) % (conf['current'], newconf))
+
+ print
+ print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current'])
+ print '>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n m merge, t toggle-merge, l look-merge: ',
+
+ c = getch ()
+
+ if c == 'q':
+ sys.exit (0)
+ if c == 'h':
+ self.do_help ()
+ continue
+ elif c == 't':
+ if newconf == mrgconf:
+ newconf = conf['new']
+ elif os.path.exists(mrgconf):
+ newconf = mrgconf
+ continue
+ elif c == 'n':
+ break
+ elif c == 'm':
+ merged = SCRATCH_DIR+"/"+os.path.basename(conf['current'])
+ print
+ os.system (self.options['merge'] % (merged, conf ['current'], newconf))
+ shutil.copyfile(merged, mrgconf)
+ os.remove(merged)
+ mystat = os.lstat(conf['new'])
+ os.chmod(mrgconf, mystat[ST_MODE])
+ os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
+ newconf = mrgconf
+ continue
+ elif c == 'l':
+ show_new_diff = 1
+ continue
+ elif c == 'e':
+ os.system(os.environ['EDITOR'] + ' ' + newconf)
+ continue
+ elif c == 'z':
+ os.unlink(conf['new'])
+ if os.path.exists(mrgconf):
+ os.unlink(mrgconf)
+ break
+ elif c == 'u':
+ self.replace(newconf, conf ['current'])
+ self.post_process(conf['current'])
+ if newconf == mrgconf:
+ os.unlink(conf['new'])
+ elif os.path.exists(mrgconf):
+ os.unlink(mrgconf)
+ break
+ else:
+ continue
+
+
+ def replace (self, newconf, curconf):
+ """Replace current config with the new/merged version. Also logs
+ the diff of what changed into the configured log file."""
+ os.system((DIFF_CONTENTS % (curconf, newconf)) + '>>' + self.options["log-file"])
+ try:
+ shutil.copyfile(newconf, curconf)
+ os.remove(newconf)
+ except (IOError, os.error), why:
+ print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \
+ (newconf, curconf, str(why))
+
+
+ def post_process(self, curconf):
+ archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/'))
+ if self.options['use-rcs'] == 'yes':
+ dispatch_conf.rcs_archive_post_process(archive)
+ else:
+ dispatch_conf.file_archive_post_process(archive)
+
+
+ def massage (self, newconfigs):
+ """Sort, rstrip, remove old versions, break into triad hash.
+
+ Triad is dictionary of current (/etc/make.conf), new (/etc/._cfg0003_make.conf)
+ and dir (/etc).
+
+ We keep ._cfg0002_conf over ._cfg0001_conf and ._cfg0000_conf.
+ """
+ h = {}
+
+ newconfigs.sort ()
+
+ for nconf in newconfigs:
+ nconf = nconf.rstrip ()
+ conf = re.sub (r'\._cfg\d+_', '', nconf)
+ dir = re.match (r'^(.+)/', nconf).group (1)
+
+ if h.has_key (conf):
+ mrgconf = re.sub(r'\._cfg', '._mrg', h[conf]['new'])
+ if os.path.exists(mrgconf):
+ os.unlink(mrgconf)
+ os.unlink(h[conf]['new'])
+
+ h [conf] = { 'current' : conf, 'dir' : dir, 'new' : nconf }
+
+ configs = h.values ()
+ configs.sort (lambda a, b: cmp(a ['current'], b ['current']))
+
+ return configs
+
+
+ def do_help (self):
+ print; print
+
+ print ' u -- update current config with new config and continue'
+ print ' z -- zap (delete) new config and continue'
+ print ' n -- skip to next config, leave all intact'
+ print ' e -- edit new config'
+ print ' m -- interactively merge current and new configs'
+ print ' l -- look at diff between pre-merged and merged configs'
+ print ' t -- toggle new config between merged and pre-merged state'
+ print ' h -- this screen'
+ print ' q -- quit'
+
+ print; print 'press any key to return to diff...',
+
+ getch ()
+
+
+def getch ():
+ # from ASPN - Danny Yoo
+ #
+ import sys, tty, termios
+
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ try:
+ tty.setraw(sys.stdin.fileno())
+ ch = sys.stdin.read(1)
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+ return ch
+
+
+# run
+d = dispatch ()
+
+if len(sys.argv) > 1:
+ # for testing
+ d.grind (string.join (sys.argv [1:]))
+else:
+ d.grind (portage.settings ['CONFIG_PROTECT'])
diff --git a/bin/dobin b/bin/dobin
new file mode 100755
index 00000000..4c070d95
--- /dev/null
+++ b/bin/dobin
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dobin,v 1.13 2004/10/04 13:56:50 vapier Exp $
+
+if [ ${#} -lt 1 ] ; then
+ echo "${0}: at least one argument needed"
+ exit 1
+fi
+
+if [ ! -d "${D}${DESTTREE}/bin" ] ; then
+ install -d "${D}${DESTTREE}/bin" || exit 2
+fi
+
+for x in "$@" ; do
+ if [ -x "${x}" ] ; then
+ #if executable, use existing perms
+ install "${x}" "${D}${DESTTREE}/bin" || exit 3
+ else
+ #otherwise, use reasonable defaults
+ echo ">>> dobin: making ${x} executable..."
+ if [ "$USERLAND" == "GNU" ]; then
+ install -m0755 -o root -g root "${x}" "${D}${DESTTREE}/bin" || exit 4
+ else
+ install -m0755 -o root -g wheel "${x}" "${D}${DESTTREE}/bin" || exit 4
+ fi
+ fi
+done
diff --git a/bin/doconfd b/bin/doconfd
new file mode 100755
index 00000000..73d5cedc
--- /dev/null
+++ b/bin/doconfd
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/doconfd,v 1.2.2.1 2005/01/13 04:51:56 vapier Exp $
+
+if [ ${#} -lt 1 ] ; then
+ echo "doconfd: at least one argument needed"
+ exit 1
+fi
+
+tmp_INSDESTTREE="${INSDESTTREE}"
+INSDESTTREE=/etc/conf.d/
+doins "$@"
+INSDESTTREE="${tmp_INSDESTTREE}"
+unset tmp_INSDESTTREE
diff --git a/bin/dodir b/bin/dodir
new file mode 100755
index 00000000..6df8f403
--- /dev/null
+++ b/bin/dodir
@@ -0,0 +1,8 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dodir,v 1.5 2004/10/04 13:56:50 vapier Exp $
+
+for x in "$@" ; do
+ install -d ${DIROPTIONS} "${D}${x}"
+done
diff --git a/bin/dodoc b/bin/dodoc
new file mode 100755
index 00000000..a25aeddb
--- /dev/null
+++ b/bin/dodoc
@@ -0,0 +1,23 @@
+#!/bin/bash
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dodoc,v 1.6.2.2 2005/05/15 11:04:21 jstubbs Exp $
+
+if [ $# -lt 1 ] ; then
+ echo "$0: at least one argument needed" 1>&2
+ exit 1
+fi
+
+dir="${D}usr/share/doc/${PF}/${DOCDESTTREE}"
+if [ ! -d "${dir}" ] ; then
+ install -d "${dir}"
+fi
+
+for x in "$@" ; do
+ if [ -s "${x}" ] ; then
+ install -m0644 "${x}" "${dir}"
+ gzip -f -9 "${dir}/${x##*/}"
+ elif [ ! -e "${x}" ] ; then
+ echo "dodoc: ${x} does not exist" 1>&2
+ fi
+done
diff --git a/bin/doenvd b/bin/doenvd
new file mode 100755
index 00000000..8a794d7f
--- /dev/null
+++ b/bin/doenvd
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/doenvd,v 1.2.2.1 2005/01/13 04:51:56 vapier Exp $
+
+if [ ${#} -lt 1 ] ; then
+ echo "doenvd: at least one argument needed"
+ exit 1
+fi
+
+tmp_INSDESTTREE="${INSDESTTREE}"
+INSDESTTREE=/etc/env.d/
+doins "$@"
+INSDESTTREE="${tmp_INSDESTTREE}"
+unset tmp_INSDESTTREE
diff --git a/bin/doexe b/bin/doexe
new file mode 100755
index 00000000..9c2f4109
--- /dev/null
+++ b/bin/doexe
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/doexe,v 1.10.2.1 2004/12/06 03:01:43 carpaski Exp $
+
+mynum=${#}
+if [ ${mynum} -lt 1 ] ; then
+ echo "doexe: at least one argument needed"
+ exit 1
+fi
+if [ ! -d "${D}${EXEDESTTREE}" ] ; then
+ install -d "${D}${EXEDESTTREE}"
+fi
+
+for x in "$@" ; do
+ if [ -L "${x}" ] ; then
+ cp "${x}" "${T}"
+ mysrc="${T}"/`/usr/bin/basename "${x}"`
+ elif [ -d "${x}" ] ; then
+ echo "doexe: warning, skipping directory ${x}"
+ continue
+ else
+ mysrc="${x}"
+ fi
+ install ${EXEOPTIONS} "${mysrc}" "${D}${EXEDESTTREE}"
+done
diff --git a/bin/dohard b/bin/dohard
new file mode 100755
index 00000000..7313e2f2
--- /dev/null
+++ b/bin/dohard
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dohard,v 1.6 2004/10/04 13:56:50 vapier Exp $
+
+if [ ${#} -ne 2 ] ; then
+ echo "${0}: two arguments needed"
+ exit 1
+fi
+
+mysrc="${1}"
+mydest="${2}"
+ln -f "${D}${mysrc}" "${D}${mydest}"
diff --git a/bin/dohtml b/bin/dohtml
new file mode 100755
index 00000000..50e13924
--- /dev/null
+++ b/bin/dohtml
@@ -0,0 +1,159 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dohtml,v 1.14.2.1 2004/10/27 14:39:29 jstubbs Exp $
+
+#
+# Typical usage:
+# dohtml -r docs/*
+# - put all files and directories in docs into /usr/share/doc/${PF}/html
+# dohtml foo.html
+# - put foo.html into /usr/share/doc/${PF}/html
+#
+#
+# Detailed usage:
+# dohtml <list-of-files>
+# - will install the files in the list of files (space-separated list) into
+# /usr/share/doc/${PF}/html, provided the file ends in .html, .png, .jpg
+# or .css
+# dohtml -r <list-of-files-and-directories>
+# - will do as 'dohtml', but recurse into all directories, as long as the
+# directory name is not CVS
+# dohtml -A jpe,java [-r] <list-of-files[-and-directories]>
+# - will do as 'dohtml' but add .jpe,.java (default filter list is
+# added to your list)
+# dohtml -a png,gif,html,htm [-r] <list-of-files[-and-directories]>
+# - will do as 'dohtml' but filter on .png,.gif,.html,.htm (default filter
+# list is ignored)
+# dohtml -x CVS,SCCS,RCS -r <list-of-files-and-directories>
+# - will do as 'dohtml -r', but ignore directories named CVS, SCCS, RCS
+#
+
+import os
+import string
+import sys
+import types
+
+def dodir(path):
+ os.system("install -d '%s'" % path)
+
+def dofile(src,dst):
+
+ os.system("install -m0644 '%s' '%s'" % (src, dst))
+
+def install(basename, dirname, options, prefix=""):
+
+ fullpath = basename
+ if prefix: fullpath = prefix + "/" + fullpath
+ if dirname: fullpath = dirname + "/" + fullpath
+
+ if options.DOCDESTTREE:
+ destdir = options.D + "usr/share/doc/" + options.PF + "/" + options.DOCDESTTREE + "/" + options.doc_prefix + "/" + prefix
+ else:
+ destdir = options.D + "usr/share/doc/" + options.PF + "/html/" + options.doc_prefix + "/" + prefix
+
+ if os.path.isfile(fullpath):
+ ext = os.path.splitext(basename)[1]
+ if (len(ext) and ext[1:] in options.allowed_exts) or basename in options.allowed_files:
+ dodir(destdir)
+ dofile(fullpath, destdir + "/" + basename)
+ elif options.recurse and os.path.isdir(fullpath) and \
+ basename not in options.disallowed_dirs:
+ for i in os.listdir(fullpath):
+ pfx = basename
+ if prefix: pfx = prefix + "/" + pfx
+ install(i, dirname, options, pfx)
+
+class OptionsClass:
+ def __init__(self):
+ self.PF = ""
+ self.D = ""
+ self.DOCDESTTREE = ""
+
+ if os.environ.has_key("PF"):
+ self.PF = os.environ["PF"]
+ if os.environ.has_key("D"):
+ self.D = os.environ["D"]
+ if os.environ.has_key("DOCDESTTREE"):
+ self.DOCDESTTREE = os.environ["DOCDESTTREE"]
+
+ self.allowed_exts = [ 'png', 'gif', 'html', 'htm', 'jpg', 'css', 'js' ]
+ self.allowed_files = []
+ self.disallowed_dirs = [ 'CVS' ]
+ self.recurse = False
+ self.verbose = False
+ self.doc_prefix = ""
+
+def print_help():
+ opts = OptionsClass()
+
+ print "dohtml [-a .foo,.bar] [-A .foo,.bar] [-f foo,bar] [-x foo,bar]"
+ print " [-r] [-V] <file> [file ...]"
+ print
+ print " -a Set the list of allowed to those that are specified."
+ print " Default:", string.join(opts.allowed_exts, ",")
+ print " -A Extend the list of allowed file types."
+ print " -f Set list of allowed extensionless file names."
+ print " -x Set directories to be excluded from recursion."
+ print " Default:", string.join(opts.disallowed_dirs, ",")
+ print " -r Install files and directories recursively."
+ print " -V Be verbose."
+ print
+
+def parse_args():
+ options = OptionsClass()
+ args = []
+
+ x = 1
+ while x < len(sys.argv):
+ arg = sys.argv[x]
+ if arg in ["-h","-r","-V"]:
+ if arg == "-h":
+ print_help()
+ sys.exit(0)
+ elif arg == "-r":
+ options.recurse = True
+ elif arg == "-V":
+ options.verbose = True
+ elif sys.argv[x] in ["-A","-a","-f","-x","-p"]:
+ x += 1
+ if x == len(sys.argv):
+ print_help()
+ sys.exit(0)
+ elif arg == "-p":
+ options.doc_prefix = sys.argv[x]
+ else:
+ values = string.split(sys.argv[x], ",")
+ if arg == "-A":
+ options.allowed_exts.extend(values)
+ elif arg == "-a":
+ options.allowed_exts = values
+ elif arg == "-f":
+ options.allowed_files = values
+ elif arg == "-x":
+ options.disallowed_dirs = values
+ else:
+ args.append(sys.argv[x])
+ x += 1
+
+ return (options, args)
+
+def main():
+
+ (options, args) = parse_args()
+
+ if type(options.allowed_exts) == types.StringType:
+ options.allowed_exts = options.allowed_exts.split(",")
+
+ if options.verbose:
+ print "Allowed extensions:", options.allowed_exts
+ print "Document prefix : '" + options.doc_prefix + "'"
+ print "Allowed files :", options.allowed_files
+
+ for x in args:
+ basename = os.path.basename(x)
+ dirname = os.path.dirname(x)
+ install(basename, dirname, options)
+
+if __name__ == "__main__":
+ main()
diff --git a/bin/doinfo b/bin/doinfo
new file mode 100755
index 00000000..a8d7f4d7
--- /dev/null
+++ b/bin/doinfo
@@ -0,0 +1,21 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/doinfo,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ ${#} -lt 1 ] ; then
+ echo "doinfo: at least one argument needed"
+ exit 1
+fi
+if [ ! -d "${D}usr/share/info" ] ; then
+ install -d "${D}usr/share/info"
+fi
+
+for x in "$@" ; do
+ if [ -e "${x}" ] ; then
+ install -m0644 "${x}" "${D}usr/share/info"
+ gzip -f -9 "${D}usr/share/info/${x##*/}"
+ else
+ echo "doinfo: ${x} does not exist"
+ fi
+done
diff --git a/bin/doinitd b/bin/doinitd
new file mode 100755
index 00000000..d4f725ab
--- /dev/null
+++ b/bin/doinitd
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/doinitd,v 1.2.2.1 2005/01/13 04:51:56 vapier Exp $
+
+if [ ${#} -lt 1 ] ; then
+ echo "doinitd: at least one argument needed"
+ exit 1
+fi
+
+tmp_EXEDESTTREE="${EXEDESTTREE}"
+EXEDESTTREE=/etc/init.d/
+doexe "$@"
+EXEDESTTREE="${tmp_EXEDESTTREE}"
+unset tmp_EXEDESTTREE
diff --git a/bin/doins b/bin/doins
new file mode 100755
index 00000000..551905e9
--- /dev/null
+++ b/bin/doins
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/doins,v 1.7.2.2 2004/12/17 22:25:13 carpaski Exp $
+
+if [ $# -lt 1 ] ; then
+ echo "${0}: at least one argument needed"
+ exit 1
+fi
+
+if [ "${1}" == "-r" ] ; then
+ DOINSRECUR=y
+ shift
+else
+ DOINSRECUR=n
+fi
+[ -z "${INSDEPTH}" ] && declare -i INSDEPTH=0
+if [ ${INSDEPTH} -gt 30 ] ; then
+ echo "${0}: sanity check ... 30 directories is too much :("
+ exit 1
+fi
+
+if [ "${INSDESTTREE%${D}*}" == "" ]; then
+ echo "-------------------------------------------------------" 1>&2
+ echo "You should not use \${D} with helpers." 1>&2
+ echo " --> ${INSDESTTREE}" 1>&2
+ echo "-------------------------------------------------------" 1>&2
+ #exit 1
+fi
+
+[ ! -d "${D}${INSDESTTREE}" ] && dodir "${INSDESTTREE}"
+
+for x in "$@" ; do
+ if [ -L "$x" ] ; then
+ cp "$x" "${T}"
+ mysrc="${T}/$(/usr/bin/basename "${x}")"
+ elif [ -d "$x" ] ; then
+ if [ "${DOINSRECUR}" == "n" ] ; then
+ continue
+ fi
+
+ mydir="${INSDESTTREE}/$(basename "${x}")"
+ find "${x}" -mindepth 1 -maxdepth 1 -exec \
+ env \
+ INSDESTTREE="${mydir}" \
+ INSDEPTH=$((INSDEPTH+1)) \
+ doins -r {} \;
+ continue
+ else
+ mysrc="${x}"
+ fi
+ install ${INSOPTIONS} "${mysrc}" "${D}${INSDESTTREE}"
+done
diff --git a/bin/dojar b/bin/dojar
new file mode 100755
index 00000000..77dadfee
--- /dev/null
+++ b/bin/dojar
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dojar,v 1.8 2004/10/04 13:56:50 vapier Exp $
+# Author Karl Trygve Kalleberg <karltk@gentoo.org>
+
+#
+# Typical usage:
+# dojar foo.jar bar.jar
+# - installs foo.jar and bar.jar into /usr/share/${PN}/lib, and adds them
+# both to /usr/share/${PN}/classpath.env
+#
+# Detailed usage
+# dojar <list-of-jars>
+# - installs <list-of-jars> into /usr/share/${PN}/lib and adds each to
+# /usr/share/${PN}/classpath.env.
+#
+# The classpath.env file is currently merely a convenience for the user as
+# it allows him to:
+# export CLASSPATH=${CLASSPATH}:`cat /usr/share/foo/classpath.env`
+#
+# For many packages that set FOO_HOME, placing the jar files into
+# lib will allow the user to set FOO_HOME=/usr/share/foo and have the
+# scripts work as expected.
+#
+# Possibly a jarinto will be needed in the future.
+#
+
+if [ -z "$JARDESTTREE" ] ; then
+ JARDESTTREE="lib"
+fi
+
+jarroot="${DESTTREE}/share/${PN}/"
+jardest="${DESTTREE}/share/${PN}/${JARDESTTREE}/"
+pf="${D}${jarroot}/package.env"
+
+dodir "${jardest}"
+
+for i in $* ; do
+ bn="$(basename $i)"
+
+ if [ -f "$pf" ] ; then
+ oldcp=`grep "CLASSPATH=" "$pf" | sed "s/CLASSPATH=//"`
+ grep -v "CLASSPATH=" "$pf" > "${pf}.new"
+ echo "CLASSPATH=${oldcp}:${jardest}${bn}" >> "${pf}.new"
+ mv "${pf}.new" "$pf"
+ else
+ echo "DESCRIPTION=\"${DESCRIPTION}\"" > "$pf"
+ echo "CLASSPATH=${jardest}${bn}" >> "$pf"
+ fi
+
+ cp "$i" "${D}${jardest}/"
+ chmod 0444 "${D}${jardest}/${bn}"
+done
diff --git a/bin/dolib b/bin/dolib
new file mode 100755
index 00000000..51b2327d
--- /dev/null
+++ b/bin/dolib
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dolib,v 1.8.2.2 2005/01/12 02:07:15 carpaski Exp $
+
+LIBDIR_VAR="LIBDIR_${ABI}"
+if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+ CONF_LIBDIR="${!LIBDIR_VAR}"
+fi
+unset LIBDIR_VAR
+
+if [ -z "${CONF_LIBDIR}" ]; then
+ # we need this to default to lib so that things dont break
+ CONF_LIBDIR="lib"
+fi
+libdir="${D}${DESTTREE}/${CONF_LIBDIR}"
+for X in 1 2 3; do
+ # The escaping is weird. It will break if you escape the last one.
+ libdir="${libdir//\/\///}"
+done
+
+
+if [ ${#} -lt 1 ] ; then
+ echo "${0}: at least one argument needed"
+ exit 1
+fi
+if [ ! -d "${libdir}" ] ; then
+ install -d "${libdir}"
+fi
+
+for x in "$@" ; do
+ if [ -e "${x}" ] ; then
+ if [ ! -L "${x}" ] ; then
+ install ${LIBOPTIONS} "${x}" "${libdir}"
+ else
+ ln -s "$(readlink "${x}")" "${libdir}/${x}"
+ fi
+ else
+ echo "${0}: ${x} does not exist"
+ fi
+done
diff --git a/bin/dolib.a b/bin/dolib.a
new file mode 100755
index 00000000..f7cced1c
--- /dev/null
+++ b/bin/dolib.a
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dolib.a,v 1.8 2004/10/10 10:07:20 carpaski Exp $
+
+exec env LIBOPTIONS="-m0644" \
+ dolib "$@"
diff --git a/bin/dolib.so b/bin/dolib.so
new file mode 100755
index 00000000..aa6df7db
--- /dev/null
+++ b/bin/dolib.so
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dolib.so,v 1.12 2004/10/10 10:07:20 carpaski Exp $
+
+exec env LIBOPTIONS="-m0755" \
+ dolib "$@"
diff --git a/bin/doman b/bin/doman
new file mode 100755
index 00000000..5c23ea0d
--- /dev/null
+++ b/bin/doman
@@ -0,0 +1,52 @@
+#!/bin/bash
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/doman,v 1.13.2.2 2005/07/29 05:55:34 vapier Exp $
+
+if [ $# -lt 1 ] ; then
+ echo "$0: at least one argument needed" 1>&2
+ exit 1
+fi
+
+BASE="/usr/share"
+i18n=""
+
+for x in "$@" ; do
+ if [ "${x:0:6}" == "-i18n=" ] ; then
+ i18n="${x:6}/"
+ fi
+ if [ "${x}" == ".keep" ] ; then
+ continue
+ fi
+
+ suffix=${x##*.}
+
+ if [ "$suffix" == "gz" ] ; then
+ compressed="gz"
+ realname="${x%.*}"
+ suffix="${realname##*.}"
+ else
+ realname="$x"
+ compressed=""
+ fi
+
+ mandir=${i18n}man${suffix:0:1}
+
+ if echo ${mandir} | egrep -q 'man[0-9n](|f|p|pm)$' -; then
+ if [ -s "${x}" ] ; then
+ if [ ! -d "${D}${BASE}/man/${mandir}" ] ; then
+ install -d "${D}${BASE}/man/${mandir}"
+ fi
+
+ install -m0644 "${x}" "${D}${BASE}/man/${mandir}"
+
+ if [ -z "${compressed}" ] ; then
+ gzip -f -9 "${D}${BASE}/man/${mandir}/${x##*/}"
+ fi
+ else
+ echo "doman: ${x} does not exist" 1>&2
+ fi
+ else
+ echo "doman: '${x}' is probably not a man page; skipping" 1>&2
+ fi
+done
diff --git a/bin/domo b/bin/domo
new file mode 100755
index 00000000..ca3cf4b4
--- /dev/null
+++ b/bin/domo
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/domo,v 1.6 2004/10/04 13:56:50 vapier Exp $
+
+mynum=${#}
+if [ ${mynum} -lt 1 ] ; then
+ echo "${0}: at least one argument needed"
+ exit 1
+fi
+if [ ! -d "${D}${DESTTREE}/share/locale" ] ; then
+ install -d "${D}${DESTTREE}/share/locale/"
+fi
+
+for x in "$@" ; do
+ if [ -e "${x}" ] ; then
+ mytiny="${x##*/}"
+ mydir="${D}${DESTTREE}/share/locale/${mytiny%.*}/LC_MESSAGES"
+ if [ ! -d "${mydir}" ] ; then
+ install -d "${mydir}"
+ fi
+ install -m0644 "${x}" "${mydir}/${MOPREFIX}.mo"
+ else
+ echo "${0}: ${x} does not exist"
+ fi
+done
diff --git a/bin/dopython b/bin/dopython
new file mode 100755
index 00000000..a3ffab96
--- /dev/null
+++ b/bin/dopython
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dopython,v 1.8 2004/10/04 13:56:50 vapier Exp $
+
+import sys
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+from sys import *
+import portage
+import types
+mycommand=argv[1]+"("
+x=2
+while (x<len(argv)):
+ if x==(len(argv)-1):
+ mycommand=mycommand+'"'+argv[x]+'"'
+ else:
+ mycommand=mycommand+'"'+argv[x]+'",'
+ x=x+1
+mycommand=mycommand+")"
+exec("myresult="+mycommand)
+if type(myresult)==types.IntType:
+ exit(myresult)
diff --git a/bin/dosbin b/bin/dosbin
new file mode 100755
index 00000000..960d3875
--- /dev/null
+++ b/bin/dosbin
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dosbin,v 1.11 2004/10/04 13:56:50 vapier Exp $
+
+if [ ${#} -lt 1 ] ; then
+ echo "${0}: at least one argument needed"
+ exit 1
+fi
+if [ ! -d "${D}${DESTTREE}/sbin" ] ; then
+ install -d "${D}${DESTTREE}/sbin" || exit 2
+fi
+
+for x in "$@" ; do
+ if [ -x "${x}" ] ; then
+ #if executable, use existing perms
+ install -m0755 "${x}" "${D}${DESTTREE}/sbin" || exit 3
+ else
+ #otherwise, use reasonable defaults
+ echo ">>> dosbin: making ${x} executable..."
+ if [ "$USERLAND" == "GNU" ]; then
+ install -m0755 -o root -g root "${x}" "${D}${DESTTREE}/sbin" || exit 4
+ else
+ install -m0755 -o root -g wheel "${x}" "${D}${DESTTREE}/sbin" || exit 4
+ fi
+ fi
+done
diff --git a/bin/dosed b/bin/dosed
new file mode 100755
index 00000000..2c53b22d
--- /dev/null
+++ b/bin/dosed
@@ -0,0 +1,22 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dosed,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+mysed="s:${D}::g"
+
+for x in "$@" ; do
+ y="${D}${x}"
+ if [ -a "${y}" ] ; then
+ if [ -f "${y}" ] ; then
+ mysrc="${T}/${y##*/}"
+ cp "${y}" "${mysrc}"
+ sed -e "${mysed}" "${mysrc}" > "${y}"
+ else
+ echo "${y} is not a regular file!"
+ exit 1
+ fi
+ else
+ mysed="${x}"
+ fi
+done
diff --git a/bin/dosym b/bin/dosym
new file mode 100755
index 00000000..ca8cb713
--- /dev/null
+++ b/bin/dosym
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/dosym,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ ${#} -ne 2 ] ; then
+ echo "${0}: two arguments needed"
+ exit 1
+fi
+
+target="${1}"
+linkname="${2}"
+ln -snf "${target}" "${D}${linkname}"
diff --git a/bin/ebuild b/bin/ebuild
new file mode 100755
index 00000000..2c4ed713
--- /dev/null
+++ b/bin/ebuild
@@ -0,0 +1,61 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/ebuild,v 1.18.2.3 2005/05/07 04:32:59 ferringb Exp $
+
+import os,sys
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+import portage_util
+
+def getroot():
+ try:
+ a=os.environ["ROOT"]
+ if a == '/':
+ return '/'
+ except SystemExit, e:
+ raise # Needed else we can't exit.
+ except:
+ return '/'
+ return os.path.normpath(a)+'/'
+
+os.environ["PORTAGE_CALLER"]="ebuild"
+
+if len(sys.argv)<=2:
+ print "expecting two arguments."
+ sys.exit(1)
+
+import getopt
+
+debug=0
+
+opts,pargs=getopt.getopt(sys.argv[1:],'',['debug'])
+for opt in opts:
+ if opt[0]=='--debug':
+ debug=1
+
+if "merge" in pargs:
+ print "Disabling noauto in features... merge disables it. (qmerge doesn't)"
+ os.environ["FEATURES"] = os.environ.get("FEATURES", "") + " -noauto"
+
+import portage
+
+for x in pargs[1:]:
+ try:
+ tmpsettings = portage.config(clone=portage.settings)
+
+ if x in ['clean','config']:
+ cleanup=1
+ else:
+ cleanup=0
+ a=portage.doebuild(pargs[0],x,getroot(),tmpsettings,debug=debug,cleanup=cleanup)
+ except KeyboardInterrupt:
+ print "(interrupted by user -- ctrl-C?)"
+ a=1
+ except IOError:
+ a=1
+ print "ebuild: this ebuild generated output during the depend phase (bad)"
+ if a == None:
+ portage_util.writemsg("Could not run the required binary?\n")
+ sys.exit(127)
+ if a:
+ sys.exit(a)
diff --git a/bin/ebuild.sh b/bin/ebuild.sh
new file mode 100755
index 00000000..3271859e
--- /dev/null
+++ b/bin/ebuild.sh
@@ -0,0 +1,1868 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/ebuild.sh,v 1.201.2.42 2005/08/20 17:24:30 jstubbs Exp $
+
+export SANDBOX_PREDICT="${SANDBOX_PREDICT}:/proc/self/maps:/dev/console:/usr/lib/portage/pym:/dev/random"
+export SANDBOX_WRITE="${SANDBOX_WRITE}:/dev/shm:${PORTAGE_TMPDIR}"
+export SANDBOX_READ="${SANDBOX_READ}:/dev/shm:${PORTAGE_TMPDIR}"
+
+if [ ! -z "${PORTAGE_GPG_DIR}" ]; then
+ SANDBOX_PREDICT="${SANDBOX_PREDICT}:${PORTAGE_GPG_DIR}"
+fi
+
+if [ "$*" != "depend" ] && [ "$*" != "clean" ] && [ "$*" != "nofetch" ]; then
+ if [ -f "${T}/environment" ]; then
+ source "${T}/environment" &>/dev/null
+ fi
+fi
+
+if [ -n "$#" ]; then
+ ARGS="${*}"
+fi
+
+declare -rx EBUILD_PHASE="$*"
+
+# Prevent aliases from causing portage to act inappropriately.
+# Make sure it's before everything so we don't mess aliases that follow.
+unalias -a
+
+# Unset some variables that break things.
+unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE
+
+# We need this next line for "die" and "assert". It expands
+# It _must_ preceed all the calls to die and assert.
+shopt -s expand_aliases
+alias die='diefunc "$FUNCNAME" "$LINENO" "$?"'
+alias assert='_pipestatus="${PIPESTATUS[*]}"; [[ "${_pipestatus// /}" -eq 0 ]] || diefunc "$FUNCNAME" "$LINENO" "$_pipestatus"'
+alias save_IFS='[ "${IFS:-unset}" != "unset" ] && old_IFS="${IFS}"'
+alias restore_IFS='if [ "${old_IFS:-unset}" != "unset" ]; then IFS="${old_IFS}"; unset old_IFS; else unset IFS; fi'
+
+OCC="$CC"
+OCXX="$CXX"
+source /etc/profile.env &>/dev/null
+if [ -f "${PORTAGE_BASHRC}" ]; then
+ source "${PORTAGE_BASHRC}"
+fi
+[ ! -z "$OCC" ] && export CC="$OCC"
+[ ! -z "$OCXX" ] && export CXX="$OCXX"
+
+export PATH="/sbin:/usr/sbin:/usr/lib/portage/bin:/bin:/usr/bin:${ROOTPATH}"
+[ ! -z "$PREROOTPATH" ] && export PATH="${PREROOTPATH%%:}:$PATH"
+
+if [ -e /etc/init.d/functions.sh ]; then
+ source /etc/init.d/functions.sh &>/dev/null
+elif [ -e /etc/rc.d/config/functions ]; then
+ source /etc/rc.d/config/functions &>/dev/null
+else
+ #Mac OS X
+ source /usr/lib/portage/bin/functions.sh &>/dev/null
+fi
+
+# the sandbox is disabled by default except when overridden in the relevant stages
+export SANDBOX_ON="0"
+
+# sandbox support functions; defined prior to profile.bashrc srcing, since the profile might need to add a default exception (/usr/lib64/conftest fex, bug #60147)
+addread()
+{
+ export SANDBOX_READ="$SANDBOX_READ:$1"
+}
+
+addwrite()
+{
+ export SANDBOX_WRITE="$SANDBOX_WRITE:$1"
+}
+
+adddeny()
+{
+ export SANDBOX_DENY="$SANDBOX_DENY:$1"
+}
+
+addpredict()
+{
+ export SANDBOX_PREDICT="$SANDBOX_PREDICT:$1"
+}
+
+
+# source the existing profile.bashrc's.
+save_IFS
+IFS=$'\n'
+for dir in ${PROFILE_PATHS}; do
+ # Must unset it so that it doesn't mess up assumptions in the RCs.
+ unset IFS
+ if [ -f "${dir}/profile.bashrc" ]; then
+ source "${dir}/profile.bashrc"
+ fi
+done
+restore_IFS
+
+
+esyslog() {
+ # Custom version of esyslog() to take care of the "Red Star" bug.
+ # MUST follow functions.sh to override the "" parameter problem.
+ return 0
+}
+
+
+use() {
+ if useq ${1}; then
+ return 0
+ fi
+ return 1
+}
+
+usev() {
+ if useq ${1}; then
+ echo "${1}"
+ return 0
+ fi
+ return 1
+}
+
+useq() {
+ local u="${1}"
+ local neg=0
+ if [ "${u:0:1}" == "!" ]; then
+ u="${u:1}"
+ neg=1
+ fi
+ local x
+
+ # Make sure we have this USE flag in IUSE
+ if ! hasq "${u}" ${IUSE} ${E_IUSE} && ! hasq "${u}" ${PORTAGE_ARCHLIST} selinux; then
+ echo "QA Notice: USE Flag '${u}' not in IUSE for ${CATEGORY}/${PF}" >&2
+ fi
+
+ for x in ${USE}; do
+ if [ "${x}" == "${u}" ]; then
+ if [ ${neg} -eq 1 ]; then
+ return 1
+ else
+ return 0
+ fi
+ fi
+ done
+ if [ ${neg} -eq 1 ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+has() {
+ if hasq "$@"; then
+ return 0
+ fi
+ return 1
+}
+
+hasv() {
+ if hasq "$@"; then
+ echo "${1}"
+ return 0
+ fi
+ return 1
+}
+
+hasq() {
+ local x
+
+ local me=$1
+ shift
+
+ # All the TTY checks really only help out depend. Which is nice.
+ # Logging kills all this anyway. Everything becomes a pipe. --NJ
+ for x in "$@"; do
+ if [ "${x}" == "${me}" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+has_version() {
+ if [ "${EBUILD_PHASE}" == "depend" ]; then
+ echo -n "QA Notice: has_version() in global scope: " >&2
+ if [ ${ECLASS_DEPTH} -gt 0 ]; then
+ echo "eclass ${ECLASS}" >&2
+ else
+ echo "${CATEGORY}/${PF}" >&2
+ fi
+ fi
+ # return shell-true/shell-false if exists.
+ # Takes single depend-type atoms.
+ if /usr/lib/portage/bin/portageq 'has_version' "${ROOT}" "$1"; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+portageq() {
+ if [ "${EBUILD_PHASE}" == "depend" ]; then
+ echo -n "QA Notice: portageq in global scope: " >&2
+ if [ ${ECLASS_DEPTH} -gt 0 ]; then
+ echo "eclass ${ECLASS}" >&2
+ else
+ echo "${CATEGORY}/${PF}" >&2
+ fi
+ fi
+ /usr/lib/portage/bin/portageq "$@"
+}
+
+
+# ----------------------------------------------------------------------------
+# ----------------------------------------------------------------------------
+# ----------------------------------------------------------------------------
+
+
+best_version() {
+ if [ "${EBUILD_PHASE}" == "depend" ]; then
+ echo -n "QA Notice: best_version() in global scope: " >&2
+ if [ ${ECLASS_DEPTH} -gt 0 ]; then
+ echo "eclass ${ECLASS}" >&2
+ else
+ echo "${CATEGORY}/${PF}" >&2
+ fi
+ fi
+ # returns the best/most-current match.
+ # Takes single depend-type atoms.
+ /usr/lib/portage/bin/portageq 'best_version' "${ROOT}" "$1"
+}
+
+use_with() {
+ if [ -z "$1" ]; then
+ echo "!!! use_with() called without a parameter." >&2
+ echo "!!! use_with <USEFLAG> [<flagname> [value]]" >&2
+ return 1
+ fi
+
+ local UW_SUFFIX=""
+ if [ ! -z "${3}" ]; then
+ UW_SUFFIX="=${3}"
+ fi
+
+ local UWORD="$2"
+ if [ -z "${UWORD}" ]; then
+ UWORD="$1"
+ fi
+
+ if useq $1; then
+ echo "--with-${UWORD}${UW_SUFFIX}"
+ else
+ echo "--without-${UWORD}"
+ fi
+ return 0
+}
+
+use_enable() {
+ if [ -z "$1" ]; then
+ echo "!!! use_enable() called without a parameter." >&2
+ echo "!!! use_enable <USEFLAG> [<flagname> [value]]" >&2
+ return 1
+ fi
+
+ local UE_SUFFIX=""
+ if [ ! -z "${3}" ]; then
+ UE_SUFFIX="=${3}"
+ fi
+
+ local UWORD="$2"
+ if [ -z "${UWORD}" ]; then
+ UWORD="$1"
+ fi
+
+ if useq $1; then
+ echo "--enable-${UWORD}${UE_SUFFIX}"
+ else
+ echo "--disable-${UWORD}"
+ fi
+ return 0
+}
+
+diefunc() {
+ local funcname="$1" lineno="$2" exitcode="$3"
+ shift 3
+ echo >&2
+ echo "!!! ERROR: $CATEGORY/$PF failed." >&2
+ echo "!!! Function $funcname, Line $lineno, Exitcode $exitcode" >&2
+ echo "!!! ${*:-(no error message)}" >&2
+ echo "!!! If you need support, post the topmost build error, NOT this status message." >&2
+ echo >&2
+ exit 1
+}
+
+#if no perms are specified, dirs/files will have decent defaults
+#(not secretive, but not stupid)
+umask 022
+export DESTTREE=/usr
+export INSDESTTREE=""
+export EXEDESTTREE=""
+export DOCDESTTREE=""
+export INSOPTIONS="-m0644"
+export EXEOPTIONS="-m0755"
+export LIBOPTIONS="-m0644"
+export DIROPTIONS="-m0755"
+export MOPREFIX=${PN}
+
+check_KV()
+{
+ if [ -z "${KV}" ]; then
+ eerror ""
+ eerror "Could not determine your kernel version."
+ eerror "Make sure that you have /usr/src/linux symlink."
+ eerror "And that said kernel has been configured."
+ eerror "You can also simply run the following command"
+ eerror "in the kernel referenced by /usr/src/linux:"
+ eerror " make include/linux/version.h"
+ eerror ""
+ die
+ fi
+}
+
+# adds ".keep" files so that dirs aren't auto-cleaned
+keepdir()
+{
+ dodir "$@"
+ local x
+ if [ "$1" == "-R" ] || [ "$1" == "-r" ]; then
+ shift
+ find "$@" -type d -printf "${D}/%p/.keep\n" | tr "\n" "\0" | $XARGS -0 -n100 touch || die "Failed to recursive create .keep files"
+ else
+ for x in "$@"; do
+ touch "${D}/${x}/.keep" || die "Failed to create .keep in ${D}/${x}"
+ done
+ fi
+}
+
+strip_duplicate_slashes () {
+ if [ -n "${1}" ]; then
+ local removed="${1/\/\///}"
+ [ "${removed}" != "${removed/\/\///}" ] && removed=$(strip_duplicate_slashes "${removed}")
+ echo ${removed}
+ fi
+}
+
+econf() {
+ local LOCAL_EXTRA_ECONF="${EXTRA_ECONF}"
+
+ if [ -z "${ECONF_SOURCE}" ]; then
+ ECONF_SOURCE="."
+ fi
+ if [ -x "${ECONF_SOURCE}/configure" ]; then
+ if [ -e /usr/share/gnuconfig/ ]; then
+ local x
+ for x in $(find "${WORKDIR}" -type f '(' -name config.guess -o -name config.sub ')') ; do
+ echo " * econf: updating ${x/${WORKDIR}\/} with /usr/share/gnuconfig/${x##*/}"
+ cp -f /usr/share/gnuconfig/${x##*/} ${x}
+ done
+ fi
+
+ if [ ! -z "${CBUILD}" ]; then
+ LOCAL_EXTRA_ECONF="--build=${CBUILD} ${LOCAL_EXTRA_ECONF}"
+ fi
+
+ if [ ! -z "${CTARGET}" ]; then
+ LOCAL_EXTRA_ECONF="--target=${CTARGET} ${LOCAL_EXTRA_ECONF}"
+ fi
+
+ # if the profile defines a location to install libs to aside from default, pass it on.
+ # if the ebuild passes in --libdir, they're responsible for the conf_libdir fun.
+ LIBDIR_VAR="LIBDIR_${ABI}"
+ if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+ CONF_LIBDIR="${!LIBDIR_VAR}"
+ fi
+ unset LIBDIR_VAR
+ if [ -n "${CONF_LIBDIR}" ] && [ "${*/--libdir}" == "$*" ]; then
+ if [ "${*/--exec-prefix}" != "$*" ]; then
+ local args="$(echo $*)"
+ local -a pref=($(echo ${args/*--exec-prefix[= ]}))
+ CONF_PREFIX=${pref}
+ [ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}"
+ elif [ "${*/--prefix}" != "$*" ]; then
+ local args="$(echo $*)"
+ local -a pref=($(echo ${args/*--prefix[= ]}))
+ CONF_PREFIX=${pref}
+ [ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}"
+ else
+ CONF_PREFIX="/usr"
+ fi
+ export CONF_PREFIX
+ [ "${CONF_LIBDIR:0:1}" != "/" ] && CONF_LIBDIR="/${CONF_LIBDIR}"
+
+ CONF_LIBDIR_RESULT="${CONF_PREFIX}${CONF_LIBDIR}"
+ for X in 1 2 3; do
+ # The escaping is weird. It will break if you escape the last one.
+ CONF_LIBDIR_RESULT="${CONF_LIBDIR_RESULT//\/\///}"
+ done
+
+ LOCAL_EXTRA_ECONF="--libdir=${CONF_LIBDIR_RESULT} ${LOCAL_EXTRA_ECONF}"
+ fi
+
+ echo "${ECONF_SOURCE}/configure" \
+ --prefix=/usr \
+ --host=${CHOST} \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --datadir=/usr/share \
+ --sysconfdir=/etc \
+ --localstatedir=/var/lib \
+ "$@" \
+ ${LOCAL_EXTRA_ECONF}
+
+ if ! "${ECONF_SOURCE}/configure" \
+ --prefix=/usr \
+ --host=${CHOST} \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --datadir=/usr/share \
+ --sysconfdir=/etc \
+ --localstatedir=/var/lib \
+ "$@" \
+ ${LOCAL_EXTRA_ECONF}; then
+
+ if [ -s config.log ]; then
+ echo
+ echo "!!! Please attach the config.log to your bug report:"
+ echo "!!! ${PWD}/config.log"
+ fi
+ die "econf failed"
+ fi
+ else
+ die "no configure script found"
+ fi
+}
+
+einstall() {
+ # CONF_PREFIX is only set if they didn't pass in libdir above.
+ LIBDIR_VAR="LIBDIR_${ABI}"
+ if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+ CONF_LIBDIR="${!LIBDIR_VAR}"
+ fi
+ unset LIBDIR_VAR
+ if [ -n "${CONF_LIBDIR}" ] && [ "${CONF_PREFIX:-unset}" != "unset" ]; then
+ EI_DESTLIBDIR="${D}/${CONF_PREFIX}/${CONF_LIBDIR}"
+ EI_DESTLIBDIR="$(strip_duplicate_slashes ${EI_DESTLIBDIR})"
+ EXTRA_EINSTALL="libdir=${EI_DESTLIBDIR} ${EXTRA_EINSTALL}"
+ unset EI_DESTLIBDIR
+ fi
+
+ if [ -f ./[mM]akefile -o -f ./GNUmakefile ] ; then
+ if [ ! -z "${PORTAGE_DEBUG}" ]; then
+ make -n prefix=${D}/usr \
+ datadir=${D}/usr/share \
+ infodir=${D}/usr/share/info \
+ localstatedir=${D}/var/lib \
+ mandir=${D}/usr/share/man \
+ sysconfdir=${D}/etc \
+ ${EXTRA_EINSTALL} \
+ "$@" install
+ fi
+ make prefix=${D}/usr \
+ datadir=${D}/usr/share \
+ infodir=${D}/usr/share/info \
+ localstatedir=${D}/var/lib \
+ mandir=${D}/usr/share/man \
+ sysconfdir=${D}/etc \
+ ${EXTRA_EINSTALL} \
+ "$@" install || die "einstall failed"
+ else
+ die "no Makefile found"
+ fi
+}
+
+pkg_setup()
+{
+ return
+}
+
+pkg_nofetch()
+{
+ [ -z "${SRC_URI}" ] && return
+
+ echo "!!! The following are listed in SRC_URI for ${PN}:"
+ for MYFILE in `echo ${SRC_URI}`; do
+ echo "!!! $MYFILE"
+ done
+}
+
+src_unpack() {
+ if [ "${A}" != "" ]; then
+ unpack ${A}
+ fi
+}
+
+src_compile() {
+ if [ -x ./configure ]; then
+ econf
+ fi
+ if [ -f Makefile ] || [ -f GNUmakefile ] || [ -f makefile ]; then
+ emake || die "emake failed"
+ fi
+}
+
+src_test()
+{
+ addpredict /
+ if make check -n &> /dev/null; then
+ echo ">>> Test phase [check]: ${CATEGORY}/${PF}"
+ if ! make check; then
+ hasq test $FEATURES && die "Make check failed. See above for details."
+ hasq test $FEATURES || eerror "Make check failed. See above for details."
+ fi
+ elif make test -n &> /dev/null; then
+ echo ">>> Test phase [test]: ${CATEGORY}/${PF}"
+ if ! make test; then
+ hasq test $FEATURES && die "Make test failed. See above for details."
+ hasq test $FEATURES || eerror "Make test failed. See above for details."
+ fi
+ else
+ echo ">>> Test phase [none]: ${CATEGORY}/${PF}"
+ fi
+ SANDBOX_PREDICT="${SANDBOX_PREDICT%:/}"
+}
+
+src_install()
+{
+ return
+}
+
+pkg_preinst()
+{
+ return
+}
+
+pkg_postinst()
+{
+ return
+}
+
+pkg_prerm()
+{
+ return
+}
+
+pkg_postrm()
+{
+ return
+}
+
+pkg_config()
+{
+ eerror "This ebuild does not have a config function."
+}
+
+# Used to generate the /lib/cpp and /usr/bin/cc wrappers
+gen_wrapper() {
+ cat > $1 << END
+#!/bin/sh
+
+$2 "\$@"
+END
+
+ chmod 0755 $1
+}
+
+dyn_setup()
+{
+ pkg_setup
+}
+
+dyn_unpack() {
+ trap "abort_unpack" SIGINT SIGQUIT
+ local newstuff="no"
+ if [ -e "${WORKDIR}" ]; then
+ local x
+ local checkme
+ for x in ${AA}; do
+ echo ">>> Checking ${x}'s mtime..."
+ if [ "${DISTDIR}/${x}" -nt "${WORKDIR}" ]; then
+ echo ">>> ${x} has been updated; recreating WORKDIR..."
+ newstuff="yes"
+ rm -rf "${WORKDIR}"
+ break
+ fi
+ done
+ if [ "${EBUILD}" -nt "${WORKDIR}" ]; then
+ echo ">>> ${EBUILD} has been updated; recreating WORKDIR..."
+ newstuff="yes"
+ rm -rf "${WORKDIR}"
+ elif [ ! -f "${BUILDDIR}/.unpacked" ]; then
+ echo ">>> Not marked as unpacked; recreating WORKDIR..."
+ newstuff="yes"
+ rm -rf "${WORKDIR}"
+ fi
+ fi
+ if [ -e "${WORKDIR}" ]; then
+ if [ "$newstuff" == "no" ]; then
+ echo ">>> WORKDIR is up-to-date, keeping..."
+ return 0
+ fi
+ fi
+
+ install -m0700 -d "${WORKDIR}" || die "Failed to create dir '${WORKDIR}'"
+ [ -d "$WORKDIR" ] && cd "${WORKDIR}"
+ echo ">>> Unpacking source..."
+ src_unpack
+ touch "${BUILDDIR}/.unpacked" || die "IO Failure -- Failed 'touch .unpacked' in BUILDIR"
+ echo ">>> Source unpacked."
+ cd "$BUILDDIR"
+ trap SIGINT SIGQUIT
+}
+
+dyn_clean() {
+ if [ "$USERLAND" == "BSD" ] && type -p chflags &>/dev/null; then
+ chflags -R noschg,nouchg,nosappnd,nouappnd,nosunlnk,nouunlnk \
+ "${BUILDDIR}"
+ fi
+
+ if [ "$USERLAND" == "Darwin" ] && type -p chflags &>/dev/null; then
+ chflags -R noschg,nouchg,nosappnd,nouappnd "${BUILDDIR}"
+ fi
+
+ rm -rf "${BUILDDIR}/image"
+
+ if ! hasq keeptemp $FEATURES; then
+ rm -rf "${T}"
+ else
+ mv "${T}/environment" "${T}/environment.keeptemp"
+ fi
+
+ if ! hasq keepwork $FEATURES; then
+ rm -rf "${BUILDDIR}/.unpacked"
+ rm -rf "${BUILDDIR}/.compiled"
+ rm -rf "${BUILDDIR}/.tested"
+ rm -rf "${BUILDDIR}/.installed"
+ rm -rf "${BUILDDIR}/.packaged"
+ rm -rf "${BUILDDIR}/build-info"
+ rm -rf "${WORKDIR}"
+ fi
+
+ if [ -f "${BUILDDIR}/.unpacked" ]; then
+ find "${BUILDDIR}" -type d ! -regex "^${WORKDIR}" | sort -r | tr "\n" "\0" | $XARGS -0 rmdir &>/dev/null
+ fi
+
+ if [ -z "$(find "${BUILDDIR}" -mindepth 1 -maxdepth 1)" ]; then
+ rmdir "${BUILDDIR}"
+ fi
+ true
+}
+
+into() {
+ if [ $1 == "/" ]; then
+ export DESTTREE=""
+ else
+ export DESTTREE=$1
+ if [ ! -d "${D}${DESTTREE}" ]; then
+ install -d "${D}${DESTTREE}"
+ fi
+ fi
+}
+
+insinto() {
+ if [ "$1" == "/" ]; then
+ export INSDESTTREE=""
+ else
+ export INSDESTTREE=$1
+ if [ ! -d "${D}${INSDESTTREE}" ]; then
+ install -d "${D}${INSDESTTREE}"
+ fi
+ fi
+}
+
+exeinto() {
+ if [ "$1" == "/" ]; then
+ export EXEDESTTREE=""
+ else
+ export EXEDESTTREE="$1"
+ if [ ! -d "${D}${EXEDESTTREE}" ]; then
+ install -d "${D}${EXEDESTTREE}"
+ fi
+ fi
+}
+
+docinto() {
+ if [ "$1" == "/" ]; then
+ export DOCDESTTREE=""
+ else
+ export DOCDESTTREE="$1"
+ if [ ! -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}" ]; then
+ install -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}"
+ fi
+ fi
+}
+
+insopts() {
+ INSOPTIONS=""
+ for x in $*; do
+ #if we have a debug build, let's not strip anything
+ if hasq nostrip $FEATURES $RESTRICT && [ "$x" == "-s" ]; then
+ continue
+ else
+ INSOPTIONS="$INSOPTIONS $x"
+ fi
+ done
+ export INSOPTIONS
+}
+
+diropts() {
+ DIROPTIONS=""
+ for x in $*; do
+ DIROPTIONS="${DIROPTIONS} $x"
+ done
+ export DIROPTIONS
+}
+
+exeopts() {
+ EXEOPTIONS=""
+ for x in $*; do
+ #if we have a debug build, let's not strip anything
+ if hasq nostrip $FEATURES $RESTRICT && [ "$x" == "-s" ]; then
+ continue
+ else
+ EXEOPTIONS="$EXEOPTIONS $x"
+ fi
+ done
+ export EXEOPTIONS
+}
+
+libopts() {
+ LIBOPTIONS=""
+ for x in $*; do
+ #if we have a debug build, let's not strip anything
+ if hasq nostrip $FEATURES $RESTRICT && [ "$x" == "-s" ]; then
+ continue
+ else
+ LIBOPTIONS="$LIBOPTIONS $x"
+ fi
+ done
+ export LIBOPTIONS
+}
+
+abort_handler() {
+ local msg
+ if [ "$2" != "fail" ]; then
+ msg="${EBUILD}: ${1} aborted; exiting."
+ else
+ msg="${EBUILD}: ${1} failed; exiting."
+ fi
+ echo
+ echo "$msg"
+ echo
+ eval ${3}
+ #unset signal handler
+ trap SIGINT SIGQUIT
+}
+
+abort_compile() {
+ abort_handler "src_compile" $1
+ rm -f "${BUILDDIR}/.compiled"
+ exit 1
+}
+
+abort_unpack() {
+ abort_handler "src_unpack" $1
+ rm -f "${BUILDDIR}/.unpacked"
+ rm -rf "${BUILDDIR}/work"
+ exit 1
+}
+
+abort_package() {
+ abort_handler "dyn_package" $1
+ rm -f "${BUILDDIR}/.packaged"
+ rm -f "${PKGDIR}"/All/${PF}.t*
+ exit 1
+}
+
+abort_test() {
+ abort_handler "dyn_test" $1
+ rm -f "${BUILDDIR}/.tested"
+ exit 1
+}
+
+abort_install() {
+ abort_handler "src_install" $1
+ rm -rf "${BUILDDIR}/image"
+ exit 1
+}
+
+dyn_compile() {
+ trap "abort_compile" SIGINT SIGQUIT
+ [ "${CFLAGS-unset}" != "unset" ] && export CFLAGS
+ [ "${CXXFLAGS-unset}" != "unset" ] && export CXXFLAGS
+ [ "${LIBCFLAGS-unset}" != "unset" ] && export LIBCFLAGS
+ [ "${LIBCXXFLAGS-unset}" != "unset" ] && export LIBCXXFLAGS
+ [ "${LDFLAGS-unset}" != "unset" ] && export LDFLAGS
+ [ "${ASFLAGS-unset}" != "unset" ] && export ASFLAGS
+
+ [ "${CCACHE_DIR-unset}" != "unset" ] && export CCACHE_DIR
+ [ "${CCACHE_SIZE-unset}" != "unset" ] && export CCACHE_SIZE
+
+ [ "${DISTCC_DIR-unset}" == "unset" ] && export DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+ [ ! -z "${DISTCC_DIR}" ] && addwrite "${DISTCC_DIR}"
+
+ if hasq noauto $FEATURES &>/dev/null && [ ! -f ${BUILDDIR}/.unpacked ]; then
+ echo
+ echo "!!! We apparently haven't unpacked... This is probably not what you"
+ echo "!!! want to be doing... You are using FEATURES=noauto so I'll assume"
+ echo "!!! that you know what you are doing... You have 5 seconds to abort..."
+ echo
+
+ echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null
+ echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null
+ echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null
+ echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null
+
+ echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null
+ echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null
+ echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null
+ echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null
+ sleep 3
+ fi
+
+ cd "${BUILDDIR}"
+ if [ ! -e "build-info" ]; then
+ mkdir build-info
+ fi
+ cp "${EBUILD}" "build-info/${PF}.ebuild"
+
+ if [ ${BUILDDIR}/.compiled -nt "${WORKDIR}" ]; then
+ echo ">>> It appears that ${PN} is already compiled; skipping."
+ echo ">>> (clean to force compilation)"
+ trap SIGINT SIGQUIT
+ return
+ fi
+ if [ -d "${S}" ]; then
+ cd "${S}"
+ fi
+ #our custom version of libtool uses $S and $D to fix
+ #invalid paths in .la files
+ export S D
+ #some packages use an alternative to $S to build in, cause
+ #our libtool to create problematic .la files
+ export PWORKDIR="$WORKDIR"
+ src_compile
+ #|| abort_compile "fail"
+ cd "${BUILDDIR}"
+ touch .compiled
+ cd build-info
+
+ echo "$ASFLAGS" > ASFLAGS
+ echo "$CATEGORY" > CATEGORY
+ echo "$CBUILD" > CBUILD
+ echo "$CC" > CC
+ echo "$CDEPEND" > CDEPEND
+ echo "$CFLAGS" > CFLAGS
+ echo "$CHOST" > CHOST
+ echo "$CTARGET" > CTARGET
+ echo "$CXX" > CXX
+ echo "$CXXFLAGS" > CXXFLAGS
+ echo "$DEPEND" > DEPEND
+ echo "$EXTRA_ECONF" > EXTRA_ECONF
+ echo "$EXTRA_EINSTALL" > EXTRA_EINSTALL
+ echo "$EXTRA_EMAKE" > EXTRA_MAKE
+ echo "$FEATURES" > FEATURES
+ echo "$INHERITED" > INHERITED
+ echo "$IUSE" > IUSE
+ echo "$PKGUSE" > PKGUSE
+ echo "$LDFLAGS" > LDFLAGS
+ echo "$LIBCFLAGS" > LIBCFLAGS
+ echo "$LIBCXXFLAGS" > LIBCXXFLAGS
+ echo "$LICENSE" > LICENSE
+ echo "$PDEPEND" > PDEPEND
+ echo "$PF" > PF
+ echo "$PROVIDE" > PROVIDE
+ echo "$RDEPEND" > RDEPEND
+ echo "$RESTRICT" > RESTRICT
+ echo "$SLOT" > SLOT
+ echo "$USE" > USE
+
+ set > environment
+ export -p | sed 's:declare -rx:declare -x:' >> environment
+ bzip2 -9 environment
+
+ cp "${EBUILD}" "${PF}.ebuild"
+ if hasq nostrip $FEATURES $RESTRICT; then
+ touch DEBUGBUILD
+ fi
+ trap SIGINT SIGQUIT
+}
+
+dyn_package() {
+ trap "abort_package" SIGINT SIGQUIT
+ cd "${BUILDDIR}/image"
+ tar cpvf - ./ | bzip2 -f > ../bin.tar.bz2 || die "Failed to create tarball"
+ cd ..
+ xpak build-info inf.xpak
+ tbz2tool join bin.tar.bz2 inf.xpak "${PF}.tbz2"
+ mv "${PF}.tbz2" "${PKGDIR}/All" || die "Failed to move tbz2 to ${PKGDIR}/All"
+ rm -f inf.xpak bin.tar.bz2
+ if [ ! -d "${PKGDIR}/${CATEGORY}" ]; then
+ install -d "${PKGDIR}/${CATEGORY}"
+ fi
+ ln -sf "../All/${PF}.tbz2" "${PKGDIR}/${CATEGORY}/${PF}.tbz2" || die "Failed to create symlink in ${PKGDIR}/${CATEGORY}"
+ echo ">>> Done."
+ cd "${BUILDDIR}"
+ touch .packaged || die "Failed to 'touch .packaged' in ${BUILDDIR}"
+ trap SIGINT SIGQUIT
+}
+
+
+dyn_test() {
+ if [ ${BUILDDIR}/.tested -nt "${WORKDIR}" ]; then
+ echo ">>> It appears that ${PN} has already been tested; skipping."
+ return
+ fi
+ trap "abort_test" SIGINT SIGQUIT
+ if [ -d "${S}" ]; then
+ cd "${S}"
+ fi
+ if hasq maketest $RESTRICT || hasq test $RESTRICT; then
+ ewarn "Skipping make test/check due to ebuild restriction."
+ echo ">>> Test phase [explicitly disabled]: ${CATEGORY}/${PF}"
+ elif ! hasq test $FEATURES; then
+ echo ">>> Test phase [not enabled]: ${CATEGORY}/${PF}"
+ else
+ echo ">>> Test phase [enabled]: ${CATEGORY}/${PF}"
+ src_test
+ fi
+
+ cd "${BUILDDIR}"
+ touch .tested || die "Failed to 'touch .tested' in ${BUILDDIR}"
+ trap SIGINT SIGQUIT
+}
+
+
+
+dyn_install() {
+ trap "abort_install" SIGINT SIGQUIT
+ rm -rf "${BUILDDIR}/image"
+ mkdir "${BUILDDIR}/image"
+ if [ -d "${S}" ]; then
+ cd "${S}"
+ fi
+ echo
+ echo ">>> Install ${PF} into ${D} category ${CATEGORY}"
+ #our custom version of libtool uses $S and $D to fix
+ #invalid paths in .la files
+ export S D
+ #some packages uses an alternative to $S to build in, cause
+ #our libtool to create problematic .la files
+ export PWORKDIR="$WORKDIR"
+ src_install
+ #|| abort_install "fail"
+ prepall
+ cd "${D}"
+
+ declare -i UNSAFE=0
+ for i in $(find "${D}/" -type f -perm -2002); do
+ ((UNSAFE++))
+ echo "UNSAFE SetGID: $i"
+ done
+ for i in $(find "${D}/" -type f -perm -4002); do
+ ((UNSAFE++))
+ echo "UNSAFE SetUID: $i"
+ done
+
+ if type -p scanelf > /dev/null ; then
+ # Make sure we disallow insecure RUNPATH/RPATH's
+ # Don't want paths that point to the tree where the package was built
+ # (older, broken libtools would do this). Also check for null paths
+ # because the loader will search $PWD when it finds null paths.
+ f=$(scanelf -qyRF '%r %p' "${D}" | grep -E "(${BUILDDIR}|: |::|^ )")
+ if [[ -n ${f} ]] ; then
+ echo -ne '\a\n'
+ echo "QA Notice: the following files contain insecure RUNPATH's"
+ echo " Please file a bug about this at http://bugs.gentoo.org/"
+ echo " For more information on this issue, kindly review:"
+ echo " http://bugs.gentoo.org/81745"
+ echo "${f}"
+ echo -ne '\a\n'
+ die "Insecure binaries detected"
+ fi
+
+ # Check for setid binaries but are not built with BIND_NOW
+ f=$(scanelf -qyRF '%b %p' "${D}")
+ if [[ -n ${f} ]] ; then
+ echo -ne '\a\n'
+ echo "QA Notice: the following files are setXid, dyn linked, and using lazy bindings"
+ echo " This combination is generally discouraged. Try re-emerging the package:"
+ echo " LDFLAGS='-Wl,-z,now' emerge ${PN}"
+ echo "${f}"
+ echo -ne '\a\n'
+ [[ ${FEATURES/stricter} != "${FEATURES}" ]] \
+ && die "Aborting due to lazy bindings"
+ sleep 1
+ fi
+
+ # TEXTREL's are baaaaaaaad
+ f=$(scanelf -qyRF '%t %p' "${D}")
+ if [[ -n ${f} ]] ; then
+ echo -ne '\a\n'
+ echo "QA Notice: the following files contain runtime text relocations"
+ echo " Text relocations require a lot of extra work to be preformed by the"
+ echo " dynamic linker which will cause serious performance impact on IA-32"
+ echo " and might not function properly on other architectures hppa for example."
+ echo " If you are a programmer please take a closer look at this package and"
+ echo " consider writing a patch which addresses this problem."
+ echo "${f}"
+ echo -ne '\a\n'
+ [[ ${FEATURES/stricter} != "${FEATURES}" ]] \
+ && die "Aborting due to textrels"
+ sleep 1
+ fi
+
+ # Check for files with executable stacks
+ f=$(scanelf -qyRF '%e %p' "${D}")
+ if [[ -n ${f} ]] ; then
+ echo -ne '\a\n'
+ echo "QA Notice: the following files contain executable stacks"
+ echo " Files with executable stacks will not work properly (or at all!)"
+ echo " on some architectures/operating systems. A bug should be filed"
+ echo " at http://bugs.gentoo.org/ to make sure the file is fixed."
+ echo "${f}"
+ echo -ne '\a\n'
+ [[ ${FEATURES/stricter} != "${FEATURES}" ]] \
+ && die "Aborting due to +x stack"
+ sleep 1
+ fi
+
+ # Save NEEDED information
+ scanelf -qyRF '%p %n' "${D}" | sed -e 's:^:/:' > "${BUILDDIR}"/build-info/NEEDED
+ fi
+
+ if [[ ${UNSAFE} > 0 ]] ; then
+ die "There are ${UNSAFE} unsafe files. Portage will not install them."
+ fi
+
+ # dumps perms to stdout. if error, no perms dumped.
+ function stat_perms() {
+ local f
+ # only define do_stat if it hasn't been already
+ if ! type -p do_stat &> /dev/null; then
+ if ! type -p stat &>/dev/null; then
+ do_stat() {
+ # Generic version -- Octal result
+ python -c "import os,stat; print '%o' % os.stat('$1')[stat.ST_MODE]"
+ }
+ else
+ if [ "${USERLAND}" == "BSD" ] || [ "${USERLAND}" == "Darwin" ]; then
+ do_stat() {
+ # BSD version -- Octal result
+ $(type -p stat) -f '%p' "$1"
+ }
+ else
+ do_stat() {
+ # Linux version -- Hex result converted to Octal
+ f=$($(type -p stat) -c '%f' "$1") || return $?
+ printf '%o' "0x$f"
+ }
+ fi
+ fi
+ fi
+
+ f=$(do_stat "$@") || return
+ f="${f:2:4}"
+ echo $f
+ }
+
+ local file s
+ local count=0
+ find "${D}/" -user portage | while read file; do
+ count=$(( $count + 1 ))
+ [[ ! -L "${file}" ]] && s=$(stat_perms "$file")
+ if [ -z "${s}" ]; then
+ ewarn "failed stat_perm'ing $file. User intervention during install isn't wise..."
+ continue
+ fi
+ chown root "$file"
+ [[ ! -L "${file}" ]] && chmod "$s" "$file"
+ done
+ if (( $count > 0 )); then
+ ewarn "$count files were installed with user portage!"
+ fi
+
+ count=0
+ find "${D}/" -group portage | while read file; do
+ count=$(( $count + 1 ))
+ [[ ! -L "${file}" ]] && s=$(stat_perms "$file")
+ if [ -z "${s}" ]; then
+ echo "failed stat_perm'ing '$file' . User intervention during install isn't wise..."
+ continue
+ fi
+ chgrp 0 "${file}"
+ [[ ! -L "${file}" ]] && chmod "$s" "$file"
+ done
+ if (( $count > 0 )); then
+ ewarn "$count files were installed with group portage!"
+ fi
+
+ unset -f stat_perms
+
+ # Portage regenerates this on the installed system.
+ if [ -f "${D}/usr/share/info/dir.gz" ]; then
+ rm -f "${D}/usr/share/info/dir.gz"
+ fi
+
+ if hasq multilib-strict ${FEATURES} && [ -x /usr/bin/file -a -x /usr/bin/find -a \
+ -n "${MULTILIB_STRICT_DIRS}" -a -n "${MULTILIB_STRICT_DENY}" ]; then
+ MULTILIB_STRICT_EXEMPT=${MULTILIB_STRICT_EXEMPT:-"(perl5|gcc|gcc-lib)"}
+ for dir in ${MULTILIB_STRICT_DIRS}; do
+ [ -d "${D}/${dir}" ] || continue
+ for file in $(find ${D}/${dir} -type f | egrep -v "^${D}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do
+ file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" && die "File ${file} matches a file type that is not allowed in ${dir}"
+ done
+ done
+ fi
+
+ touch "${BUILDDIR}/.installed"
+ echo ">>> Completed installing ${PF} into ${D}"
+ echo
+ cd ${BUILDDIR}
+ trap SIGINT SIGQUIT
+}
+
+dyn_preinst() {
+ # set IMAGE depending if this is a binary or compile merge
+ [ "${EMERGE_FROM}" == "binary" ] && IMAGE=${PKG_TMPDIR}/${PF}/bin \
+ || IMAGE=${D}
+
+ pkg_preinst
+
+ # hopefully this will someday allow us to get rid of the no* feature flags
+ # we don't want globbing for initial expansion, but afterwards, we do
+ local shopts=$-
+ set -o noglob
+ for no_inst in ${INSTALL_MASK}; do
+ set +o noglob
+ einfo "Removing ${no_inst}"
+ # normal stuff
+ rm -Rf ${IMAGE}/${no_inst} >&/dev/null
+
+ # we also need to handle globs (*.a, *.h, etc)
+ find "${IMAGE}" -name ${no_inst} -exec rm -fR {} \; >&/dev/null
+ done
+ # set everything back the way we found it
+ set +o noglob
+ set -${shopts}
+
+ # remove man pages
+ if hasq noman $FEATURES; then
+ rm -fR "${IMAGE}/usr/share/man"
+ fi
+
+ # remove info pages
+ if hasq noinfo $FEATURES; then
+ rm -fR "${IMAGE}/usr/share/info"
+ fi
+
+ # remove docs
+ if hasq nodoc $FEATURES; then
+ rm -fR "${IMAGE}/usr/share/doc"
+ fi
+
+ # remove share dir if unnessesary
+ if hasq nodoc $FEATURES -o hasq noman $FEATURES -o hasq noinfo $FEATURES; then
+ rmdir "${IMAGE}/usr/share" &> /dev/null
+ fi
+
+ # Smart FileSystem Permissions
+ if hasq sfperms $FEATURES; then
+ for i in $(find ${IMAGE}/ -type f -perm -4000); do
+ ebegin ">>> SetUID: [chmod go-r] $i "
+ chmod go-r "$i"
+ eend $?
+ done
+ for i in $(find ${IMAGE}/ -type f -perm -2000); do
+ ebegin ">>> SetGID: [chmod o-r] $i "
+ chmod o-r "$i"
+ eend $?
+ done
+ fi
+
+ # total suid control.
+ if hasq suidctl $FEATURES > /dev/null ; then
+ sfconf=/etc/portage/suidctl.conf
+ echo ">>> Preforming suid scan in ${IMAGE}"
+ for i in $(find ${IMAGE}/ -type f \( -perm -4000 -o -perm -2000 \) ); do
+ if [ -s "${sfconf}" ]; then
+ suid="`grep ^${i/${IMAGE}/}$ ${sfconf}`"
+ if [ "${suid}" = "${i/${IMAGE}/}" ]; then
+ echo "- ${i/${IMAGE}/} is an approved suid file"
+ else
+ echo ">>> Removing sbit on non registered ${i/${IMAGE}/}"
+ for x in 5 4 3 2 1 0; do echo -ne "\a"; sleep 0.25 ; done
+ echo -ne "\a"
+ chmod ugo-s "${i}"
+ grep ^#${i/${IMAGE}/}$ ${sfconf} > /dev/null || {
+ # sandbox prevents us from writing directly
+ # to files outside of the sandbox, but this
+ # can easly be bypassed using the addwrite() function
+ addwrite "${sfconf}"
+ echo ">>> Appending commented out entry to ${sfconf} for ${PF}"
+ ls_ret=`ls -ldh "${i}"`
+ echo "## ${ls_ret%${IMAGE}*}${ls_ret#*${IMAGE}}" >> ${sfconf}
+ echo "#${i/${IMAGE}/}" >> ${sfconf}
+ # no delwrite() eh?
+ # delwrite ${sconf}
+ }
+ fi
+ else
+ echo "suidctl feature set but you are lacking a ${sfconf}"
+ fi
+ done
+ fi
+
+ # SELinux file labeling (needs to always be last in dyn_preinst)
+ if useq selinux; then
+ # only attempt to label if setfiles is executable
+ # and 'context' is available on selinuxfs.
+ if [ -f /selinux/context -a -x /usr/sbin/setfiles ]; then
+ echo ">>> Setting SELinux security labels"
+ if [ -f ${POLICYDIR}/file_contexts/file_contexts ]; then
+ cp -f "${POLICYDIR}/file_contexts/file_contexts" "${T}"
+ else
+ make -C "${POLICYDIR}" FC=${T}/file_contexts "${T}/file_contexts"
+ fi
+
+ addwrite /selinux/context
+ /usr/sbin/setfiles -r "${IMAGE}" "${T}/file_contexts" "${IMAGE}" \
+ || die "Failed to set SELinux security labels."
+ else
+ # nonfatal, since merging can happen outside a SE kernel
+ # like during a recovery situation
+ echo "!!! Unable to set SELinux security labels"
+ fi
+ fi
+ trap SIGINT SIGQUIT
+}
+
+dyn_spec() {
+ tar czf "/usr/src/redhat/SOURCES/${PF}.tar.gz" "${O}/${PF}.ebuild" "${O}/files" || die "Failed to create base rpm tarball."
+
+ cat <<__END1__ > ${PF}.spec
+Summary: ${DESCRIPTION}
+Name: ${PN}
+Version: ${PV}
+Release: ${PR}
+Copyright: GPL
+Group: portage/${CATEGORY}
+Source: ${PF}.tar.gz
+Buildroot: ${D}
+%description
+${DESCRIPTION}
+
+${HOMEPAGE}
+
+%prep
+%setup -c
+
+%build
+
+%install
+
+%clean
+
+%files
+/
+__END1__
+
+}
+
+dyn_rpm() {
+ dyn_spec
+ rpmbuild -bb "${PF}.spec" || die "Failed to integrate rpm spec file"
+ install -D "/usr/src/redhat/RPMS/i386/${PN}-${PV}-${PR}.i386.rpm" "${RPMDIR}/${CATEGORY}/${PN}-${PV}-${PR}.rpm" || die "Failed to move rpm"
+}
+
+dyn_help() {
+ echo
+ echo "Portage"
+ echo "Copyright 1999-2004 Gentoo Foundation"
+ echo
+ echo "How to use the ebuild command:"
+ echo
+ echo "The first argument to ebuild should be an existing .ebuild file."
+ echo
+ echo "One or more of the following options can then be specified. If more"
+ echo "than one option is specified, each will be executed in order."
+ echo
+ echo " help : show this help screen"
+ echo " setup : execute package specific setup actions"
+ echo " fetch : download source archive(s) and patches"
+ echo " digest : creates a digest and a manifest file for the package"
+ echo " manifest : creates a manifest file for the package"
+ echo " unpack : unpack/patch sources (auto-fetch if needed)"
+ echo " compile : compile sources (auto-fetch/unpack if needed)"
+ echo " test : test package (auto-fetch/unpack/compile if needed)"
+ echo " preinst : execute pre-install instructions"
+ echo " postinst : execute post-install instructions"
+ echo " install : installs the package to the temporary install directory"
+ echo " qmerge : merge image into live filesystem, recording files in db"
+ echo " merge : does fetch, unpack, compile, install and qmerge"
+ echo " prerm : execute pre-removal instructions"
+ echo " postrm : execute post-removal instructions"
+ echo " unmerge : remove package from live filesystem"
+ echo " config : execute package specific configuration actions"
+ echo " package : create tarball package in ${PKGDIR}/All"
+ echo " rpm : builds a RedHat RPM package"
+ echo " clean : clean up all source and temporary files"
+ echo
+ echo "The following settings will be used for the ebuild process:"
+ echo
+ echo " package : ${PF}"
+ echo " slot : ${SLOT}"
+ echo " category : ${CATEGORY}"
+ echo " description : ${DESCRIPTION}"
+ echo " system : ${CHOST}"
+ echo " c flags : ${CFLAGS}"
+ echo " c++ flags : ${CXXFLAGS}"
+ echo " make flags : ${MAKEOPTS}"
+ echo -n " build mode : "
+ if hasq nostrip $FEATURES $RESTRICT; then
+ echo "debug (large)"
+ else
+ echo "production (stripped)"
+ fi
+ echo " merge to : ${ROOT}"
+ echo
+ if [ -n "$USE" ]; then
+ echo "Additionally, support for the following optional features will be enabled:"
+ echo
+ echo " ${USE}"
+ fi
+ echo
+}
+
+# debug-print() gets called from many places with verbose status information useful
+# for tracking down problems. The output is in $T/eclass-debug.log.
+# You can set ECLASS_DEBUG_OUTPUT to redirect the output somewhere else as well.
+# The special "on" setting echoes the information, mixing it with the rest of the
+# emerge output.
+# You can override the setting by exporting a new one from the console, or you can
+# set a new default in make.*. Here the default is "" or unset.
+
+# in the future might use e* from /etc/init.d/functions.sh if i feel like it
+debug-print() {
+ # if $T isn't defined, we're in dep calculation mode and
+ # shouldn't do anything
+ [ -z "$T" ] && return 0
+
+ while [ "$1" ]; do
+
+ # extra user-configurable targets
+ if [ "$ECLASS_DEBUG_OUTPUT" == "on" ]; then
+ echo "debug: $1"
+ elif [ -n "$ECLASS_DEBUG_OUTPUT" ]; then
+ echo "debug: $1" >> $ECLASS_DEBUG_OUTPUT
+ fi
+
+ # default target
+ echo "$1" >> "${T}/eclass-debug.log"
+ # let the portage user own/write to this file
+ chmod g+w "${T}/eclass-debug.log" &>/dev/null
+
+ shift
+ done
+}
+
+# The following 2 functions are debug-print() wrappers
+
+debug-print-function() {
+ str="$1: entering function"
+ shift
+ debug-print "$str, parameters: $*"
+}
+
+debug-print-section() {
+ debug-print "now in section $*"
+}
+
+# Sources all eclasses in parameters
+declare -ix ECLASS_DEPTH=0
+inherit() {
+ ECLASS_DEPTH=$(($ECLASS_DEPTH + 1))
+ if [[ $ECLASS_DEPTH > 1 ]]; then
+ debug-print "*** Multiple Inheritence (Level: ${ECLASS_DEPTH})"
+ fi
+
+ local location
+ local PECLASS
+
+ local B_IUSE
+ local B_DEPEND
+ local B_RDEPEND
+ local B_CDEPEND
+ local B_PDEPEND
+ while [ "$1" ]; do
+ location="${ECLASSDIR}/${1}.eclass"
+
+ # PECLASS is used to restore the ECLASS var after recursion.
+ PECLASS="$ECLASS"
+ export ECLASS="$1"
+
+ if [ "$EBUILD_PHASE" != "depend" ]; then
+ if ! hasq $ECLASS $INHERITED; then
+ echo
+ echo "QA Notice: ECLASS '$ECLASS' inherited illegally in $CATEGORY/$PF" >&2
+ echo
+ fi
+ fi
+
+ # any future resolution code goes here
+ if [ -n "$PORTDIR_OVERLAY" ]; then
+ local overlay
+ for overlay in ${PORTDIR_OVERLAY}; do
+ olocation="${overlay}/eclass/${1}.eclass"
+ if [ -e "$olocation" ]; then
+ location="${olocation}"
+ debug-print " eclass exists: ${location}"
+ fi
+ done
+ fi
+ debug-print "inherit: $1 -> $location"
+
+ #We need to back up the value of DEPEND and RDEPEND to B_DEPEND and B_RDEPEND
+ #(if set).. and then restore them after the inherit call.
+
+ #turn off glob expansion
+ set -f
+
+ # Retain the old data and restore it later.
+ unset B_IUSE B_DEPEND B_RDEPEND B_CDEPEND B_PDEPEND
+ [ "${IUSE-unset}" != "unset" ] && B_IUSE="${IUSE}"
+ [ "${DEPEND-unset}" != "unset" ] && B_DEPEND="${DEPEND}"
+ [ "${RDEPEND-unset}" != "unset" ] && B_RDEPEND="${RDEPEND}"
+ [ "${CDEPEND-unset}" != "unset" ] && B_CDEPEND="${CDEPEND}"
+ [ "${PDEPEND-unset}" != "unset" ] && B_PDEPEND="${PDEPEND}"
+ unset IUSE DEPEND RDEPEND CDEPEND PDEPEND
+ #turn on glob expansion
+ set +f
+
+ source "$location" || export ERRORMSG="died sourcing $location in inherit()"
+ [ -z "${ERRORMSG}" ] || die "${ERRORMSG}"
+
+ #turn off glob expansion
+ set -f
+
+ # If each var has a value, append it to the global variable E_* to
+ # be applied after everything is finished. New incremental behavior.
+ [ "${IUSE-unset}" != "unset" ] && export E_IUSE="${E_IUSE} ${IUSE}"
+ [ "${DEPEND-unset}" != "unset" ] && export E_DEPEND="${E_DEPEND} ${DEPEND}"
+ [ "${RDEPEND-unset}" != "unset" ] && export E_RDEPEND="${E_RDEPEND} ${RDEPEND}"
+ [ "${CDEPEND-unset}" != "unset" ] && export E_CDEPEND="${E_CDEPEND} ${CDEPEND}"
+ [ "${PDEPEND-unset}" != "unset" ] && export E_PDEPEND="${E_PDEPEND} ${PDEPEND}"
+
+ [ "${B_IUSE-unset}" != "unset" ] && IUSE="${B_IUSE}"
+ [ "${B_IUSE-unset}" != "unset" ] || unset IUSE
+
+ [ "${B_DEPEND-unset}" != "unset" ] && DEPEND="${B_DEPEND}"
+ [ "${B_DEPEND-unset}" != "unset" ] || unset DEPEND
+
+ [ "${B_RDEPEND-unset}" != "unset" ] && RDEPEND="${B_RDEPEND}"
+ [ "${B_RDEPEND-unset}" != "unset" ] || unset RDEPEND
+
+ [ "${B_CDEPEND-unset}" != "unset" ] && CDEPEND="${B_CDEPEND}"
+ [ "${B_CDEPEND-unset}" != "unset" ] || unset CDEPEND
+
+ [ "${B_PDEPEND-unset}" != "unset" ] && PDEPEND="${B_PDEPEND}"
+ [ "${B_PDEPEND-unset}" != "unset" ] || unset PDEPEND
+
+ #turn on glob expansion
+ set +f
+
+ hasq $1 $INHERITED || export INHERITED="$INHERITED $1"
+
+ export ECLASS="$PECLASS"
+
+ shift
+ done
+ ECLASS_DEPTH=$(($ECLASS_DEPTH - 1))
+}
+
+# Exports stub functions that call the eclass's functions, thereby making them default.
+# For example, if ECLASS="base" and you call "EXPORT_FUNCTIONS src_unpack", the following
+# code will be eval'd:
+# src_unpack() { base_src_unpack; }
+EXPORT_FUNCTIONS() {
+ if [ -z "$ECLASS" ]; then
+ echo "EXPORT_FUNCTIONS without a defined ECLASS" >&2
+ exit 1
+ fi
+ while [ "$1" ]; do
+ debug-print "EXPORT_FUNCTIONS: ${1} -> ${ECLASS}_${1}"
+ eval "$1() { ${ECLASS}_$1 "\$@" ; }" > /dev/null
+ shift
+ done
+}
+
+# adds all parameters to E_DEPEND and E_RDEPEND, which get added to DEPEND
+# and RDEPEND after the ebuild has been processed. This is important to
+# allow users to use DEPEND="foo" without frying dependencies added by an
+# earlier inherit. It also allows RDEPEND to work properly, since a lot
+# of ebuilds assume that an unset RDEPEND gets its value from DEPEND.
+# Without eclasses, this is true. But with them, the eclass may set
+# RDEPEND itself (or at least used to) which would prevent RDEPEND from
+# getting its value from DEPEND. This is a side-effect that made eclasses
+# have unreliable dependencies.
+
+newdepend() {
+ debug-print-function newdepend $*
+ debug-print "newdepend: E_DEPEND=$E_DEPEND E_RDEPEND=$E_RDEPEND"
+
+ while [ -n "$1" ]; do
+ case $1 in
+ "/autotools")
+ do_newdepend DEPEND sys-devel/autoconf sys-devel/automake sys-devel/make
+ ;;
+ "/c")
+ do_newdepend DEPEND sys-devel/gcc virtual/libc
+ do_newdepend RDEPEND virtual/libc
+ ;;
+ *)
+ do_newdepend DEPEND $1
+ ;;
+ esac
+ shift
+ done
+}
+
+newrdepend() {
+ debug-print-function newrdepend $*
+ do_newdepend RDEPEND $1
+}
+
+newcdepend() {
+ debug-print-function newcdepend $*
+ do_newdepend CDEPEND $1
+}
+
+newpdepend() {
+ debug-print-function newpdepend $*
+ do_newdepend PDEPEND $1
+}
+
+do_newdepend() {
+ # This function does a generic change determining whether we're in an
+ # eclass or not. If we are, we change the E_* variables for deps.
+ debug-print-function do_newdepend $*
+ [ -z "$1" ] && die "do_newdepend without arguments"
+
+ # Grab what we're affecting... Figure out if we're affecting eclasses.
+ [[ ${ECLASS_DEPTH} > 0 ]] && TARGET="E_$1"
+ [[ ${ECLASS_DEPTH} > 0 ]] || TARGET="$1"
+ shift # $1 was a variable name.
+
+ while [ -n "$1" ]; do
+ # This bit of evil takes TARGET and uses it to evaluate down to a
+ # variable. This is a sneaky way to make this infinately expandable.
+ # The normal translation of this would look something like this:
+ # E_DEPEND="${E_DEPEND} $1" :::::: Cool, huh? :)
+ eval export ${TARGET}=\"\${${TARGET}} \$1\"
+ shift
+ done
+}
+
+# this is a function for removing any directory matching a passed in pattern from
+# PATH
+remove_path_entry() {
+ save_IFS
+ IFS=":"
+ stripped_path="${PATH}"
+ while [ -n "$1" ]; do
+ cur_path=""
+ for p in ${stripped_path}; do
+ if [ "${p/${1}}" == "${p}" ]; then
+ cur_path="${cur_path}:${p}"
+ fi
+ done
+ stripped_path="${cur_path#:*}"
+ shift
+ done
+ restore_IFS
+ PATH="${stripped_path}"
+}
+
+# === === === === === === === === === === === === === === === === === ===
+# === === === === === functions end, main part begins === === === === ===
+# === === === === === functions end, main part begins === === === === ===
+# === === === === === functions end, main part begins === === === === ===
+# === === === === === === === === === === === === === === === === === ===
+
+if [ "$*" != "depend" ] && [ "$*" != "clean" ]; then
+ cd ${PORTAGE_TMPDIR} &> /dev/null
+ cd ${BUILD_PREFIX} &> /dev/null
+
+ if [ "$(id -nu)" == "portage" ] ; then
+ export USER=portage
+ fi
+
+ if hasq distcc ${FEATURES} &>/dev/null; then
+ if [ -d /usr/lib/distcc/bin ]; then
+ #We can enable distributed compile support
+ if [ -z "${PATH/*distcc*/}" ]; then
+ # Remove the other reference.
+ remove_path_entry "distcc"
+ fi
+ export PATH="/usr/lib/distcc/bin:${PATH}"
+ [ ! -z "${DISTCC_LOG}" ] && addwrite "$(dirname ${DISTCC_LOG})"
+ elif which distcc &>/dev/null; then
+ export CC="distcc $CC"
+ export CXX="distcc $CXX"
+ fi
+ fi
+
+ if hasq ccache ${FEATURES} &>/dev/null; then
+ #We can enable compiler cache support
+ if [ -z "${PATH/*ccache*/}" ]; then
+ # Remove the other reference.
+ remove_path_entry "ccache"
+ fi
+
+ if [ -d /usr/lib/ccache/bin ]; then
+ export PATH="/usr/lib/ccache/bin:${PATH}"
+ elif [ -d /usr/bin/ccache ]; then
+ export PATH="/usr/bin/ccache:${PATH}"
+ fi
+
+ [ -z "${CCACHE_DIR}" ] && export CCACHE_DIR="/root/.ccache"
+
+ addread "${CCACHE_DIR}"
+ addwrite "${CCACHE_DIR}"
+
+ [ -n "${CCACHE_SIZE}" ] && ccache -M ${CCACHE_SIZE} &> /dev/null
+ fi
+
+ # XXX: Load up the helper functions.
+# for X in /usr/lib/portage/bin/functions/*.sh; do
+# source ${X} || die "Failed to source ${X}"
+# done
+
+else
+
+killparent() {
+ trap INT
+ kill ${PORTAGE_MASTER_PID}
+}
+trap "killparent" INT
+
+fi # "$*"!="depend" && "$*"!="clean"
+
+export SANDBOX_ON="1"
+export S=${WORKDIR}/${P}
+
+unset E_IUSE E_DEPEND E_RDEPEND E_CDEPEND E_PDEPEND
+
+declare -r T P PN PV PVR PR A D EBUILD EMERGE_FROM O PPID FILESDIR
+declare -r PORTAGE_TMPDIR
+
+# Turn of extended glob matching so that g++ doesn't get incorrectly matched.
+shopt -u extglob
+
+QA_INTERCEPTORS="javac java-config python python-config perl grep egrep fgrep sed gcc g++ cc bash awk nawk gawk pkg-config"
+# level the QA interceptors if we're in depend
+if hasq "depend" "$@"; then
+ for BIN in ${QA_INTERCEPTORS}; do
+ BIN_PATH=`type -pf ${BIN}`
+ if [ "$?" != "0" ]; then
+ BODY="echo \"*** missing command: ${BIN}\" >&2; return 127"
+ else
+ BODY="${BIN_PATH} \"\$@\"; return \$?"
+ fi
+ FUNC_SRC="${BIN}() {
+ echo -n \"QA Notice: ${BIN} in global scope: \" >&2
+ if [ \$ECLASS_DEPTH -gt 0 ]; then
+ echo \"eclass \${ECLASS}\" >&2
+ else
+ echo \"\${CATEGORY}/\${PF}\" >&2
+ fi
+ ${BODY}
+ }";
+ eval "$FUNC_SRC" || echo "error creating QA interceptor ${BIN}" >&2
+ done
+ unset src bin_path body
+fi
+source ${EBUILD} || die "error sourcing ebuild"
+if ! hasq depend $EBUILD_PHASE; then
+ RESTRICT="${PORTAGE_RESTRICT}"
+ unset PORTAGE_RESTRICT
+fi
+[ -z "${ERRORMSG}" ] || die "${ERRORMSG}"
+
+# Expand KEYWORDS
+# We need to turn off pathname expansion for -* in KEYWORDS and
+# we need to escape ~ to avoid tilde expansion
+set -f
+KEYWORDS="`eval echo ${KEYWORDS//~/\\~}`"
+set +f
+
+hasq nostrip ${RESTRICT} && export DEBUGBUILD=1
+
+#a reasonable default for $S
+if [ "$S" = "" ]; then
+ export S=${WORKDIR}/${P}
+fi
+
+#wipe the interceptors. we don't want saved.
+if hasq "depend" "$@"; then
+ unset -f $QA_INTERCEPTORS
+ unset QA_INTERCEPTORS
+fi
+
+#some users have $TMP/$TMPDIR to a custom dir in their home ...
+#this will cause sandbox errors with some ./configure
+#scripts, so set it to $T.
+export TMP="${T}"
+export TMPDIR="${T}"
+
+# Note: this next line is not the same as export RDEPEND=${RDEPEND:-${DEPEND}}
+# That will test for unset *or* NULL (""). We want just to set for unset...
+
+#turn off glob expansion from here on in to prevent *'s and ? in the DEPEND
+#syntax from getting expanded :) Fixes bug #1473
+#check eclass rdepends also. bug #58819
+set -f
+if [ "${RDEPEND-unset}" == "unset" ] && [ "${E_RDEPEND-unset}" == "unset" ] ; then
+ export RDEPEND="${DEPEND} ${E_DEPEND}"
+ debug-print "RDEPEND: not set... Setting to: ${DEPEND}"
+fi
+
+#add in dependency info from eclasses
+IUSE="$IUSE $E_IUSE"
+DEPEND="$DEPEND $E_DEPEND"
+RDEPEND="$RDEPEND $E_RDEPEND"
+CDEPEND="$CDEPEND $E_CDEPEND"
+PDEPEND="$PDEPEND $E_PDEPEND"
+
+unset E_IUSE E_DEPEND E_RDEPEND E_CDEPEND E_PDEPEND
+
+if [ "${EBUILD_PHASE}" != "depend" ]; then
+ # Lock the dbkey variables after the global phase
+ declare -r DEPEND RDEPEND SLOT SRC_URI RESTRICT HOMEPAGE LICENSE DESCRIPTION
+ declare -r KEYWORDS INHERITED IUSE CDEPEND PDEPEND PROVIDE
+fi
+
+set +f
+
+for myarg in $*; do
+ case $myarg in
+ nofetch)
+ pkg_nofetch
+ exit 1
+ ;;
+ prerm|postrm|postinst|config)
+ export SANDBOX_ON="0"
+ if [ "$PORTAGE_DEBUG" != "1" ]; then
+ pkg_${myarg}
+ #Allow non-zero return codes since they can be caused by &&
+ else
+ set -x
+ pkg_${myarg}
+ #Allow non-zero return codes since they can be caused by &&
+ set +x
+ fi
+ ;;
+ unpack|compile|test|clean|install)
+ if [ "${SANDBOX_DISABLED="0"}" == "0" ]; then
+ export SANDBOX_ON="1"
+ else
+ export SANDBOX_ON="0"
+ fi
+ if [ "$PORTAGE_DEBUG" != "1" ]; then
+ dyn_${myarg}
+ #Allow non-zero return codes since they can be caused by &&
+ else
+ set -x
+ dyn_${myarg}
+ #Allow non-zero return codes since they can be caused by &&
+ set +x
+ fi
+ export SANDBOX_ON="0"
+ ;;
+ help|clean|setup|preinst)
+ #pkg_setup needs to be out of the sandbox for tmp file creation;
+ #for example, awking and piping a file in /tmp requires a temp file to be created
+ #in /etc. If pkg_setup is in the sandbox, both our lilo and apache ebuilds break.
+ export SANDBOX_ON="0"
+ if [ "$PORTAGE_DEBUG" != "1" ]; then
+ dyn_${myarg}
+ else
+ set -x
+ dyn_${myarg}
+ set +x
+ fi
+ ;;
+ package|rpm)
+ export SANDBOX_ON="0"
+ if [ "$PORTAGE_DEBUG" != "1" ]; then
+ dyn_${myarg}
+ else
+ set -x
+ dyn_${myarg}
+ set +x
+ fi
+ ;;
+ depend)
+ export SANDBOX_ON="0"
+ set -f
+
+ # Handled in portage.py now
+ #dbkey=${PORTAGE_CACHEDIR}/${CATEGORY}/${PF}
+
+ if [ ! -d "${dbkey%/*}" ]; then
+ install -d -g ${PORTAGE_GID} -m2775 "${dbkey%/*}"
+ fi
+
+ # Make it group writable. 666&~002==664
+ umask 002
+
+ #the extra `echo` commands remove newlines
+ echo `echo "$DEPEND"` > $dbkey
+ echo `echo "$RDEPEND"` >> $dbkey
+ echo `echo "$SLOT"` >> $dbkey
+ echo `echo "$SRC_URI"` >> $dbkey
+ echo `echo "$RESTRICT"` >> $dbkey
+ echo `echo "$HOMEPAGE"` >> $dbkey
+ echo `echo "$LICENSE"` >> $dbkey
+ echo `echo "$DESCRIPTION"` >> $dbkey
+ echo `echo "$KEYWORDS"` >> $dbkey
+ echo `echo "$INHERITED"` >> $dbkey
+ echo `echo "$IUSE"` >> $dbkey
+ echo `echo "$CDEPEND"` >> $dbkey
+ echo `echo "$PDEPEND"` >> $dbkey
+ echo `echo "$PROVIDE"` >> $dbkey
+ echo `echo "$UNUSED_01"` >> $dbkey
+ echo `echo "$UNUSED_02"` >> $dbkey
+ echo `echo "$UNUSED_03"` >> $dbkey
+ echo `echo "$UNUSED_04"` >> $dbkey
+ echo `echo "$UNUSED_05"` >> $dbkey
+ echo `echo "$UNUSED_06"` >> $dbkey
+ echo `echo "$UNUSED_07"` >> $dbkey
+ echo `echo "$UNUSED_08"` >> $dbkey
+ set +f
+ #make sure it is writable by our group:
+ exit 0
+ ;;
+ *)
+ export SANDBOX_ON="1"
+ echo "Please specify a valid command."
+ echo
+ dyn_help
+ exit 1
+ ;;
+ esac
+
+ #if [ $? -ne 0 ]; then
+ # exit 1
+ #fi
+done
+
+if [ "$myarg" != "clean" ]; then
+ # Save current environment and touch a success file. (echo for success)
+ umask 002
+ set | egrep -v "^SANDBOX_" > "${T}/environment" 2>/dev/null
+ chown portage:portage "${T}/environment" &>/dev/null
+ chmod g+w "${T}/environment" &>/dev/null
+fi
+
+exit 0
diff --git a/bin/emake b/bin/emake
new file mode 100755
index 00000000..44fe8340
--- /dev/null
+++ b/bin/emake
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/emake,v 1.9.2.1 2005/05/18 15:19:52 jstubbs Exp $
+#
+# emake: Supplies some default parameters to GNU make. At the moment the
+# only parameter supplied is -jN, where N is a number of
+# parallel processes that should be ideal for the running host
+# (e.g. on a single-CPU machine, N=2). The MAKEOPTS variable
+# is set in /etc/make.globals. We don't source
+# /etc/make.globals here because emake is only called from an
+# ebuild.
+
+${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@"
diff --git a/bin/emerge b/bin/emerge
new file mode 100755
index 00000000..5ae17196
--- /dev/null
+++ b/bin/emerge
@@ -0,0 +1,3213 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/emerge,v 1.345.2.38 2005/08/13 17:25:26 ferringb Exp $
+
+import os,sys
+os.environ["PORTAGE_CALLER"]="emerge"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage
+
+import emergehelp,xpak,string,re,commands,time,shutil,traceback,atexit,signal,socket,types
+from stat import *
+from output import *
+
+import portage_util
+import portage_locks
+import portage_exception
+
+
+spinner_msgs = ["Gentoo Rocks ("+os.uname()[0]+")",
+ "Thank you for using Gentoo. :)",
+ "Are you actually trying to read this?",
+ "How many times have you stared at this?",
+ "We are generating the cache right now",
+ "You are paying too much attention.",
+ "A theory is better than its explanation.",
+ "Phasers locked on target, Captain.",
+ "Thrashing is just virtual crashing.",
+ "To be is to program.",
+ "Real Users hate Real Programmers.",
+ "When all else fails, read the instructions.",
+ "Functionality breeds Contempt.",
+ "The future lies ahead.",
+ "3.1415926535897932384626433832795028841971694",
+ "Sometimes insanity is the only alternative.",
+ "Inaccuracy saves a world of explanation.",
+ ]
+
+
+def update_basic_spinner():
+ global spinner, spinpos
+ spinpos = (spinpos+1) % 500
+ if (spinpos % 100) == 0:
+ if spinpos == 0:
+ sys.stdout.write(". ")
+ else:
+ sys.stdout.write(".")
+ sys.stdout.flush()
+
+def update_scroll_spinner():
+ global spinner, spinpos
+ if(spinpos >= len(spinner)):
+ sys.stdout.write(darkgreen(" \b\b\b"+spinner[len(spinner)-1-(spinpos%len(spinner))]))
+ else:
+ sys.stdout.write(green("\b "+spinner[spinpos]))
+ sys.stdout.flush()
+ spinpos = (spinpos+1) % (2*len(spinner))
+
+def update_twirl_spinner():
+ global spinner, spinpos
+ spinpos = (spinpos+1) % len(spinner)
+ sys.stdout.write("\b\b "+spinner[spinpos])
+ sys.stdout.flush()
+
+spinpos = 0
+spinner = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
+update_spinner = update_twirl_spinner
+if "candy" in portage.settings.features:
+ spinner = spinner_msgs[int(time.time()*100)%len(spinner_msgs)]
+ update_spinner = update_scroll_spinner
+if not sys.stdout.isatty() or ("--nospinner" in sys.argv):
+ update_spinner = update_basic_spinner
+
+
+if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]):
+ nocolor()
+
+def normpath(mystr):
+ if mystr and (mystr[0]=='/'):
+ return os.path.normpath("///"+mystr)
+ else:
+ return os.path.normpath(mystr)
+
+def userquery(prompt, responses=None, colours=None):
+ """Displays a prompt and a set of responses, then waits for a response
+ which is checked against the responses and the first to match is
+ returned.
+
+ prompt: a String.
+ responses: a List of Strings.
+ colours: a List of Functions taking and returning a String, used to
+ process the responses for display. Typically these will be functions
+ like red() but could be e.g. lambda x: "DisplayString".
+ If responses is omitted, defaults to ["Yes", "No"], [green, red].
+ If only colours is omitted, defaults to [bold, ...].
+
+ Returns a member of the List responses. (If called without optional
+ arguments, returns "Yes" or "No".)
+ KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
+ printed."""
+ if responses is None:
+ responses, colours = ["Yes", "No"], [green, red]
+ elif colours is None:
+ colours=[bold]
+ colours=(colours*len(responses))[:len(responses)]
+ print bold(prompt),
+ try:
+ while True:
+ response=raw_input("["+string.join([colours[i](responses[i]) for i in range(len(responses))],"/")+"] ")
+ for key in responses:
+ if response.upper()==key[:len(response)].upper():
+ return key
+ print "Sorry, response '%s' not understood." % response,
+ except (EOFError, KeyboardInterrupt):
+ print "Interrupted."
+ sys.exit(1)
+
+def sorted_versions(verlist):
+ ret = []
+ for ver in verlist:
+ verparts = ver.split("-")
+ if len(verparts) == 2:
+ verrev = int(verparts[1][1:])
+ else:
+ verrev = 0
+ x = 0
+ while x < len(ret):
+ retparts = ret[x].split("-")
+ verdiff = portage.vercmp(retparts[0], verparts[0])
+ if verdiff > 0:
+ break
+ elif verdiff == 0:
+ if len(retparts) == 2:
+ retrev = int(retparts[1][1:])
+ else:
+ retrev = 0
+ if retrev >= verrev:
+ break
+ x += 1
+ ret.insert(x, ver)
+ return ret
+
+if portage.settings.has_key("PORTAGE_NICENESS"):
+ try:
+ os.nice(int(portage.settings["PORTAGE_NICENESS"]))
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception,e:
+ print "!!! Failed to change nice value to '"+str(portage.settings["PORTAGE_NICENESS"])+"'"
+ print "!!!",e
+
+#Freeze the portdbapi for enhanced performance:
+portage.portdb.freeze()
+
+# Kill noauto as it will break merges otherwise.
+while 'noauto' in portage.features:
+ del portage.features[portage.features.index('noauto')]
+
+#number of ebuilds merged
+merged=0
+params=["selective", "deep", "self", "recurse", "empty"]
+actions=[
+"clean", "config", "depclean",
+"info", "inject", "metadata",
+"prune", "regen", "rsync", "search",
+"sync", "system", "unmerge", "world",
+]
+options=[
+"--ask",
+"--buildpkg", "--buildpkgonly",
+"--changelog", "--columns",
+"--debug", "--deep",
+"--digest",
+"--emptytree",
+"--fetchonly", "--fetch-all-uri",
+"--getbinpkg", "--getbinpkgonly",
+"--help", "--noconfmem",
+"--newuse", "--nocolor",
+"--nodeps", "--noreplace",
+"--nospinner", "--oneshot",
+"--onlydeps", "--pretend",
+"--quiet", "--resume",
+"--searchdesc", "--selective",
+"--skipfirst",
+"--tree",
+"--update", "--upgradeonly",
+"--usepkg", "--usepkgonly",
+"--verbose", "--version"
+]
+
+shortmapping={
+"1":"--oneshot",
+"a":"--ask",
+"b":"--buildpkg", "B":"--buildpkgonly",
+"c":"--clean", "C":"--unmerge",
+"d":"--debug", "D":"--deep",
+"e":"--emptytree",
+"f":"--fetchonly", "F":"--fetch-all-uri",
+"g":"--getbinpkg", "G":"--getbinpkgonly",
+"h":"--help",
+"i":"--inject",
+"k":"--usepkg", "K":"--usepkgonly",
+"l":"--changelog",
+"n":"--noreplace", "N":"--newuse",
+"o":"--onlydeps", "O":"--nodeps",
+"p":"--pretend", "P":"--prune",
+"q":"--quiet",
+"s":"--search", "S":"--searchdesc",
+'t':"--tree",
+"u":"--update", "U":"--upgradeonly",
+"v":"--verbose", "V":"--version"
+}
+
+myaction=None
+myopts=[]
+myfiles=[]
+edebug=0
+
+# process short actions
+tmpcmdline=sys.argv[1:]
+#tmpcmdline.extend(portage.settings["EMERGE_OPTS"].split())
+cmdline=[]
+for x in tmpcmdline:
+ if x[0:1]=="-"and x[1:2]!="-":
+ for y in x[1:]:
+ if shortmapping.has_key(y):
+ if shortmapping[y] in cmdline:
+ print
+ print "*** Warning: Redundant use of",shortmapping[y]
+ else:
+ cmdline.append(shortmapping[y])
+ else:
+ print "!!! Error: -"+y+" is an invalid short action or option."
+ sys.exit(1)
+ else:
+ cmdline.append(x)
+
+# process the options and command arguments
+for x in cmdline:
+ if not x:
+ continue
+ if len(x)>=2 and x[0:2]=="--":
+ if x in options:
+ myopts.append(x)
+ elif x[2:] in actions:
+ if x[2:]=="rsync" or x=="rsync":
+ # "emerge --rsync"
+ print
+ print red("*** '--rsync' has been deprecated.")
+ print red("*** Please use '--sync' instead.")
+ print
+ x="--sync"
+ if myaction:
+ if myaction not in ["system", "world"]:
+ myaction="--"+myaction
+ print
+ print red("!!!")+green(" Multiple actions requested... Please choose one only.")
+ print red("!!!")+" '"+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
+ print
+ sys.exit(1)
+ myaction=x[2:]
+ else:
+ print "!!! Error:",x,"is an invalid option."
+ sys.exit(1)
+ elif (not myaction) and (x in actions):
+ if x not in ["system", "world"]:
+ #print red("*** Deprecated use of action '"+x+"'")
+ if x=="rsync":
+ # "emerge rsync"
+ print
+ print red("*** 'rsync' will now install the package rsync.")
+ print red("*** To sync the tree, please use '--sync' instead.")
+ print
+ myfiles.append(x)
+ continue
+ if myaction:
+ print
+ print red("!!!")+green(" Multiple actions requested... Please choose one only.")
+ print red("!!! '")+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
+ print
+ sys.exit(1)
+ myaction=x
+ elif x[-1]=="/":
+ # this little conditional helps tab completion
+ myfiles.append(x[:-1])
+ else:
+ myfiles.append(x)
+
+
+if "moo" in myfiles:
+ print """
+
+ Gentoo (""" + os.uname()[0] + """)
+
+ _______________________
+< Have you mooed today? >
+ -----------------------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+
+"""
+
+if (myaction in ["world", "system"]) and myfiles:
+ print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
+ sys.exit(1)
+
+for x in myfiles:
+ if (x[-7:] == ".ebuild" or x[-5:] == ".tbz2") and os.path.exists(os.path.abspath(x)):
+ print "emerging by path implies --oneshot... adding --oneshot to options."
+ print red("\n*** emerging by path is broken and may not always work!!!\n")
+ break
+
+if ("--tree" in myopts) and ("--columns" in myopts):
+ print "emerge: can't specify both of \"--tree\" and \"--columns\"."
+ sys.exit(1)
+
+# Always create packages if FEATURES=buildpkg
+# Imply --buildpkg if --buildpkgonly
+if ("buildpkg" in portage.features) or ("--buildpkgonly" in myopts):
+ if "--buildpkg" not in myopts:
+ myopts.append("--buildpkg")
+
+# --tree only makes sense with --pretend
+if "--tree" in myopts and not (("--pretend" in myopts) or ("--ask" in myopts)):
+ print ">>> --tree implies --pretend... adding --pretend to options."
+ myopts.append("--pretend")
+
+# Also allow -S to invoke search action (-sS)
+if ("--searchdesc" in myopts):
+ if myaction and myaction != "search":
+ myfiles.append(myaction)
+ if "--search" not in myopts:
+ myopts.append("--search")
+ myaction = "search"
+
+# Always try and fetch binary packages if FEATURES=getbinpkg
+if ("getbinpkg" in portage.features):
+ myopts.append("--getbinpkg")
+
+if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
+ myopts.append("--usepkgonly")
+
+if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
+ myopts.append("--getbinpkg")
+
+if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
+ myopts.append("--usepkg")
+
+# Also allow -K to apply --usepkg/-k
+if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
+ myopts.append("--usepkg")
+
+# Print deprecation warning for -U
+if ("--upgradeonly" in myopts):
+ print
+ print red("*** Warning: --upgradeonly is a deprecated option in portage-"+portage.VERSION)
+ print red("*** and will likely be removed in a future version.")
+ print
+ # Also allow -U to apply --update/-u
+ if not ("--update" in myopts):
+ print ">>> --upgradeonly implies --update... adding --update to options."
+ myopts.append("--update")
+
+# Also allow -l to apply --pretend/-p, but if already in --ask mode
+if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
+ print ">>> --changelog implies --pretend... adding --pretend to options."
+ myopts.append("--pretend")
+
+# Allow -p to remove --ask
+if ("--pretend" in myopts) and ("--ask" in myopts):
+ print ">>> --pretend disables --ask... removing --ask from options."
+ myopts.remove("--ask")
+
+# forbid --ask when not in a terminal
+# note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
+if ("--ask" in myopts) and (not sys.stdin.isatty()):
+ portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n")
+ sys.exit(1)
+
+# Set so that configs will be merged regardless of remembered status
+if ("--noconfmem" in myopts):
+ portage.settings.unlock()
+ portage.settings["NOCONFMEM"]="1"
+ portage.settings.backup_changes("NOCONFMEM")
+ portage.settings.lock()
+
+# Set various debug markers... They should be merged somehow.
+if ("--debug" in myopts):
+ portage.settings.unlock()
+ portage.settings["PORTAGE_DEBUG"]="1"
+ portage.settings.backup_changes("PORTAGE_DEBUG")
+ portage.debug=1
+ portage.settings.lock()
+
+if ("--resume" in myopts):
+ if "--verbose" in myopts:
+ print "* --verbose is currently broken with --resume. Disabling..."
+ myopts.remove("--verbose")
+ if "--tree" in myopts:
+ print "* --tree is currently broken with --resume. Disabling..."
+ myopts.remove("--tree")
+
+# Set color output
+if ("--nocolor" in myopts) and (sys.stdout.isatty()):
+ nocolor()
+
+CLEAN_DELAY = 5
+EMERGE_WARNING_DELAY = 10
+if portage.settings["CLEAN_DELAY"]:
+ CLEAN_DELAY = string.atoi("0"+portage.settings["CLEAN_DELAY"])
+if portage.settings["EMERGE_WARNING_DELAY"]:
+ EMERGE_WARNING_DELAY = string.atoi("0"+portage.settings["EMERGE_WARNING_DELAY"])
+
+if "inject" == myaction:
+ print
+ print red("*** --inject has been deprecated.")
+ print red("*** If you manage a piece of software yourself, add it's name and")
+ print red("*** version (eg foo/bar-1.0) to /etc/portage/profile/package.provided.")
+ print red("*** If you want to prevent portage from upgrading a package, add it to")
+ print red("*** /etc/portage/package.mask prepending it with '>' (eg >foo/bar-1.0)")
+ print red("*** For more information on fine-grained portage control, please see")
+ print red("*** the portage man page.")
+ print
+
+def emergelog(mystr,short_msg=None):
+ if "notitles" not in portage.features:
+ if short_msg:
+ xtermTitle(short_msg)
+ else:
+ xtermTitle(mystr)
+ try:
+ #seems odd opening a file each write...
+ if not os.path.exists("/var/log/emerge.log"):
+ mylogfile=open("/var/log/emerge.log", "w")
+ os.chmod("/var/log/emerge.log", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+ os.chown("/var/log/emerge.log", portage.portage_uid, portage.portage_gid)
+ else:
+ mylogfile=open("/var/log/emerge.log", "a")
+
+ l=portage_locks.lockfile(mylogfile)
+ # seek because we may have gotten held up by the lock.
+ # if so, we may not be positioned at the end of the file.
+ mylogfile.seek(0,2)
+ mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
+ mylogfile.flush()
+ portage_locks.unlockfile(l)
+ mylogfile.close()
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ if edebug:
+ print "emergelog():",e
+ pass
+
+def emergeexit():
+ """This gets out final log message in before we quit."""
+ if "--pretend" not in myopts:
+ emergelog(" *** terminating.")
+ if "notitles" not in portage.features:
+ xtermTitleReset()
+atexit.register(emergeexit)
+
+def emergeexitsig(signum, frame):
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ portage.portageexit()
+ portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
+ sys.exit(100+signum)
+signal.signal(signal.SIGINT, emergeexitsig)
+
+def countdown(secs=5, doing="Starting"):
+ if secs:
+ print ">>> Waiting",secs,"seconds before starting..."
+ print ">>> (Control-C to abort)...\n"+doing+" in: ",
+ ticks=range(secs)
+ ticks.reverse()
+ for sec in ticks:
+ sys.stdout.write(red(str(sec+1)+" "))
+ sys.stdout.flush()
+ time.sleep(1)
+ print
+
+# formats a size given in bytes nicely
+def format_size(mysize):
+ if type(mysize) not in [types.IntType,types.LongType]:
+ return str(mysize)
+ mystr=str(mysize/1024)
+ mycount=len(mystr)
+ while (mycount > 3):
+ mycount-=3
+ mystr=mystr[:mycount]+","+mystr[mycount:]
+ return mystr+" kB"
+
+
+def getgccversion():
+ """
+ rtype: C{str}
+ return: the current in-use gcc version
+ """
+
+ gcc_env_dir = os.path.join('/', 'etc', 'env.d', 'gcc')
+ gcc_config_config = os.path.join(gcc_env_dir, 'config')
+ gcc_ver_command = 'gcc -dumpversion'
+ gcc_ver_prefix = 'gcc-'
+
+ gcc_not_found_error = red(
+ "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
+ "!!! to update the environment of this terminal and possibly\n" +
+ "!!! other terminals also."
+ )
+
+ gcc_distcc_broken_error = green(
+ '!!! Relying on the shell to locate gcc, this may break\n' +
+ '!!! DISTCC, installing gcc-config and setting your current gcc\n' +
+ '!!! profile will fix this'
+ )
+
+ def fallback():
+
+ print >>sys.stderr, gcc_distcc_broken_error
+
+ gccout = commands.getstatusoutput(gcc_ver_command)
+
+ if gccout[0] != 0:
+ print >>sys.stderr, gcc_not_found_error
+ gccver = "[unavailable]"
+ else:
+ gccver = gcc_ver_prefix + gccout[1]
+
+ return gccver
+
+ if os.path.isfile(gcc_config_config):
+ try:
+ gccver_str = open(gcc_config_config).read().strip()
+ gccver = gcc_ver_prefix + string.join(gccver_str.split('-')[4:], '-')
+ except IndexError:
+ gccver = fallback()
+
+ else:
+ import glob
+ dir_l = glob.glob(os.path.join(gcc_env_dir, '*-*'))
+
+ if len(dir_l) == 1:
+ try:
+ gccver = gcc_ver_prefix + dir_l[0].split('-')[-1]
+ except IndexError:
+ gccver = fallback()
+
+ else:
+ # There was no "config" file in /etc/env.d/gcc and there was more
+ # than one profile in /etc/env.d/gcc so we can't actively
+ # determine what version of gcc we are using so we fall back on the
+ # old way that breaks distcc
+
+ gccver = fallback()
+
+ return gccver
+
+def getportageversion():
+ try:
+ import re
+ profilever = os.path.normpath("///"+os.readlink("/etc/make.profile"))
+ basepath = os.path.normpath("///"+portage.settings["PORTDIR"]+"/profiles")
+ if re.match(basepath,profilever):
+ profilever = profilever[len(basepath)+1:]
+ else:
+ profilever = "!"+profilever
+ del basepath
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ profilever="unavailable"
+ libcver=[]
+ libclist = portage.vardbapi(portage.root).match("virtual/libc")
+ libclist += portage.vardbapi(portage.root).match("virtual/glibc")
+ libclist = portage_util.unique_array(libclist)
+ for x in libclist:
+ xs=portage.catpkgsplit(x)
+ if libcver:
+ libcver+=","+string.join(xs[1:], "-")
+ else:
+ libcver=string.join(xs[1:], "-")
+ if libcver==[]:
+ libcver="unavailable"
+
+ gccver = getgccversion()
+ unameout=os.uname()[2]+" "+os.uname()[4]
+
+ return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
+
+def help():
+ # Move all the help stuff out of this file.
+ emergehelp.help(myaction,myopts,havecolor)
+
+# check if root user is the current user for the actions where emerge needs this
+if ("--pretend" in myopts) or ("--fetchonly" in myopts or "--fetch-all-uri" in myopts) or (myaction=="search"):
+ if not portage.secpass:
+ if portage.wheelgid==portage.portage_gid:
+ print "emerge: wheel group membership required for \"--pretend\" and search."
+ print "emerge: wheel group use is being deprecated. Please update group and passwd to"
+ print " include the portage user as noted above, and then use group portage."
+ else:
+ print "emerge: portage group membership required for \"--pretend\" and search."
+ sys.exit(1)
+elif "--version" in myopts:
+ print getportageversion()
+ sys.exit(0)
+elif "--help" in myopts:
+ help()
+ sys.exit(0)
+elif portage.secpass!=2:
+ if myaction in ["search", "info", "regen"]:
+ pass
+ elif (not myaction) and (not myfiles):
+ pass
+ elif ("--pretend" in myopts) and (myaction in ["world","system","clean","prune","unmerge"]):
+ pass
+ else:
+ if "--debug" in myopts:
+ print "myaction",myaction
+ print "myopts",myopts
+ print "emerge: root access required."
+ sys.exit(1)
+
+if not "--pretend" in myopts:
+ emergelog("Started emerge on: "+time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
+ myelogstr=""
+ if myopts:
+ myelogstr=string.join(myopts, " ")
+ if myaction:
+ myelogstr+=" "+myaction
+ if myfiles:
+ myelogstr+=" "+string.join(myfiles, " ")
+ emergelog(" *** emerge "+myelogstr)
+
+#configure emerge engine parameters
+#
+# self: include _this_ package regardless of if it is merged.
+# selective: exclude the package if it is merged
+# recurse: go into the dependencies
+# empty: pretend nothing is merged
+myparams=["self","recurse"]
+add=[]
+sub=[]
+if "--update" in myopts:
+ add.extend(["selective","empty"])
+if "--emptytree" in myopts:
+ add.extend(["empty"])
+ sub.extend(["selective"])
+if "--nodeps" in myopts:
+ sub.extend(["recurse"])
+if "--noreplace" in myopts:
+ add.extend(["selective"])
+if "--deep" in myopts:
+ add.extend(["deep"])
+if "--selective" in myopts:
+ add.extend(["selective"])
+if myaction in ["world","system"]:
+ add.extend(["selective"])
+elif myaction in ["depclean"]:
+ add.extend(["empty"])
+ sub.extend(["selective"])
+for x in add:
+ if (x not in myparams) and (x not in sub):
+ myparams.append(x)
+for x in sub:
+ if x in myparams:
+ myparams.remove(x)
+
+# search functionality
+class search:
+
+ #
+ # class constants
+ #
+ VERSION_SHORT=1
+ VERSION_RELEASE=2
+
+ #
+ # public interface
+ #
+ def __init__(self):
+ """Searches the available and installed packages for the supplied search key.
+ The list of available and installed packages is created at object instantiation.
+ This makes successive searches faster."""
+ self.installcache = portage.db["/"]["vartree"]
+
+ def execute(self,searchkey):
+ """Performs the search for the supplied search key"""
+ global myopts
+ match_category = 0
+ self.searchkey=searchkey
+ self.packagematches = []
+ if "--searchdesc" in myopts:
+ self.searchdesc=1
+ self.matches = {"pkg":[], "desc":[]}
+ else:
+ self.searchdesc=0
+ self.matches = {"pkg":[]}
+ print "Searching... ",
+
+ if self.searchkey[0] == '@':
+ match_category = 1
+ self.searchkey = self.searchkey[1:]
+ if self.searchkey=="*":
+ #hack for people who aren't regular expression gurus
+ self.searchkey==".*"
+ if re.search("\+\+", self.searchkey):
+ #hack for people who aren't regular expression gurus
+ self.searchkey=re.sub("\+\+","\+\+",self.searchkey)
+ self.searchre=re.compile(self.searchkey.lower(),re.I)
+ for package in portage.portdb.cp_all():
+ update_spinner()
+
+ if match_category:
+ match_string = package[:]
+ else:
+ match_string = package.split("/")[-1]
+
+ masked=0
+ if self.searchre.search(match_string):
+ if not portage.portdb.xmatch("match-visible",package):
+ masked=1
+ self.matches["pkg"].append([package,masked])
+ elif self.searchdesc: # DESCRIPTION searching
+ full_package = portage.portdb.xmatch("bestmatch-visible",package)
+ if not full_package:
+ #no match found; we don't want to query description
+ full_package=portage.best(portage.portdb.xmatch("match-all",package))
+ if not full_package:
+ continue
+ else:
+ masked=1
+ try:
+ full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0]
+ except KeyError:
+ print "emerge: search: aux_get() failed, skipping"
+ continue
+ if self.searchre.search(full_desc):
+ self.matches["desc"].append([full_package,masked])
+ self.mlen=0
+ for mtype in self.matches.keys():
+ self.matches[mtype].sort()
+ self.mlen += len(self.matches[mtype])
+
+ def output(self):
+ """Outputs the results of the search."""
+ print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
+ print "[ Applications found : "+white(str(self.mlen))+" ]"
+ print " "
+ for mtype in self.matches.keys():
+ for match,masked in self.matches[mtype]:
+ if mtype=="pkg":
+ catpack=match
+ full_package = portage.portdb.xmatch("bestmatch-visible",match)
+ if not full_package:
+ #no match found; we don't want to query description
+ masked=1
+ full_package=portage.best(portage.portdb.xmatch("match-all",match))
+ else:
+ full_package = match
+ match = portage.pkgsplit(match)[0]
+
+ if full_package:
+ try:
+ desc, homepage, license = portage.portdb.aux_get(full_package,["DESCRIPTION","HOMEPAGE","LICENSE"])
+ except KeyError:
+ print "emerge: search: aux_get() failed, skipping"
+ continue
+ if masked:
+ print green("*")+" "+white(match)+" "+red("[ Masked ]")
+ else:
+ print green("*")+" "+white(match)
+ myversion = self.getVersion(full_package, search.VERSION_RELEASE)
+
+ mysum = [0,0]
+ mycat = match.split("/")[0]
+ mypkg = match.split("/")[1]
+
+ mydigest = portage.db["/"]["porttree"].dbapi.finddigest(mycat+"/"+mypkg + "-" + myversion)
+
+ try:
+ myfile = open(mydigest,"r")
+ for line in myfile.readlines():
+ mysum[0] += int(line.split(" ")[3])
+ myfile.close()
+ mystr = str(mysum[0]/1024)
+ mycount=len(mystr)
+ while (mycount > 3):
+ mycount-=3
+ mystr=mystr[:mycount]+","+mystr[mycount:]
+ mysum[0]=mystr+" kB"
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ if edebug:
+ print "!!! Exception:",e
+ mysum[0]=" [no/bad digest]"
+
+ if "--quiet" not in myopts:
+ print " ", darkgreen("Latest version available:"),myversion
+ print " ", self.getInstallationStatus(mycat+'/'+mypkg)
+ print " ", darkgreen("Size of downloaded files:"),mysum[0]
+ print " ", darkgreen("Homepage:")+" ",homepage
+ print " ", darkgreen("Description:"),desc
+ print " ", darkgreen("License:")+" ",license
+ print
+ print
+ #
+ # private interface
+ #
+ def getInstallationStatus(self,package):
+ installed_package = self.installcache.dep_bestmatch(package)
+ result = ""
+ version = self.getVersion(installed_package,search.VERSION_RELEASE)
+ if len(version) > 0:
+ result = darkgreen("Latest version installed:")+" "+version
+ else:
+ result = darkgreen("Latest version installed:")+" [ Not Installed ]"
+ return result
+
+ def getVersion(self,full_package,detail):
+ if len(full_package) > 1:
+ package_parts = portage.catpkgsplit(full_package)
+ if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
+ result = package_parts[2]+ "-" + package_parts[3]
+ else:
+ result = package_parts[2]
+ else:
+ result = ""
+ return result
+
+
+#build our package digraph
+def getlist(mode):
+ if mode=="system":
+ mylines=portage.settings.packages
+ elif mode=="world":
+ try:
+ myfile=open(portage.root+portage.WORLD_FILE,"r")
+ mylines=myfile.readlines()
+ myfile.close()
+ except OSError:
+ print "!!! Couldn't open "+pfile+"; exiting."
+ sys.exit(1)
+ except IOError:
+ #world file doesn't exist
+ mylines=[]
+ mynewlines=[]
+ for x in mylines:
+ myline=string.join(string.split(x))
+ if not len(myline):
+ continue
+ elif myline[0]=="#":
+ continue
+ elif mode=="system":
+ if myline[0]!="*":
+ continue
+ myline=myline[1:]
+ mynewlines.append(myline.strip())
+ return mynewlines
+
+def genericdict(mylist):
+ mynewdict={}
+ for x in mylist:
+ mynewdict[portage.dep_getkey(x)]=x
+ return mynewdict
+
+olddbapi=None
+class depgraph:
+
+ def __init__(self,myaction,myopts):
+ global olddbapi
+ self.pkgsettings = portage.config(clone=portage.settings)
+ if not self.pkgsettings["ARCH"]:
+ portage.writemsg(red("\a!!! ARCH is not set... Are you missing the /etc/make.profile symlink?\n"))
+ portage.writemsg(red("\a!!! Is the symlink correct? Is your portage tree complete?\n\n"))
+ sys.exit(9)
+ self.applied_useflags = {}
+
+ self.missingbins=[]
+ self.myaction=myaction
+ self.digraph=portage.digraph()
+ self.orderedkeys=[]
+ self.outdatedpackages=[]
+ self.mydbapi={}
+ self.mydbapi["/"] = portage.fakedbapi()
+ if "empty" not in myparams:
+ for pkg in portage.db["/"]["vartree"].getallcpv():
+ self.mydbapi["/"].cpv_inject(pkg)
+ if portage.root != "/":
+ self.mydbapi[portage.root] = portage.fakedbapi()
+ if "empty" not in myparams:
+ for pkg in portage.db[portage.root]["vartree"].getallcpv():
+ self.mydbapi[portage.root].cpv_inject(pkg)
+
+ if "--usepkg" in myopts:
+ portage.db["/"]["bintree"].populate(("--getbinpkg" in myopts), ("--getbinpkgonly" in myopts))
+
+ def create(self,mybigkey,myparent=None,addme=1,myuse=None):
+ """creates the actual digraph of packages to merge. return 1 on success, 0 on failure
+ mybigkey = specification of package to merge; myparent = parent package (one depending on me);
+ addme = should I be added to the tree? (for the --onlydeps mode)"""
+ #stuff to add:
+ #SLOT-aware emerge
+ #IUSE-aware emerge
+ #"no downgrade" emerge
+ #print "mybigkey:",mybigkey
+
+ jbigkey=string.join(mybigkey)
+ if self.digraph.hasnode(jbigkey+" merge") or self.digraph.hasnode(jbigkey+" nomerge"):
+ #this conditional is needed to prevent infinite recursion on already-processed deps
+ return 1
+
+ update_spinner()
+
+ mytype,myroot,mykey=mybigkey
+ # select the correct /var database that we'll be checking against
+ vardbapi=portage.db[myroot]["vartree"].dbapi
+
+ if addme:
+ # if the package is already on the system, we add a "nomerge"
+ # directive, otherwise we add a "merge" directive.
+ if mytype=="blocks":
+ # we've encountered a "blocks" node. We will totally ignore this
+ # node and not add it to our digraph if it doesn't apply to us.
+ if "--buildpkgonly" not in myopts and myparent and (self.mydbapi[myroot].match(mykey) or vardbapi.match(mykey)):
+ mybigkey.append(myparent.split()[2])
+ self.digraph.addnode(string.join(mybigkey),myparent)
+ return 1
+
+ if myuse == None:
+ self.pkgsettings.setcpv(mykey)
+ myuse=string.split(self.pkgsettings["USE"], " ")
+
+ self.applied_useflags[mykey] = myuse
+
+ merging=1
+ if addme:
+ # this is where we add the node to the list of packages to merge
+ if not myparent:
+ # command-line specified or part of a world list...
+ if ("self" not in myparams) or (("selective" in myparams) and vardbapi.cpv_exists(mykey)):
+ # the package is on the system, so don't merge it.
+ merging=0
+ elif ("selective" in myparams) and vardbapi.cpv_exists(mykey):
+ merging=0
+
+ if (merging==0 and mytype=="ebuild" and "--newuse" in myopts and vardbapi.cpv_exists(mykey)):
+ iuses=string.split(portage.portdb.aux_get(mykey, ["IUSE"])[0])
+ old_use=string.split(vardbapi.aux_get(mykey, ["USE"])[0])
+ now_use=string.split(self.pkgsettings["USE"])
+ for x in iuses:
+ if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)):
+ merging=1
+ break
+ else:
+ #onlydeps mode; don't merge
+ merging=2
+ if merging==1:
+ mybigkey.append("merge")
+ else:
+ mybigkey.append("nomerge")
+
+ # whatever the case, we need to add the node to our digraph so
+ # that children can depend upon it.
+ self.digraph.addnode(string.join(mybigkey),myparent)
+ if ("deep" not in myparams) and (not merging):
+ return 1
+ elif "recurse" not in myparams:
+ return 1
+
+ edepend={}
+ if mytype=="binary":
+ mypkgparts=portage.catpkgsplit(mykey)
+ tbz2name = string.split(mykey, "/")[1]+".tbz2"
+ if tbz2name in portage.db[portage.root]["bintree"].invalids:
+ sys.stderr.write("\nINVALID PACKAGE (is required to continue): "+str(mykey)+"\n")
+ sys.exit(1)
+ if portage.db[portage.root]["bintree"].isremote(mykey):
+ edepend = portage.db[portage.root]["bintree"].remotepkgs[tbz2name]
+ edepend["DEPEND"] =""
+ edepend["RDEPEND"]=string.join(string.split(edepend["RDEPEND"])," ")
+ edepend["PDEPEND"]=string.join(string.split(edepend["PDEPEND"])," ")
+ edepend["CDEPEND"]=string.join(string.split(edepend["CDEPEND"])," ")
+ edepend["SLOT"] =string.strip(edepend["SLOT"])
+ #portage.db[portage.root]["bintree"].gettbz2(mykey)
+ else: # It's local.
+ mytbz2=xpak.tbz2(portage.db[portage.root]["bintree"].getname(mykey))
+ edepend["DEPEND"] =""
+ edepend["RDEPEND"]=string.join(mytbz2.getelements("RDEPEND")," ")
+ edepend["PDEPEND"]=string.join(mytbz2.getelements("PDEPEND")," ")
+ edepend["CDEPEND"]=string.join(mytbz2.getelements("CDEPEND")," ")
+ edepend["SLOT"] =mytbz2.getfile("SLOT",mypkgparts[2])
+ elif mytype=="ebuild":
+ try:
+ mymeta = ["DEPEND","RDEPEND","PDEPEND","CDEPEND"]
+ myfoo = portage.portdb.aux_get(mykey, mymeta)
+ for index in range(0,len(mymeta)):
+ edepend[mymeta[index]] = myfoo[index]
+ except (KeyError,IOError):
+ print "emerge: create(): aux_get() error on",mykey+"; aborting..."
+ sys.exit(1)
+ mydep={}
+ mp=string.join(mybigkey)
+
+ if myroot=="/":
+ mydep["/"]=edepend["DEPEND"]+" "+edepend["RDEPEND"]
+ if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse):
+ return 0
+ else:
+ mydep["/"]=edepend["DEPEND"]
+ mydep[myroot]=edepend["RDEPEND"]
+ if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse):
+ return 0
+ if not self.select_dep(myroot,mydep[myroot],myparent=mp,myuse=myuse):
+ return 0
+
+ if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
+ # Post Depend -- Add to the list without a parent, as it depends
+ # on a package being present AND must be built after that package.
+ if not self.select_dep(myroot,edepend["PDEPEND"],myuse=myuse):
+ return 0
+
+ return 1
+
+ def select_files(self,myfiles):
+ "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
+ myfavorites=[]
+ for x in myfiles:
+ if x[-5:]==".tbz2":
+ if not os.path.exists(x):
+ if os.path.exists(self.pkgsettings["PKGDIR"]+"/All/"+x):
+ x=self.pkgsettings["PKGDIR"]+"/All/"+x
+ elif os.path.exists(self.pkgsettings["PKGDIR"]+"/"+x):
+ x=self.pkgsettings["PKGDIR"]+"/"+x
+ else:
+ print "\n\n!!! Binary package '"+str(x)+"' does not exist."
+ print "!!! Please ensure the tbz2 exists as specified.\n"
+ sys.exit(1)
+ mytbz2=xpak.tbz2(x)
+ mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(x)[:-5]
+ if os.path.realpath(portage.db["/"]["bintree"].getname(mykey)) != os.path.realpath(x):
+ print red("\n*** You need to adjust PKGDIR to emerge this package.\n")
+ sys.exit(1)
+ if not self.create(["binary",portage.root,mykey],None,"--onlydeps" not in myopts):
+ return (0,myfavorites)
+ elif not "--oneshot" in myopts:
+ myfavorites.append(mykey)
+ elif x[-7:]==".ebuild":
+ x = os.path.realpath(x)
+ mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.basename(x)[:-7]
+ ebuild_path = portage.db["/"]["porttree"].dbapi.findname(mykey)
+ if ebuild_path:
+ if os.path.realpath(ebuild_path) != x:
+ print red("\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
+ sys.exit(1)
+ if mykey not in portage.db["/"]["porttree"].dbapi.xmatch("match-visible", portage.dep_getkey(mykey)):
+ print red("\n*** You are emerging a masked package. It is MUCH better to use")
+ print red("*** /etc/portage/package.* to accomplish this. See portage(5) man")
+ print red("*** page for details.")
+ countdown(EMERGE_WARNING_DELAY, "Continuing...")
+ else:
+ print red("\n*** "+x+" does not exist")
+ sys.exit(1)
+ if not self.create(["ebuild",portage.root,mykey],None,"--onlydeps" not in myopts):
+ return (0,myfavorites)
+ elif not "--oneshot" in myopts:
+ myfavorites.append(mykey)
+ else:
+ try:
+ mykey=portage.dep_expand(x,mydb=portage.portdb)
+ except ValueError, errpkgs:
+ print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
+ print "!!! one of the following fully-qualified ebuild names instead:\n"
+ for i in errpkgs[0]:
+ print " " + green(i)
+ print
+ sys.exit(1)
+
+ # select needs to return 0 on dep_check failure
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+
+ try:
+ self.mysd = self.select_dep(portage.root,mykey,arg=x)
+ except portage_exception.MissingSignature, e:
+ portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
+ portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+ portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+ portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n")
+ portage.writemsg("!!! Affected file: %s\n" % (e))
+ sys.exit(1)
+ except portage_exception.InvalidSignature, e:
+ portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
+ portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+ portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+ portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n")
+ portage.writemsg("!!! Affected file: %s\n" % (e))
+ sys.exit(1)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ if "--debug" in myopts:
+ raise
+ print "\n\n!!! Problem in",mykey,"dependencies."
+ print "!!!",str(e),e.__module__
+ sys.exit(1)
+
+ if not self.mysd:
+ return (0,myfavorites)
+ elif not "--oneshot" in myopts:
+ myfavorites.append(mykey)
+
+ missing=0
+ if "--usepkgonly" in myopts:
+ for x in self.digraph.dict.keys():
+ xs=string.split(x," ")
+ if (xs[0] != "binary") and (xs[3]=="merge"):
+ if missing == 0:
+ print
+ missing += 1
+ print "Missing binary for:",xs[2]
+
+ # We're true here unless we are missing binaries.
+ return (not missing,myfavorites)
+
+ def is_newer_ver_installed(self,myroot,pkg,pkgver):
+ "if there is a version of pkg installed newer than pkgver, return it"
+ vardbapi=portage.db[myroot]["vartree"].dbapi
+
+ matches=portage.db[myroot]["vartree"].dbapi.match(pkg)
+ if matches:
+ myslot=portage.db["/"]["porttree"].getslot(pkgver)
+ for match in matches:
+ if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(match)[1:]) < 0:
+ curslot=portage.db[myroot]["vartree"].getslot(match)
+ if curslot == myslot:
+ return match
+
+ def select_dep(self,myroot,depstring,myparent=None,arg=None,myuse=None):
+ "given a dependency string, create the appropriate depgraph and return 1 on success and 0 on failure"
+ if "--debug" in myopts:
+ print
+ print "Parent: ",myparent
+ print "Depstring:",depstring
+ if not arg:
+ #processing dependencies
+ mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse,use_binaries=("--usepkg" in myopts))
+ #mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse)
+
+ if not mycheck[0]:
+ mymerge=[]
+ else:
+ mymerge=mycheck[1]
+
+ else:
+ #we're processing a command-line argument; unconditionally merge it even if it's already merged
+ mymerge=[depstring]
+
+ # dep_check has been run so we can now add our parent to our
+ # build state to update virtuals and other settings. This
+ # happens after the package is added to the tree so that a
+ # package can depend on a virtual which it satisfies.
+ if myparent:
+ myp = myparent.split()
+ if myp[3]=="merge":
+ self.mydbapi[myroot].cpv_inject(myp[2])
+ if myp[0]=="binary":
+ self.pkgsettings.setinst(myp[2],portage.db["/"]["bintree"].dbapi)
+ else:
+ self.pkgsettings.setinst(myp[2],portage.db[myroot]["porttree"].dbapi)
+
+ if not mymerge:
+ return 1
+
+ if "--debug" in myopts:
+ print "Candidates:",mymerge
+ for x in mymerge:
+ myk=None
+ binpkguseflags=None
+ if x[0]=="!":
+ # if this package is myself, don't append it to block list.
+ if "--debug" in myopts:
+ print "Myparent",myparent
+ if (myparent):
+ if myparent.split()[2] in portage.portdb.xmatch("match-all", x[1:]):
+ # myself, so exit.
+ continue
+ # adding block
+ myk=["blocks",myroot,x[1:]]
+ else:
+ #We are not processing a blocker but a normal dependency
+ myeb=None
+ myeb_matches = portage.portdb.xmatch("match-visible",x)
+ if ("--usepkgonly" not in myopts):
+ myeb=portage.best(myeb_matches)
+
+ myeb_pkg=None
+ if ("--usepkg" in myopts):
+ # The next line assumes the binarytree has been populated.
+ # XXX: Need to work out how we use the binary tree with roots.
+ myeb_pkg_matches=portage.db["/"]["bintree"].dbapi.match(x)
+ if ("--usepkgonly" not in myopts):
+ # Remove any binary package entries that are masked in the portage tree (#55871)
+ for idx in range(len(myeb_pkg_matches)-1,-1,-1):
+ if myeb_pkg_matches[idx] not in myeb_matches:
+ del myeb_pkg_matches[idx]
+ myeb_pkg = portage.best(myeb_pkg_matches)
+
+ if not myeb_pkg:
+ myeb_pkg = None
+ elif ("--newuse" in myopts):
+ iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["IUSE"])[0])
+ old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["USE"])[0])
+ self.pkgsettings.setcpv(myeb_pkg)
+ now_use=string.split(self.pkgsettings["USE"])
+ self.pkgsettings.reset()
+ for x in iuses:
+ if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)):
+ myeb_pkg = None
+ break
+
+ if (not myeb) and (not myeb_pkg):
+ if not arg:
+ xinfo='"'+x+'"'
+ else:
+ xinfo='"'+arg+'"'
+ if myparent:
+ xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"])")
+ alleb=portage.portdb.xmatch("match-all",x)
+ if alleb:
+ if "--usepkgonly" not in myopts:
+ print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
+ print "!!! One of the following masked packages is required to complete your request:"
+ oldcomment = ""
+ for p in alleb:
+ mreasons = portage.getmaskingstatus(p)
+ print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")"
+ comment = portage.getmaskingreason(p)
+ if comment and comment != oldcomment:
+ print comment
+ oldcomment = comment
+ print
+ print "For more information, see MASKED PACKAGES section in the emerge man page or "
+ print "section 2.2 \"Software Availability\" in the Gentoo Handbook."
+ if myparent:
+ print "!!! "+red(xfrom)
+ print
+ else:
+ print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
+ print "!!! Either add a suitable binary package or compile from an ebuild."
+ else:
+ print "\nemerge: there are no ebuilds to satisfy "+xinfo+"."
+ print
+ return 0
+
+ if "--debug" in myopts:
+ print "ebuild:",myeb
+ print "binpkg:",myeb_pkg
+
+ if myeb and myeb_pkg:
+ myeb_s = portage.catpkgsplit(myeb)
+ myeb_s = [myeb_s[0]+"/"+myeb_s[1], myeb_s[2], myeb_s[3]]
+ myeb_pkg_s = portage.catpkgsplit(myeb_pkg)
+ myeb_pkg_s = [myeb_pkg_s[0]+"/"+myeb_pkg_s[1], myeb_pkg_s[2], myeb_pkg_s[3]]
+
+ if portage.pkgcmp(myeb_s, myeb_pkg_s) == 0: # pkg is same version as ebuild
+ myeb = None
+ else:
+ myeb_pkg = None
+
+ if "--upgradeonly" in myopts:
+ # Check that there isn't a newer version of this package already installed
+ cand = None
+ try:
+ # XXX: This can throw an exception if the ebuild doesn't exist
+ if myeb:
+ cand=self.is_newer_ver_installed(myroot,x,myeb)
+ elif myeb_pkg:
+ cand=self.is_newer_ver_installed(myroot,x,myeb_pkg)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "Warning: "+str(e)
+ if cand:
+ myeb=cand
+
+ if myeb:
+ myk=["ebuild",myroot,myeb]
+ elif myeb_pkg:
+ binpkguseflags=portage.db[portage.root]["bintree"].get_use(myeb_pkg)
+ myk=["binary",myroot,myeb_pkg]
+ else:
+ sys.stderr.write("!!! Confused... Don't know what I'm using for dependency info. :(\n")
+ sys.exit(1)
+
+ #if "--usepkg" in myopts:
+ # #If we want to use packages, see if we have a pre-built one...
+ # mypk=portage.db["/"]["bintree"].dbapi.match(x)
+ # if myeb in mypk:
+ # #Use it only if it's exactly the version we want.
+ # myk=["binary",myroot,myeb]
+ # else:
+ # myk=["ebuild",myroot,myeb]
+ #else:
+ # myk=["ebuild",myroot,myeb]
+ if myparent:
+ #we are a dependency, so we want to be unconditionally added
+ if not self.create(myk,myparent,myuse=binpkguseflags):
+ return 0
+ else:
+ #if mysource is not set, then we are a command-line dependency and should not be added
+ #if --onlydeps is specified.
+ if not self.create(myk,myparent,"--onlydeps" not in myopts,myuse=binpkguseflags):
+ return 0
+
+ if "--debug" in myopts:
+ print "Exiting...",myparent
+ return 1
+
+
+ def altlist(self):
+ mygraph=self.digraph.copy()
+ dolist=["/"]
+ retlist=[]
+ for x in portage.db.keys():
+ portage.db[x]["merge"]=[]
+ if x not in dolist:
+ dolist.append(x)
+ while (not mygraph.empty()):
+ mycurkey=mygraph.firstzero()
+ if not mycurkey:
+ print "!!! Error: circular dependencies:"
+ print
+ for x in mygraph.dict.keys():
+ for y in mygraph.dict[x][1]:
+ print y,"depends on",x
+ print
+ sys.exit(1)
+ splitski=string.split(mycurkey)
+ #I'm not sure of the significance of the following lines (vestigal?) so I'm commenting 'em out.
+ #These lines remove already-merged things from our alt-list
+ #if "--update" in myopts:
+ # if not portage.db["/"]["vartree"].exists_specific(splitski[2]):
+ # portage.db["/"]["merge"].append(splitski)
+ #else:
+ portage.db[splitski[1]]["merge"].append(splitski)
+ mygraph.delnode(mycurkey)
+ for x in dolist:
+ for y in portage.db[x]["merge"]:
+ retlist.append(y)
+ return retlist
+
+ def xcreate(self,mode="system"):
+ global syslist
+ if mode=="system":
+ mylist=syslist
+ else:
+ #world mode
+ worldlist=getlist("world")
+ sysdict=genericdict(syslist)
+ worlddict=genericdict(worldlist)
+ #we're effectively upgrading sysdict to contain all new deps from worlddict
+ for x in worlddict.keys():
+ #only add the world node if the package is:
+ #actually installed -- this prevents the remerging of already unmerged packages when we do a world --update;
+ #actually available -- this prevents emerge from bombing out due to no match being found (we want a silent ignore)
+ if "empty" in myparams:
+ if portage.db["/"]["vartree"].dbapi.match(x):
+ sysdict[x]=worlddict[x]
+ elif portage.db[portage.root]["vartree"].dbapi.match(x):
+ #package is installed
+ sysdict[x]=worlddict[x]
+ else:
+ print "\n*** Package in world file is not installed: "+x
+ mylist = sysdict.keys()
+
+ for mydep in mylist:
+ myeb=portage.portdb.xmatch("bestmatch-visible",mydep)
+ if not myeb:
+ #this is an unavailable world entry; just continue
+ continue
+
+ if "--upgradeonly" in myopts:
+ cand=self.is_newer_ver_installed(portage.root,mydep,myeb)
+ if cand:
+ myeb=cand
+
+ #THIS NEXT BUNCH OF CODE NEEDS TO BE REPLACED TO SUPPORT WORLD ANTI-DEPS
+ #if mydep2[0]=="!":, etc.
+ binpkguseflags = None
+ if "--usepkg" in myopts:
+ mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep)
+ if myeb==mypk:
+ myk=["binary",portage.root,mypk]
+ binpkguseflags=portage.db[portage.root]["bintree"].get_use(mypk)
+ if ("--newuse" in myopts):
+ iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["IUSE"])[0])
+ old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["USE"])[0])
+ self.pkgsettings.setcpv(mypk)
+ now_use=string.split(self.pkgsettings["USE"])
+ self.pkgsettings.reset()
+ for x in iuses:
+ if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)):
+ myk=["ebuild",portage.root,myeb]
+ binpkguseflags=None
+ break
+ elif "--usepkgonly" in myopts:
+ if not mypk:
+ self.missingbins += [myeb]
+ myk=["binary",portage.root,myeb]
+ else:
+ myk=["binary",portage.root,mypk]
+ else:
+ myk=["ebuild",portage.root,myeb]
+ else:
+ myk=["ebuild",portage.root,myeb]
+
+ if not self.create(myk,myuse=binpkguseflags):
+ print
+ print "!!! Problem with",myk[0],myk[2]
+ print "!!! Possibly a DEPEND/*DEPEND problem."
+ print
+ return 0
+ return 1
+
+ def match(self,mydep,myroot=portage.root,mykey=None):
+ # support mutual exclusive deps
+ mydep2=mydep
+ if mydep2[0]=="!":
+ mydep2=mydep[1:]
+
+ if mydep[0]=="!":
+ #add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example)
+ myk="blocks "+myroot+" "+mydep2
+ else:
+ myeb=portage.db[portage.root]["porttree"].dep_bestmatch(mydep2)
+ if not myeb:
+ if not mykey:
+ print "\n!!! Error: couldn't find match for",mydep
+ else:
+ print "\n!!! Error: couldn't find match for",mydep,"in",mykey
+ print
+ sys.exit(1)
+
+ if "--usepkg" in myopts:
+ mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep)
+ if myeb==mypk:
+ myk="binary "+portage.root+" "+mypk
+ else:
+ myk="ebuild "+myroot+" "+myeb
+ else:
+ myk="ebuild "+myroot+" "+myeb
+
+ return myk
+
+ def display(self,mylist):
+ changelogs=[]
+ p=[]
+ totalsize=0
+
+ if "--verbose" in myopts:
+ overlays = string.split(portage.settings['PORTDIR_OVERLAY'])
+
+ if "--tree" in myopts:
+ mylist.reverse()
+ mygraph=self.digraph.copy()
+
+ i = 0
+ while i < len(mylist):
+ if mylist[i][-1]=="nomerge":
+ if not ("--tree" in myopts):
+ # we don't care about this elements
+ mylist.pop(i)
+ continue
+ if (i == (len(mylist) - 1)) \
+ or (mygraph.depth(string.join(mylist[i])) \
+ >= mygraph.depth(string.join(mylist[i+1]))):
+ # end of a useless branch (may be the last one)
+ # -> delete the element and test the previous one
+ mylist.pop(i)
+ if i > 0:
+ i -= 1
+ continue
+ # the branch continues, or we've found a good element.
+ # -> let's see what's next, if anything
+ i += 1
+
+ display_overlays=False
+ # files to fetch list - avoids counting a same file twice
+ # in size display (verbose mode)
+ myfetchlist=[]
+ for x in mylist:
+ fetch=" "
+
+ if x[0]=="blocks":
+ addl=""+red("B")+" "+fetch+" "
+ resolved=portage.db[x[1]]["vartree"].resolve_key(x[2])
+ print "["+x[0]+" "+addl+"]",red(resolved),
+ if resolved!=x[2]:
+ if x[3]:
+ print red("(\""+x[2]+"\" is blocking "+x[3]+")")
+ else:
+ print red("(\""+x[2]+"\")")
+ else:
+ if x[3]:
+ print red("(is blocking "+x[3]+")")
+ else:
+ print
+ else:
+ if (x[0]!="binary") and ("fetch" in string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])):
+ fetch = red("F")
+ if portage.portdb.fetch_check(x[2], portage.settings):
+ fetch = green("f")
+
+ #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
+ #param is used for -u, where you still *do* want to see when something is being upgraded.
+ myoldbest=""
+ if (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific(x[2]):
+ addl=" "+yellow("R")+fetch+" "
+ elif (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific_cat(x[2]):
+ if x[0] == "binary":
+ mynewslot=portage.db["/"]["bintree"].getslot(x[2])
+ elif x[0] == "ebuild":
+ mynewslot=portage.db["/"]["porttree"].getslot(x[2])
+ myoldlist=portage.db[x[1]]["vartree"].dbapi.match(portage.pkgsplit(x[2])[0])
+ myinslotlist=filter((lambda p: portage.db[portage.root]["vartree"].getslot(p)==mynewslot),myoldlist)
+ if myinslotlist:
+ myoldbest=portage.best(myinslotlist)
+ addl=" "+fetch
+ if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
+ # Downgrade in slot
+ addl+=turquoise("U")+blue("D")
+ else:
+ # Update in slot
+ addl+=turquoise("U")+" "
+ else:
+ # New slot, mark it new.
+ addl=" "+green("NS")+fetch+" "
+
+ if "--changelog" in myopts:
+ changelogs.extend(self.calc_changelog(
+ portage.portdb.findname(x[2]),
+ portage.db["/"]["vartree"].dep_bestmatch('/'.join(portage.catpkgsplit(x[2])[:2])),
+ x[2]
+ ))
+ else:
+ addl=" "+green("N")+" "+fetch+" "
+
+ verboseadd=""
+ if "--verbose" in myopts:
+ # iuse verbose
+ try:
+ if x[0] == "binary":
+ iuse_split = string.split(portage.db["/"]["bintree"].dbapi.aux_get(x[2],["IUSE"])[0])
+ elif x[0] == "ebuild":
+ iuse_split = string.split(portage.portdb.aux_get(x[2],["IUSE"])[0])
+ else:
+ iuse_split = []
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ portage.writemsg("!!! Error getting IUSE (report this to bugs.gentoo.org)\n")
+ portage.writemsg("!!! %s\n" % x)
+ iuse_split = []
+ iuse_split.sort()
+ old_use=None
+ if myoldbest:
+ pkg=myoldbest
+ else:
+ pkg=x[2]
+ if portage.db["/"]["vartree"].dbapi.cpv_exists(pkg):
+ try:
+ old_use=string.split(portage.db["/"]["vartree"].dbapi.aux_get(pkg, ["USE"])[0])
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+ iuse=""
+ now_use=self.applied_useflags[x[2]]
+ for ebuild_iuse in portage_util.unique_array(iuse_split):
+ usechange=""
+ if old_use:
+ if (old_use.count(ebuild_iuse) and not now_use.count(ebuild_iuse)) or (not old_use.count(ebuild_iuse) and now_use.count(ebuild_iuse)):
+ usechange="*"
+
+ if ebuild_iuse in self.applied_useflags[x[2]]:
+ if usechange == "*":
+ iuse=green("+"+ebuild_iuse)
+ else:
+ iuse=red("+"+ebuild_iuse)
+ elif ebuild_iuse in portage.settings.usemask:
+ iuse=blue("(-"+ebuild_iuse+")")
+ else:
+ iuse=blue("-"+ebuild_iuse)
+ verboseadd+=iuse+usechange+" "
+
+ # size verbose
+ mysize=0
+ if x[0] == "ebuild" and x[-1]!="nomerge":
+ myfilesdict=portage.portdb.getfetchsizes(x[2], useflags=self.applied_useflags[x[2]], debug=edebug)
+ if myfilesdict==None:
+ myfilesdict="[empty/missing/bad digest]"
+ else:
+ for myfetchfile in myfilesdict.keys():
+ if myfetchfile not in myfetchlist:
+ mysize+=myfilesdict[myfetchfile]
+ myfetchlist.append(myfetchfile)
+ totalsize+=mysize
+ verboseadd+=format_size(mysize)+" "
+
+ # overlay verbose
+ # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
+ # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
+ file_name=portage.portdb.findname(x[2])
+ if file_name: # It might not exist in the tree
+ dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
+ if (overlays.count(dir_name)>0):
+ verboseadd+=teal("["+str(overlays.index(os.path.normpath(dir_name))+1)+"]")+" "
+ display_overlays=True
+ else:
+ verboseadd += "[No ebuild?]"
+
+ xs=portage.pkgsplit(x[2])
+ if xs[2]=="r0":
+ xs[2]=""
+ else:
+ xs[2]="-"+xs[2]
+
+ if self.pkgsettings.has_key("COLUMNWIDTH"):
+ mywidth=int(self.pkgsettings.settings["COLUMNWIDTH"])
+ else:
+ mywidth=130
+ oldlp=mywidth-30
+ newlp=oldlp-30
+
+ indent=""
+ if ("--tree" in myopts):
+ indent=" "*mygraph.depth(string.join(x))
+
+ if myoldbest:
+ myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
+ if myoldbest[-3:]=="-r0":
+ myoldbest=myoldbest[:-3]
+ myoldbest=blue("["+myoldbest+"]")
+
+ if x[1]!="/":
+ if "--columns" in myopts:
+ myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+ if (newlp-nc_len(myprint)) > 0:
+ myprint=myprint+(" "*(newlp-nc_len(myprint)))
+ myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
+ if (oldlp-nc_len(myprint)) > 0:
+ myprint=myprint+" "*(oldlp-nc_len(myprint))
+ myprint=myprint+myoldbest
+ myprint=myprint+darkgreen(" to "+x[1])+" "+verboseadd
+ else:
+ myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+darkgreen("to "+x[1])+" "+verboseadd
+ else:
+ if "--columns" in myopts:
+ myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+ if (newlp-nc_len(myprint)) > 0:
+ myprint=myprint+(" "*(newlp-nc_len(myprint)))
+ myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
+ if (oldlp-nc_len(myprint)) > 0:
+ myprint=myprint+(" "*(oldlp-nc_len(myprint)))
+ myprint=myprint+myoldbest+" "+verboseadd
+ else:
+ if x[3]=="nomerge":
+ myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
+ else:
+ myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
+ p.append(myprint)
+
+ if ("--tree" not in myopts):
+ mysplit=portage.pkgsplit(x[2])
+
+ # XXX mysplit _can_ be None.... Why?
+ if mysplit and (len(mysplit)==3):
+ if "--emptytree" not in myopts:
+ if mysplit[0]=="sys-apps/portage":
+ if ((mysplit[1]+mysplit[2]) != portage.VERSION) and \
+ ("livecvsportage" not in portage.settings.features):
+ if mylist.index(x)<len(mylist)-1:
+ p.append(red("*** Portage will stop merging at this point and reload itself,"))
+ p.append(red(" recalculate dependencies, and complete the merge."))
+ if "--update" not in myopts:
+ p.append(darkgreen(" You may avoid the remerging of packages by updating portage on its own."))
+ print
+ else:
+ if mysplit[0]=="sys-apps/portage" and ("--emptytree" in myopts):
+ if mysplit[1]+mysplit[2]!=portage.VERSION:
+ p.append(red("***")+" Please update portage to the above version before proceeding.")
+ p.append(" Failure to do so may result in failed or improper merges.")
+ p.append(" A simple '"+green("emerge -u portage")+"' is sufficient.")
+ p.append("")
+ del mysplit
+
+ for x in p:
+ print x
+
+ if "--verbose" in myopts:
+ print
+ print "Total size of downloads: "+format_size(totalsize)
+ if overlays and display_overlays:
+ print "Portage overlays:"
+ y=0
+ for x in overlays:
+ y=y+1
+ print " "+teal("["+str(y)+"]"),x
+
+ if "--changelog" in myopts:
+ print
+ for revision,text in changelogs:
+ print bold('*'+revision)
+ sys.stdout.write(text)
+
+ def calc_changelog(self,ebuildpath,current,next):
+ current = '-'.join(portage.catpkgsplit(current)[1:])
+ if current.endswith('-r0'): current = current[:-3]
+ next = '-'.join(portage.catpkgsplit(next)[1:])
+ if next.endswith('-r0'): next = next[:-3]
+ changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
+ try:
+ changelog = open(changelogpath).read()
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ return []
+ divisions = self.find_changelog_tags(changelog)
+ #print 'XX from',current,'to',next
+ #for div,text in divisions: print 'XX',div
+ # skip entries for all revisions above the one we are about to emerge
+ for i in range(len(divisions)):
+ if divisions[i][0]==next:
+ divisions = divisions[i:]
+ break
+ # find out how many entries we are going to display
+ for i in range(len(divisions)):
+ if divisions[i][0]==current:
+ divisions = divisions[:i]
+ break
+ else:
+ # couldnt find the current revision in the list. display nothing
+ return []
+ return divisions
+
+ def find_changelog_tags(self,changelog):
+ divs = []
+ release = None
+ while 1:
+ match = re.search(r'^\*\ ?([-a-zA-Z0-9_.]*)(?:\ .*)?\n',changelog,re.M)
+ if match is None:
+ if release is not None:
+ divs.append((release,changelog))
+ return divs
+ if release is not None:
+ divs.append((release,changelog[:match.start()]))
+ changelog = changelog[match.end():]
+ release = match.group(1)
+ if release.endswith('.ebuild'):
+ release = release[:-7]
+ if release.endswith('-r0'):
+ release = release[:-3]
+
+ def outdated(self):
+ return self.outdatedpackages
+
+ def merge(self,mylist):
+ returnme=0
+ mymergelist=[]
+
+ #check for blocking dependencies
+ if ("--fetchonly" not in myopts) and ("--buildpkgonly" not in myopts):
+ for x in mylist:
+ if x[0]=="blocks":
+ print "\n!!! Error: the "+x[2]+" package conflicts with another package."
+ print "!!! both can't be installed on the same system together."
+ print "!!! Please use 'emerge --pretend' to determine blockers."
+ print
+ if ("--pretend" not in myopts):
+ sys.exit(1)
+
+ #buildsyspkg: I need mysysdict also on resume (moved from the else block)
+ mysysdict=genericdict(syslist)
+ if ("--resume" in myopts):
+ # We're resuming.
+ print green("*** Resuming merge...")
+ emergelog(" *** Resuming merge...")
+ mymergelist=portage.mtimedb["resume"]["mergelist"][:]
+ if ("--skipfirst" in myopts) and mymergelist:
+ del portage.mtimedb["resume"]["mergelist"][0]
+ del mymergelist[0]
+ else:
+ myfavs=portage.grabfile(portage.root+portage.WORLD_FILE)
+ myfavdict=genericdict(myfavs)
+ for x in range(len(mylist)):
+ if mylist[x][3]!="nomerge":
+ # Add to the mergelist
+ mymergelist.append(mylist[x])
+ else:
+ myfavkey=portage.cpv_getkey(mylist[x][2])
+ if "--onlydeps" in myopts:
+ continue
+ # Add to the world file. Since we won't be able to later.
+ if (not "--fetchonly" in myopts) and (myfavkey in favorites):
+ #don't record if already in system profile or already recorded
+ if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+ #we don't have a favorites entry for this package yet; add one
+ myfavdict[myfavkey]=myfavkey
+ print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+ if not "--fetchonly" in myopts:
+ portage.writedict(myfavdict,portage.root+portage.WORLD_FILE,writekey=0)
+
+ portage.mtimedb["resume"]["mergelist"]=mymergelist[:]
+
+ # We need to yank the harmful-to-new-builds settings from features.
+ myorigfeat=self.pkgsettings["FEATURES"]
+ myfeat=myorigfeat.split()
+ while ("keeptemp" in myfeat):
+ del myfeat[myfeat.index("keeptemp")]
+ while ("keepwork" in myfeat):
+ del myfeat[myfeat.index("keepwork")]
+
+ self.pkgsettings["FEATURES"]=string.join(myfeat)
+
+ mergecount=0
+ for x in mymergelist:
+ mergecount+=1
+ myroot=x[1]
+ pkgindex=2
+ if x[0]=="blocks":
+ pkgindex=3
+ y=portage.portdb.findname(x[pkgindex])
+ if not "--pretend" in myopts:
+ print ">>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+")",x[pkgindex],"to",x[1]
+ emergelog(" >>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" to "+x[1])
+
+ self.pkgsettings["EMERGE_FROM"] = x[0][:]
+ self.pkgsettings.backup_changes("EMERGE_FROM")
+
+ #buildsyspkg: Check if we need to _force_ binary package creation
+ issyspkg = ("buildsyspkg" in myfeat) \
+ and x[0] != "blocks" \
+ and mysysdict.has_key(portage.cpv_getkey(x[2])) \
+ and not ("--buildpkg" in myopts)
+ if x[0] in ["ebuild","blocks"]:
+ if (x[0]=="blocks") and ("--fetchonly" not in myopts):
+ raise Exception, "Merging a blocker"
+ elif ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts):
+ if ("--fetch-all-uri" in myopts):
+ retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1,fetchall=1)
+ else:
+ retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1)
+ if (retval == None) or retval:
+ print
+ print "!!! Fetch for",y,"failed, continuing..."
+ print
+ returnme=1
+ continue
+ elif "--buildpkg" in myopts or issyspkg:
+ #buildsyspkg: Sounds useful to display something, but I don't know if we should also log it
+ if issyspkg:
+ print ">>> This is a system package, let's pack a rescue tarball."
+ #emergelog(">>> This is a system package, let's pack a rescue tarball.")
+ #create pkg, then merge pkg
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Packaging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"package",myroot,self.pkgsettings,edebug)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ #dynamically update our database
+ if "--buildpkgonly" not in myopts:
+ portage.db[portage.root]["bintree"].inject(x[2])
+ mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+
+ self.pkgsettings["EMERGE_FROM"] = "binary"
+ self.pkgsettings.backup_changes("EMERGE_FROM")
+
+ retval=portage.pkgmerge(mytbz2,myroot,self.pkgsettings)
+ if retval==None:
+ sys.exit(1)
+ else:
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"merge",myroot,self.pkgsettings,edebug)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ #dynamically update our database
+ elif x[0]=="binary":
+ #merge the tbz2
+ mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
+ if portage.db[portage.root]["bintree"].isremote(x[2]):
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Fetch"
+ emergelog(" --- ("+str(mergecount)+" of "+str(len(mymergelist))+") Fetching Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
+ portage.db[portage.root]["bintree"].gettbz2(x[2])
+
+ if ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts):
+ continue
+
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
+ retval=portage.pkgmerge(mytbz2,x[1],self.pkgsettings)
+ if retval==None:
+ sys.exit(1)
+ #need to check for errors
+ if "--buildpkgonly" not in myopts:
+ portage.db[x[1]]["vartree"].inject(x[2])
+ myfavkey=portage.cpv_getkey(x[2])
+ if "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts and myfavkey in favorites:
+ myfavs=portage.grabfile(myroot+portage.WORLD_FILE)
+ myfavdict=genericdict(myfavs)
+ mysysdict=genericdict(syslist)
+ #don't record if already in system profile or already recorded
+ if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+ #we don't have a favorites entry for this package yet; add one
+ myfavdict[myfavkey]=myfavkey
+ print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Updating world file ("+x[pkgindex]+")")
+ portage.writedict(myfavdict,myroot+portage.WORLD_FILE,writekey=0)
+
+ if ("noclean" not in portage.features) and (x[0] != "binary"):
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean Post"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Post-Build Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+
+ if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
+ # Clean the old package that we have merged over top of it.
+ if self.pkgsettings["AUTOCLEAN"]=="yes":
+ xsplit=portage.pkgsplit(x[2])
+ emergelog(" >>> AUTOCLEAN: "+xsplit[0])
+ retval=unmerge("clean", [xsplit[0]])
+ if not retval:
+ emergelog(" --- AUTOCLEAN: Nothing unmerged.")
+
+ # Figure out if we need a restart.
+ mysplit=portage.pkgsplit(x[2])
+ if mysplit[0]=="sys-apps/portage":
+ myver=mysplit[1]+"-"+mysplit[2]
+ if myver[-3:]=='-r0':
+ myver=myver[:-3]
+ if (myver != portage.VERSION) and \
+ ("livecvsportage" not in portage.settings.features):
+ if len(mymergelist) > mergecount:
+ myargv=sys.argv
+ myr=0
+ for myra in range(len(myargv)):
+ if myargv[myr][0:len("portage")]=="portage":
+ del myargv[myr]
+ myr-=1
+ if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage":
+ del myargv[myr]
+ myr-=1
+ myr+=1
+ emergelog(" *** RESTARTING emerge via exec() after change of portage version.")
+ portage.portageexit()
+ # Remove --ask from options before restarting
+ mynewargv=[]
+ badlongopts = ["--ask","--tree","--changelog"]
+ badshortopts = ["a","t","l"]
+ for arg in myargv:
+ if arg[0:2] == "--":
+ if arg in badlongopts:
+ continue
+ mynewargv += [arg]
+ elif arg[0] == "-":
+ myarg = "-"
+ for ch in arg[1:]:
+ if ch in badshortopts:
+ continue
+ myarg += ch
+ mynewargv += [myarg]
+ else:
+ mynewargv += [arg]
+ os.execv("/usr/lib/portage/bin/emerge", mynewargv)
+
+ if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
+ emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1])
+
+ # Unsafe for parallel merges
+ del portage.mtimedb["resume"]["mergelist"][0]
+
+ emergelog(" *** Finished. Cleaning up...")
+
+ # We're out of the loop... We're done. Delete the resume data.
+ if portage.mtimedb.has_key("resume"):
+ del portage.mtimedb["resume"]
+
+ if ("--pretend" not in myopts):
+ if ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
+ if (mergecount>0):
+ if retval:
+ portage.env_update()
+
+ #by doing an exit this way, --fetchonly can continue to try to
+ #fetch everything even if a particular download fails.
+ if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+ if returnme:
+ print "\n\n!!! Some fetch errors were encountered. Please see above for details.\n\n"
+ sys.exit(returnme)
+ else:
+ sys.exit(0)
+
+def unmerge(unmerge_action, unmerge_files):
+ candidate_catpkgs=[]
+ global_unmerge=0
+
+ realsyslist = getlist("system")
+ syslist = []
+ for x in realsyslist:
+ mycp = portage.dep_getkey(x)
+ if mycp in portage.settings.virtuals:
+ syslist.extend(portage.settings.virtuals[mycp])
+ syslist.append(mycp)
+
+ global myopts
+ mysettings = portage.config(clone=portage.settings)
+
+ if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files:
+ if "unmerge"==unmerge_action:
+ print
+ print bold("emerge unmerge")+" can only be used with specific package names, not with "+bold("world")+" or"
+ print bold("system")+" targets."
+ print
+ return 0
+ else:
+ global_unmerge=1
+
+ localtree=portage.db[portage.root]["vartree"]
+ # process all arguments and add all valid db entries to candidate_catpkgs
+ if global_unmerge:
+ if not unmerge_files or "world" in unmerge_files:
+ candidate_catpkgs.extend(localtree.getallnodes())
+ elif "system" in unmerge_files:
+ candidate_catpkgs.extend(getlist("system"))
+ else:
+ #we've got command-line arguments
+ if not unmerge_files:
+ print "\nNo packages to unmerge have been provided.\n"
+ return 0
+ for x in unmerge_files:
+ arg_parts=x.split('/')
+ if (x[0] not in [".","/"]) and (arg_parts[-1][-7:] != ".ebuild"):
+ #possible cat/pkg or dep; treat as such
+ candidate_catpkgs.append(x)
+ elif unmerge_action in ["prune","clean"]:
+ print "\n!!! Prune and clean do not accept individual ebuilds as arguments;\n skipping.\n"
+ continue
+ else:
+ # it appears that the user is specifying an installed ebuild and we're in "unmerge" mode, so it's
+ # ok.
+ if not os.path.exists(x):
+ print "\n!!! The path '"+x+"' doesn't exist.\n"
+ return 0
+
+ absx = os.path.abspath(x)
+ sp_absx = absx.split("/")
+ if sp_absx[-1][-7:] == ".ebuild":
+ del sp_absx[-1]
+ absx = string.join(sp_absx,"/")
+
+ sp_absx_len = len(sp_absx)
+
+ vdb_path = portage.root+portage.VDB_PATH
+ vdb_len = len(vdb_path)
+
+ sp_vdb = vdb_path.split("/")
+ sp_vdb_len = len(sp_vdb)
+
+ if not os.path.exists(absx+"/CONTENTS"):
+ print "!!! Not a valid db dir: "+str(absx)
+ return 0
+
+ if sp_absx_len <= sp_vdb_len:
+ # The Path is shorter... so it can't be inside the vdb.
+ print spabsx
+ print absx
+ print "\n!!!",x,"cannot be inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n"
+ return 0
+
+ for idx in range(0,sp_vdb_len):
+ if (idx >= sp_absx_len) or (sp_vdb[idx] != sp_absx[idx]):
+ print sp_absx
+ print absx
+ print "\n!!!",x,"is not inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n"
+ return 0
+
+ print "="+string.join(sp_absx[sp_vdb_len:],"/")
+ candidate_catpkgs.append("="+string.join(sp_absx[sp_vdb_len:],"/"))
+
+ if ("--pretend" in myopts) or ("--ask" in myopts):
+ print darkgreen("\n>>> These are the packages that I would unmerge:")
+
+ pkgmap={}
+ numselected=0
+ for x in candidate_catpkgs:
+ #cycle through all our candidate deps and determine what will and will not get unmerged
+ try:
+ mymatch=localtree.dep_match(x)
+ except KeyError:
+ mymatch=None
+ except ValueError, errpkgs:
+ print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
+ print "!!! one of the following fully-qualified ebuild names instead:\n"
+ for i in errpkgs[0]:
+ print " " + green(i)
+ print
+ sys.exit(1)
+
+ if not mymatch and x[0] not in "<>=~":
+ #add a "=" if missing
+ mymatch=localtree.dep_match("="+x)
+ if not mymatch:
+ print "\n--- Couldn't find " + white(x) + " to "+unmerge_action+"."
+ continue
+ mykey=portage.key_expand(portage.dep_getkey(mymatch[0]),portage.db["/"]["vartree"].dbapi)
+ if not pkgmap.has_key(mykey):
+ pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
+ if unmerge_action=="unmerge":
+ for y in mymatch:
+ if y not in pkgmap[mykey]["selected"]:
+ pkgmap[mykey]["selected"].append(y)
+ numselected=numselected+len(mymatch)
+
+ else:
+ #unmerge_action in ["prune", clean"]
+ slotmap={}
+ for mypkg in mymatch:
+ if unmerge_action=="clean":
+ myslot=localtree.getslot(mypkg)
+ else:
+ #since we're pruning, we don't care about slots and put all the pkgs in together
+ myslot=0
+ if not slotmap.has_key(myslot):
+ slotmap[myslot]={}
+ slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
+ for myslot in slotmap.keys():
+ counterkeys=slotmap[myslot].keys()
+ counterkeys.sort()
+ if not counterkeys:
+ continue
+ counterkeys.sort()
+ pkgmap[mykey]["protected"].append(slotmap[myslot][counterkeys[-1]])
+ del counterkeys[-1]
+ #be pretty and get them in order of merge:
+ for ckey in counterkeys:
+ pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
+ numselected=numselected+1
+ #ok, now the last-merged package is protected, and the rest are selected
+ if global_unmerge and not numselected:
+ print "\n>>> No outdated packages were found on your system.\n"
+ return 0
+
+ if not numselected:
+ print "\n>>>",unmerge_action+": No packages selected for removal.\n"
+ return 0
+
+ for x in pkgmap.keys():
+ for y in localtree.dep_match(x):
+ if y not in pkgmap[x]["omitted"] and \
+ y not in pkgmap[x]["selected"] and \
+ y not in pkgmap[x]["protected"]:
+ pkgmap[x]["omitted"].append(y)
+ if global_unmerge and not pkgmap[x]["selected"]:
+ #avoid cluttering the preview printout with stuff that isn't getting unmerged
+ continue
+ if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
+ print red("\a\n\n!!! '%s' is part of your system profile. '%s'" % (mykey))
+ print yellow("\a!!! Unmerging it may be damaging to your system.\n")
+ if "--pretend" not in myopts and "--ask" not in myopts:
+ global EMERGE_WARNING_DELAY
+ countdown(EMERGE_WARNING_DELAY,red("Press Ctrl-C to Stop"))
+ print "\n "+white(x)
+ for mytype in ["selected","protected","omitted"]:
+ print string.rjust(mytype,12)+":",
+ if pkgmap[x][mytype]:
+ for mypkg in pkgmap[x][mytype]:
+ mysplit=portage.catpkgsplit(mypkg)
+ if mysplit[3]=="r0":
+ myversion=mysplit[2]
+ else:
+ myversion=mysplit[2]+"-"+mysplit[3]
+ if mytype=="selected":
+ print red(myversion),
+ else:
+ print green(myversion),
+ else:
+ print "none",
+ print
+
+ print "\n>>>",red("'Selected'"),"packages are slated for removal."
+ print ">>>",green("'Protected'"),"and",green("'omitted'"),"packages will not be removed.\n"
+
+ if "--pretend" in myopts:
+ #we're done... return
+ return 0
+ if "--ask" in myopts:
+ if userquery("Do you want me to unmerge these packages?")=="No":
+ # enter pretend mode for correct formatting of results
+ myopts+=["--pretend"]
+ print
+ print "Quitting."
+ print
+ return 0
+ #the real unmerging begins, after a short delay....
+
+ global CLEAN_DELAY
+ countdown(CLEAN_DELAY, ">>> Unmerging")
+
+ for x in pkgmap.keys():
+ for y in pkgmap[x]["selected"]:
+ print ">>> Unmerging "+y+"..."
+ emergelog("=== Unmerging... ("+y+")")
+ mysplit=string.split(y,"/")
+ #unmerge...
+ retval=portage.unmerge(mysplit[0],mysplit[1],portage.root,mysettings,unmerge_action not in ["clean","prune"])
+ if retval:
+ emergelog(" !!! unmerge FAILURE: "+y)
+ else:
+ emergelog(" >>> unmerge success: "+y)
+ #run ldconfig, etc...
+ portage.env_update()
+ if not numselected:
+ return 0
+ else:
+ return 1
+
+
+def chk_updated_info_files(retval):
+ root=portage.root
+
+ infodirs=[]
+ infodirs.extend(string.split(portage.settings["INFOPATH"], ":"))
+ infodirs.extend(string.split(portage.settings["INFODIR"], ":"))
+
+ print
+ if os.path.exists("/usr/bin/install-info"):
+ regen_infodirs=[]
+ for z in infodirs:
+ if z=='':
+ continue
+ inforoot=normpath(root+z)
+ if os.path.isdir(inforoot):
+ try:
+ infomtime=os.stat(inforoot)[ST_MTIME]
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ infomtime=0
+
+ if not portage.mtimedb.has_key("info"):
+ portage.mtimedb["info"]={}
+ if portage.mtimedb["info"].has_key(inforoot):
+ if portage.mtimedb["info"][inforoot]==infomtime:
+ pass
+ else:
+ portage.mtimedb["info"][inforoot]=infomtime
+ regen_infodirs.append(inforoot)
+ else:
+ regen_infodirs.append(inforoot)
+
+ if not regen_infodirs:
+ print " "+green("*")+" GNU info directory index is up-to-date."
+ else:
+ print " "+green("*")+" Regenerating GNU info directory index..."
+
+ icount=0
+ badcount=0
+ for inforoot in regen_infodirs:
+ if inforoot=='':
+ continue
+ try:
+ os.rename(inforoot+"/dir",inforoot+"/dir.old")
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+
+ if not os.path.isdir(inforoot):
+ continue
+ errmsg = ""
+ for x in os.listdir(inforoot):
+ if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
+ continue
+ myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
+ existsstr="already exists, for file `"
+ if myso!="":
+ if re.search(existsstr,myso):
+ # Already exists... Don't increment the count for this.
+ pass
+ elif myso[:44]=="install-info: warning: no info dir entry in ":
+ # This info file doesn't contain a DIR-header: install-info produces this
+ # (harmless) warning (the --quiet switch doesn't seem to work).
+ # Don't increment the count for this.
+ pass
+ else:
+ badcount=badcount+1
+ errmsg += myso + "\n"
+ icount=icount+1
+
+ #update mtime so we can potentially avoid regenerating.
+ portage.mtimedb["info"][inforoot]=os.stat(inforoot)[ST_MTIME]
+
+ if badcount:
+ print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
+ print errmsg
+ else:
+ print " "+green("*")+" Processed",icount,"info files."
+
+
+def post_emerge(retval=0):
+ global myopts
+ os.chdir("/")
+ if "--pretend" in myopts:
+ sys.exit(retval)
+
+ emergelog(" *** exiting successfully.")
+
+ if "noinfo" not in portage.settings.features:
+ chk_updated_info_files(retval)
+
+ chk_updated_cfg_files()
+ sys.exit(retval)
+
+
+def chk_updated_cfg_files():
+ if portage.settings["CONFIG_PROTECT"]:
+ #number of directories with some protect files in them
+ procount=0
+ for x in string.split(portage.settings["CONFIG_PROTECT"]):
+ if os.path.isdir(x):
+ a=commands.getstatusoutput("cd "+x+"; find . -iname '._cfg????_*'")
+ if a[0]!=0:
+ print " "+red("*")+" error scanning",x
+ else:
+ files=string.split(a[1])
+ if files:
+ procount=procount+1
+ print " "+yellow("* IMPORTANT:")+"",len(files),"config files in",x,"need updating."
+ if procount:
+ #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+ print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+ print
+
+# general options that should be taken into account before any action
+if "--debug" in myopts:
+ edebug=1
+
+if myaction in ["sync","rsync","metadata"] and (not "--help" in myopts):
+ if "--pretend" in myopts:
+ print "emerge: \"sync\" actions do not support \"--pretend.\""
+ sys.exit(1)
+
+ emergelog(" === "+str(myaction))
+ myportdir=portage.settings["PORTDIR"]
+ if myportdir[-1]=="/":
+ myportdir=myportdir[:-1]
+ if not os.path.exists(myportdir):
+ print ">>>",myportdir,"not found, creating it."
+ os.makedirs(myportdir,0755)
+ syncuri=string.rstrip(portage.settings["SYNC"])
+ os.umask(0022)
+ if myaction == "metadata":
+ if "--ask" in myopts:
+ if userquery("Are you sure?") == "No":
+ sys.exit(1)
+ print "skipping sync"
+ updatecache_flg = True
+ tmpservertimestampfile = None
+ elif syncuri[:8]=="rsync://":
+ if not os.path.exists("/usr/bin/rsync"):
+ print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
+ print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
+ sys.exit(1)
+ mytimeout=180
+ if portage.settings.has_key("RSYNC_TIMEOUT"):
+ try:
+ mytimeout=int(portage.settings["RSYNC_TIMEOUT"])
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+
+ rsync_flags = [
+ "--recursive", # Recurse directories
+ "--links", # Consider symlinks
+ "--safe-links", # Ignore links outside of tree
+ "--perms", # Preserve permissions
+ "--times", # Preserive mod times
+ "--compress", # Compress the data transmitted
+ "--force", # Force deletion on non-empty dirs
+ "--whole-file", # Don't do block transfers, only entire files
+ "--delete", # Delete files that aren't in the master tree
+ "--delete-after", # Delete only after everything else is done
+ "--stats", # Show final statistics about what was transfered
+ "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
+ "--exclude='/distfiles'", # Exclude distfiles from consideration
+ "--exclude='/local'", # Exclude local from consideration
+ "--exclude='/packages'", # Exclude packages from consideration
+ ]
+
+ if "--quiet" in myopts:
+ rsync_flags.append("--quiet") # Shut up a lot
+ else:
+ rsync_flags.append("--progress") # Progress meter for each file
+
+ if "--verbose" in myopts:
+ rsync_flags.append("--verbose") # More noise? Not really sure what
+
+ if "--debug" in myopts:
+ rsync_flags.append("--checksum") # Force checksum on all files
+
+ if portage.settings.has_key("RSYNC_EXCLUDEFROM"):
+ if os.path.exists(portage.settings["RSYNC_EXCLUDEFROM"]):
+ rsync_flags.append("--exclude-from="+portage.settings["RSYNC_EXCLUDEFROM"])
+ else:
+ print "!!! RSYNC_EXCLUDEFROM specified, but file does not exist."
+
+ if portage.settings.has_key("RSYNC_RATELIMIT"):
+ rsync_flags.append("--bwlimit="+portage.settings["RSYNC_RATELIMIT"])
+
+ rsynccommand = "/usr/bin/rsync " + string.join(rsync_flags, " ")
+
+ servertimestampdir = portage.settings.depcachedir+"/"
+ servertimestampfile = portage.settings.depcachedir+"/timestamp.chk"
+ tmpservertimestampdir = portage.settings["PORTAGE_TMPDIR"]+"/"
+ tmpservertimestampfile = portage.settings["PORTAGE_TMPDIR"]+"/timestamp.chk"
+
+ # We only use the backup if a timestamp exists in the portdir.
+ content=None
+ if os.path.exists(myportdir+"/metadata/timestamp.chk"):
+ content=portage.grabfile(servertimestampfile)
+ if (not content):
+ content=portage.grabfile(myportdir+"/metadata/timestamp.chk")
+
+ if (content):
+ try:
+ mytimestamp=time.mktime(time.strptime(content[0], "%a, %d %b %Y %H:%M:%S +0000"))
+ except ValueError:
+ mytimestamp=0
+ else:
+ mytimestamp=0
+
+ if not os.path.exists(servertimestampdir):
+ os.mkdir(servertimestampdir)
+ os.chown(servertimestampdir, os.getuid(), portage.portage_gid)
+ os.chmod(servertimestampdir, 02775)
+
+ #exitcode=0
+ try:
+ maxretries=int(portage.settings["RSYNC_RETRIES"])
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ maxretries=3 #default number of retries
+
+ retries=0
+ hostname, port=re.split("rsync://([^:/]*)(:[0-9]+)?", syncuri)[1:3];
+ if port==None:
+ port=""
+ updatecache_flg=True
+
+ ips=[]
+ while (1):
+ if ips:
+ del ips[0]
+ if ips==[]:
+ try:
+ ips=socket.gethostbyname_ex(hostname)[2]
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "Notice:",str(e)
+ dosyncuri=syncuri
+
+ if ips:
+ try:
+ dosyncuri=string.replace(syncuri, "//"+hostname+port+"/", "//"+ips[0]+port+"/", 1)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "Notice:",str(e)
+ dosyncuri=syncuri
+
+ if (retries==0):
+ if "--ask" in myopts:
+ if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
+ print
+ print "Quitting."
+ print
+ sys.exit(0)
+ emergelog(">>> starting rsync with "+dosyncuri)
+ if "--quiet" not in myopts:
+ print ">>> starting rsync with "+dosyncuri+"..."
+ else:
+ emergelog(">>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri))
+ print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
+
+ if "--quiet" not in myopts:
+ print ">>> checking server timestamp ..."
+ mycommand=rsynccommand+" "+dosyncuri+"/metadata/timestamp.chk "+tmpservertimestampdir
+ exitcode=portage.spawn(mycommand,portage.settings,free=1)
+ if (exitcode==0):
+ try:
+ servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000"))
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ servertimestamp = 0
+
+ if (servertimestamp != 0) and (servertimestamp == mytimestamp):
+ emergelog(">>> Cancelling sync -- Already current.")
+ print
+ print ">>>"
+ print ">>> Timestamps on the server and in the local repository are the same."
+ print ">>> Cancelling all further sync action. You are already up to date."
+ print ">>>"
+ print
+ sys.exit(0)
+ elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
+ emergelog(">>> Server out of date: %s" % dosyncuri)
+ print
+ print ">>>"
+ print ">>> SERVER OUT OF DATE: %s" % dosyncuri
+ print ">>>"
+ print
+ elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
+ # actual sync
+ mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
+ exitcode=portage.spawn(mycommand,portage.settings,free=1)
+ if exitcode in [0,1,2,3,4,11,14,20,21]:
+ break
+ elif exitcode in [0,1,2,3,4,11,14,20,21]:
+ break
+
+ retries=retries+1
+
+ if retries<=maxretries:
+ print ">>> retry ..."
+ time.sleep(11)
+ else:
+ # over retries
+ # exit loop
+ updatecache_flg=False
+ break
+
+ if (exitcode==0):
+ emergelog("=== Sync completed with %s" % dosyncuri)
+ elif (exitcode>0):
+ print
+ if exitcode==1:
+ print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
+ print darkred("!!!")+green(" that your SYNC statement is proper.")
+ print darkred("!!!")+green(" SYNC="+portage.settings["SYNC"])
+ elif exitcode==11:
+ print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
+ print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
+ print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
+ print darkred("!!!")+green(" and try again after the problem has been fixed.")
+ print darkred("!!!")+green(" PORTDIR="+portage.settings["PORTDIR"])
+ elif exitcode==20:
+ print darkred("!!!")+green(" Rsync was killed before it finished.")
+ else:
+ print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
+ print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
+ print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
+ print darkred("!!!")+green(" temporary problem unless complications exist with your network")
+ print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
+ print
+ sys.exit(exitcode)
+ elif syncuri[:6]=="cvs://":
+ if not os.path.exists("/usr/bin/cvs"):
+ print "!!! /usr/bin/cvs does not exist, so rsync support is disabled."
+ print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
+ sys.exit(1)
+ cvsroot=syncuri[6:]
+ cvsdir=os.path.dirname(myportdir)
+ if not os.path.exists(myportdir+"/CVS"):
+ #initial checkout
+ print ">>> starting initial cvs checkout with "+syncuri+"..."
+ if not portage.spawn("cd "+cvsdir+"; cvs -d "+cvsroot+" login",portage.settings,free=1):
+ print "!!! cvs login error; exiting."
+ sys.exit(1)
+ if os.path.exists(cvsdir+"/gentoo-x86"):
+ print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
+ sys.exit(1)
+ if not portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",portage.settings,free=1):
+ print "!!! cvs checkout error; exiting."
+ sys.exit(1)
+ if cvsdir!=myportdir:
+ portage.movefile(cvsdir,portage.settings["PORTDIR"])
+ sys.exit(0)
+ else:
+ #cvs update
+ print ">>> starting cvs update with "+syncuri+"..."
+ sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",portage.settings,free=1))
+ else:
+ print "!!! rsync setting: ",syncuri,"not recognized; exiting."
+ sys.exit(1)
+
+ try: # Prevent users from affecting ebuild.sh.
+ os.close(sys.stdin.fileno())
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+
+ if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
+ if "--quiet" not in myopts:
+ print "\n>>> Updating Portage cache: ",
+ os.umask(0002)
+ cachedir = os.path.normpath(portage.settings.depcachedir)
+ if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
+ "/lib", "/opt", "/proc", "/root", "/sbin",
+ "/sys", "/tmp", "/usr", "/var"]:
+ print "!!! PORTAGE_CACHEDIR IS SET TO A PRIMARY ROOT DIRECTORY ON YOUR SYSTEM."
+ print "!!! This is ALMOST CERTAINLY NOT what you want: "+str(cachedir)
+ sys.exit(73)
+ if not os.path.exists(cachedir):
+ os.mkdir(cachedir)
+
+ # Potentially bad
+ #if os.path.exists(cachedir+"/"+myportdir):
+ # portage.spawn("rm -Rf "+cachedir+"/"+myportdir+"/*",portage.settings,free=1)
+
+ # save timestamp.chk for next timestamp check.
+ try:
+ if tmpservertimestampfile != None:
+ portage.movefile(tmpservertimestampfile, servertimestampfile)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "!!! Failed to save current timestamp."
+ print "!!!",e
+
+ portage.portdb.flush_cache()
+
+ try:
+ os.umask(002)
+ os.chown(cachedir, os.getuid(), portage.portage_gid)
+ os.chmod(cachedir, 02775)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+ # we don't make overlay trees cache here, plus we don't trust portage.settings.categories
+ porttree_root = portage.portdb.porttree_root
+ pdb = portage.portdbapi(porttree_root, portage.config(config_profile_path=portage.settings.profile_path[:], \
+ config_incrementals=portage.settings.incrementals[:]))
+ cp_list = pdb.cp_all()
+ if len(cp_list) == 0:
+ print "no metadata to transfer, exiting"
+ sys.exit(0)
+ cp_list.sort()
+ pcnt=0
+ pcntstr=""
+ pcntcount=len(cp_list)/100.0
+ nextupdate=pcntcount
+ current=1
+
+ def cleanse_cache(pdb, cat, saves, porttree_root=porttree_root):
+ if len(saves):
+ d={}
+ for v in saves:
+ d[portage.catsplit(v)[1]] = True
+ for pv in pdb.auxdb[porttree_root][cat].keys():
+ if pv not in d:
+ pdb.auxdb[porttree_root][cat].del_key(pv)
+ else:
+ try:
+ pdb.auxdb[porttree_root][cat].clear()
+ del pdb.auxdb[porttree_root][cat]
+ except KeyError:
+ pass
+
+ savelist = []
+ catlist = []
+ oldcat = portage.catsplit(cp_list[0])[0]
+ for cp in cp_list:
+ current += 1
+ if current >= nextupdate:
+ pcnt += 1
+ nextupdate += pcntcount
+ if "--quiet" not in myopts:
+ pcntstr = str(pcnt)
+ sys.stdout.write("\b"*(len(pcntstr)+1)+pcntstr+"%")
+ sys.stdout.flush()
+ cat = portage.catsplit(cp)[0]
+ if cat != oldcat:
+ catlist.append(oldcat)
+ cleanse_cache(pdb, oldcat, savelist)
+ savelist = []
+ oldcat = cat
+ mymatches = pdb.xmatch("match-all", cp)
+ savelist.extend(mymatches)
+ for cpv in mymatches:
+ try: pdb.aux_get(cpv, ["IUSE"],metacachedir=myportdir+"/metadata/cache",debug=("cachedebug" in portage.features))
+ except SystemExit: raise
+ except Exception, e: print "\nFailed cache update:",cpv,e
+ catlist.append(oldcat)
+ catlist.append("local")
+ cleanse_cache(pdb, oldcat, savelist)
+ filelist = portage.listdir(cachedir+"/"+myportdir)
+ for x in filelist:
+ found = False
+ for y in catlist:
+ if x.startswith(y):
+ found = True
+ break
+ if not found:
+ portage.spawn("cd /; rm -Rf "+cachedir+"/"+myportdir+"/"+x,portage.settings,free=1,droppriv=1)
+
+
+ sys.stdout.write("\n\n")
+ sys.stdout.flush()
+
+ portage.portageexit()
+ reload(portage)
+ mybestpv=portage.portdb.xmatch("bestmatch-visible","sys-apps/portage")
+ mypvs=portage.best(portage.db[portage.root]["vartree"].dbapi.match("sys-apps/portage"))
+
+ chk_updated_cfg_files()
+
+ if(mybestpv != mypvs):
+ print
+ print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
+ print red(" * ")+"that you update portage now, before any other packages are updated."
+ print red(" * ")+"Please do so and then update "+bold("ALL")+" of your configuration files."
+ print
+elif myaction=="regen":
+ emergelog(" === regen")
+ #regenerate cache entries
+ print "Regenerating cache entries... "
+ try:
+ os.close(sys.stdin.fileno())
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+ sys.stdout.flush()
+ mynodes=portage.portdb.cp_all()
+ for x in mynodes:
+ mymatches=portage.portdb.xmatch("match-all",x)
+ if not "--quiet" in myopts:
+ print "processing",x
+ for y in mymatches:
+ try:
+ foo=portage.portdb.aux_get(y,["DEPEND"],debug=1)
+ except SystemExit, e:
+ # sys.exit is an exception... And consequently, we can't catch it.
+ raise
+ except Exception, e:
+ print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
+ print "done!"
+# HELP action
+elif "config"==myaction:
+ if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
+ print red("!!! config can only take a single package atom at this time\n")
+ sys.exit(1)
+
+ print
+ pkgs = portage.db[portage.root]["vartree"].dbapi.match(myfiles[0])
+ if len(pkgs) == 0:
+ print "No packages found.\n"
+ sys.exit(0)
+ elif len(pkgs) > 1:
+ if "--ask" in myopts:
+ options = []
+ print "Please select a package to configure:"
+ idx = 0
+ for pkg in pkgs:
+ idx += 1
+ options.append(str(idx))
+ print options[-1]+") "+pkg
+ print "X) Cancel"
+ options.append("X")
+ idx = userquery("Selection?", options)
+ if idx == "X":
+ sys.exit(0)
+ pkg = pkgs[int(idx)-1]
+ else:
+ print "The following packages available:"
+ for pkg in pkgs:
+ print "* "+pkg
+ print "\nPlease use a specific atom or the --ask option."
+ sys.exit(1)
+ else:
+ pkg = pkgs[0]
+
+ print
+ if "--ask" in myopts:
+ if userquery("Ready to configure "+pkg+"?") == "No":
+ sys.exit(0)
+ else:
+ print "Configuring pkg..."
+ print
+ ebuildpath = portage.db[portage.root]["vartree"].dbapi.findname(pkg)
+ mysettings = portage.config(clone=portage.settings)
+ portage.doebuild(ebuildpath,"config",portage.root,mysettings,debug=("--debug" in myopts),cleanup=True)
+ print
+
+# INFO action
+elif "info"==myaction:
+ unameout=commands.getstatusoutput("uname -mrp")[1]
+ print getportageversion()
+ print "================================================================="
+ print "System uname: "+unameout
+ if os.path.exists("/etc/gentoo-release"):
+ os.system("cat /etc/gentoo-release")
+ else:
+ print "Unknown Host Operating System"
+
+ output=commands.getstatusoutput("distcc --version")
+ if not output[0]:
+ print str(string.split(output[1],"\n",1)[0]),
+ if "distcc" in portage.features:
+ print "[enabled]"
+ else:
+ print "[disabled]"
+
+ output=commands.getstatusoutput("ccache -V")
+ if not output[0]:
+ print str(string.split(output[1],"\n",1)[0]),
+ if "ccache" in portage.features:
+ print "[enabled]"
+ else:
+ print "[disabled]"
+
+ myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
+ "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
+ myvars += portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_pkgs")
+ myvars = portage_util.unique_array(myvars)
+ myvars.sort()
+
+ for x in myvars:
+ if portage.isvalidatom(x):
+ pkg_matches = portage.db["/"]["vartree"].dbapi.match(x)
+ pkgs = []
+ for y in pkg_matches:
+ mycpv = portage.catpkgsplit(y)
+ if(mycpv[3] != "r0"):
+ pkgs += [mycpv[2] + "-" + mycpv[3]]
+ else:
+ pkgs += [mycpv[2]]
+ if not pkgs:
+ pkgs = "[Not Present]"
+ else:
+ pkgs = ", ".join(sorted_versions(pkgs))
+ print "%-20s %s" % (x+":", pkgs)
+ else:
+ print "%-20s %s" % (x+":", "[NOT VALID]")
+
+ libtool_vers = string.join(portage.db["/"]["vartree"].dbapi.match("sys-devel/libtool"), ",")
+
+ if "--verbose" in myopts:
+ myvars=portage.settings.keys()
+ else:
+ myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
+ 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
+ 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
+ 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES']
+
+ myvars.extend(portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_vars"))
+
+ myvars = portage_util.unique_array(myvars)
+ unset_vars = []
+ myvars.sort()
+ for x in myvars:
+ if portage.settings.has_key(x):
+ print x+'="'+portage.settings[x]+'"'
+ else:
+ unset_vars.append(x)
+ if unset_vars:
+ print "Unset: "+", ".join(unset_vars)
+ print
+
+ if "--debug" in myopts:
+ for x in dir(portage):
+ module = getattr(portage, x)
+ if "cvs_id_string" in dir(module):
+ print "%s: %s" % (str(x), str(module.cvs_id_string))
+
+# SEARCH action
+elif "search"==myaction:
+ if not myfiles:
+ print "emerge: no search terms provided."
+ else:
+ searchinstance = search()
+ for mysearch in myfiles:
+ try:
+ searchinstance.execute(mysearch)
+ except re.error, comment:
+ print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
+ sys.exit(1)
+ searchinstance.output()
+elif "inject"==myaction:
+ if not myfiles:
+ print "emerge: please specify at least one cat/pkg-ver to inject."
+ sys.exit(1)
+ if "--pretend" in myopts:
+ print "emerge: the \"inject\" action does not support \"--pretend.\""
+ sys.exit(1)
+ for x in myfiles:
+ if x[0] in [">","<","=","!"]:
+ print "!!! '"+x+"' is an invalid specification."
+ print "!!! Must be 'category/package-version' with no other symbols."
+ print
+ continue
+ mycps=portage.catpkgsplit(x)
+ if (not mycps) or (mycps[0]=="null"):
+ print "!!!",x,"is not a specific cat/pkg-version, skipping..."
+ continue
+ if portage.db["/"]["vartree"].exists_specific(x):
+ print "!!! Not injecting",x+"; Package already exists."
+ else:
+ if "--ask" in myopts:
+ if userquery("Do you want to inject the package %s?" % x)=="No":
+ print
+ print "Quitting."
+ print
+ sys.exit(0)
+ portage.db["/"]["vartree"].dbapi.cpv_inject(x)
+ print ">>> Injected",x+"."
+ emergelog(" === inject: "+x)
+elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
+ if 1==unmerge(myaction, myfiles):
+ post_emerge()
+
+elif "depclean"==myaction:
+ # Kill packages that aren't explicitly merged or are required as a
+ # dependency of another package. World file is explicit.
+
+ print
+ print red("*** WARNING ***")+" : DEPCLEAN CAN SERIOUSLY IMPAIR YOUR SYSTEM. USE CAUTION."
+ print red("*** WARNING ***")+" : (Cancel: CONTROL-C) -- ALWAYS VERIFY ALL PACKAGES IN THE"
+ print red("*** WARNING ***")+" : CANDIDATE LIST FOR SANITY BEFORE ALLOWING DEPCLEAN TO"
+ print red("*** WARNING ***")+" : UNMERGE ANY PACKAGES."
+ print red("*** WARNING ***")+" :"
+ print red("*** WARNING ***")+" : USE FLAGS MAY HAVE AN EXTREME EFFECT ON THE OUTPUT."
+ print red("*** WARNING ***")+" : SOME LIBRARIES MAY BE USED BY PACKAGES BUT ARE NOT"
+ print red("*** WARNING ***")+" : CONSIDERED TO BE A DEPEND DUE TO USE FLAG SETTINGS."
+ print red("*** WARNING ***")+" : emerge --update --deep --newuse world TO VERIFY"
+ print red("*** WARNING ***")+" : SANITY IN THIS REGARD."
+ print red("*** WARNING ***")+" :"
+ print red("*** WARNING ***")+" : Packages in the list that are desired may be added"
+ print red("*** WARNING ***")+" : directly to the world file to cause them to be ignored"
+ print red("*** WARNING ***")+" : by depclean and maintained in the future. BREAKAGES DUE"
+ print red("*** WARNING ***")+" : TO UNMERGING AN ==IN-USE LIBRARY== MAY BE REPAIRED BY"
+ print red("*** WARNING ***")+" : MERGING *** THE PACKAGE THAT COMPLAINS *** ABOUT THE"
+ print red("*** WARNING ***")+" : MISSING LIBRARY."
+ print
+ if ("--pretend" not in myopts) and ("--ask" not in myopts):
+ countdown(EMERGE_WARNING_DELAY, ">>> Depclean")
+ emergelog(" >>> depclean")
+
+ mydepgraph=depgraph(myaction,myopts)
+ syslist=getlist("system")
+ worldlist=getlist("world")
+
+ print "Calculating",myaction,"dependencies ",
+ if not mydepgraph.xcreate("world"):
+ print "\n!!! Failed to create deptree."
+ sys.exit(1)
+ print "\b\b ... done!"
+
+ if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
+ sys.stderr.write(red("The following binaries are not available for merging...\n"))
+ for x in mydepgraph.missingbins:
+ sys.stderr.write(" "+str(x)+"\n")
+ sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
+ sys.exit(1)
+
+ alldeps=mydepgraph.digraph.allnodes()
+ myvarlist=portage.vardbapi(portage.root).cp_all()
+
+ if not syslist:
+ print "!!! You have no system list. Cannot determine system from world."
+ if not worldlist:
+ print "!!! You have no world file. Cannot determine explicit merges."
+ if not myvarlist:
+ print "!!! You have no installed package tree (%s). This is a problem." % portage.VDB_PATH
+ if not alldeps:
+ print "!!! You have no dependencies. Impossible. Bug."
+
+ if not (syslist and worldlist and myvarlist and alldeps):
+ print
+ sys.exit(1)
+
+ reallist=[]
+ for x in alldeps:
+ myparts=portage.catpkgsplit(string.split(x)[2])
+ if not myparts:
+ sys.stderr.write(
+ red("!!! There appears to be a problem with the following package:\n")+
+ red("!!! "+str(string.split(x)[2])+"\n\n")+
+ "!!! Please ensure that blocking/conflicting packages are not merged."+
+ "!!! 'emerge -p "+str(string.split(x)[2])+"\n\n")
+ if ("--pretend" not in myopts) and ("--ask" not in myopts):
+ countdown(EMERGE_WARNING_DELAY, "*** Continuing")
+ continue
+
+ catpack=myparts[0]+"/"+myparts[1]
+ if catpack not in reallist:
+ reallist.append(catpack)
+
+ cleanlist=[]
+ for x in myvarlist:
+ if x not in reallist:
+ if x not in cleanlist:
+ cleanlist.append(x)
+
+ for x in syslist+worldlist:
+ myparts = portage.catpkgsplit(x)
+ if myparts:
+ if myparts[0][0] in ('<','>','='):
+ myparts[0] = myparts[0][1:]
+ if myparts[0][0] in ('<','>','='):
+ myparts[0] = myparts[0][1:]
+ catpack=myparts[0]+"/"+myparts[1]
+ else:
+ catpack=x
+ if catpack in cleanlist:
+ cleanlist.remove(catpack)
+
+ #print "\n\n\nCleaning: "
+ #for x in cleanlist:
+ # print x
+ #print
+
+ if len(cleanlist):
+ unmerge("unmerge", cleanlist)
+
+ print
+ print "Packages installed: "+str(len(myvarlist))
+ print "Packages in world: "+str(len(worldlist))
+ print "Packages in system: "+str(len(syslist))
+ print "Unique package names: "+str(len(reallist))
+ print "Required packages: "+str(len(alldeps))
+ if "--pretend" in myopts:
+ print "Number to remove: "+str(len(cleanlist))
+ else:
+ print "Number removed: "+str(len(cleanlist))
+ post_emerge()
+
+# "update", "system", or just process files:
+else:
+ favorites=[]
+ syslist=getlist("system")
+ if (("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts)) or ("--ask" in myopts):
+ if "--tree" in myopts:
+ print
+ print darkgreen("These are the packages that I would merge, in reverse order:")
+ print
+ else:
+ print
+ print darkgreen("These are the packages that I would merge, in order:")
+ print
+
+ if ("--resume" in myopts) and portage.mtimedb.has_key("resume"):
+ myresumeopts=portage.mtimedb["resume"]["myopts"][:]
+
+ while "--skipfirst" in myresumeopts:
+ myresumeopts.remove("--skipfirst")
+ while "--ask" in myresumeopts:
+ myresumeopts.remove("--ask")
+
+ for myopt in myopts:
+ if myopt not in myresumeopts:
+ myresumeopts.append(myopt)
+ myopts=myresumeopts
+ mydepgraph=depgraph("resume",myopts)
+ if "--resume" not in myopts:
+ myopts+=["--resume"]
+ else:
+ if ("--resume" in myopts):
+ del myopts[myopts.index("--resume")]
+ print darkgreen("emerge: It seems we have nothing to resume...")
+ sys.exit(0)
+
+ mydepgraph=depgraph(myaction,myopts)
+ if myaction in ["system","world"]:
+ print "Calculating",myaction,"dependencies ",
+ sys.stdout.flush()
+ if not mydepgraph.xcreate(myaction):
+ print "!!! Depgraph creation failed."
+ sys.exit(1)
+ print "\b\b ...done!"
+ else:
+ if not myfiles:
+ print "emerge: please tell me what to do."
+ help()
+ sys.exit(1)
+ #we don't have any files to process; skip this step and exit
+ print "Calculating dependencies ",
+ sys.stdout.flush()
+ retval,favorites=mydepgraph.select_files(myfiles)
+ if not retval:
+ sys.exit(1)
+ print "\b\b ...done!"
+
+ if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
+ sys.stderr.write(red("The following binaries are not available for merging...\n"))
+
+ if mydepgraph.missingbins:
+ for x in mydepgraph.missingbins:
+ sys.stderr.write(" "+str(x)+"\n")
+ sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
+ sys.exit(1)
+
+ if "--ask" in myopts:
+ if "--resume" in myopts:
+ mydepgraph.display(portage.mtimedb["resume"]["mergelist"])
+ prompt="Do you want me to resume merging these packages?"
+ else:
+ mydepgraph.display(mydepgraph.altlist())
+ mergecount=0
+ for x in mydepgraph.altlist():
+ if x[3]!="nomerge":
+ mergecount+=1
+ #check for blocking dependencies
+ if x[0]=="blocks":
+ print "\n!!! Error: The above package list contains packages which cannot be installed"
+ print "!!! on the same system."
+ print
+ sys.exit(1)
+ if mergecount==0:
+ if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]:
+ prompt="Nothing to merge; do you want me to auto-clean packages?"
+ else:
+ print
+ print "Nothing to merge; quitting."
+ print
+ sys.exit(0)
+ elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+ prompt="Do you want me to fetch the source files for these packages?"
+ else:
+ prompt="Do you want me to merge these packages?"
+ print
+ if userquery(prompt)=="No":
+ print
+ print "Quitting."
+ print
+ sys.exit(0)
+ # Don't ask again (e.g. when auto-cleaning packages after merge)
+ myopts.remove("--ask")
+
+ if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+ if ("--resume" in myopts):
+ mydepgraph.display(portage.mtimedb["resume"]["mergelist"])
+ else:
+ mydepgraph.display(mydepgraph.altlist())
+ else:
+ if ("--buildpkgonly" in myopts):
+ if not mydepgraph.digraph.hasallzeros():
+ print "\n!!! --buildpkgonly requires all dependencies to be merged."
+ print "!!! Cannot merge requested packages. Merge deps and try again.\n"
+ sys.exit(1)
+
+ if ("--resume" in myopts):
+ favorites=portage.mtimedb["resume"]["favorites"]
+ mydepgraph.merge(portage.mtimedb["resume"]["mergelist"])
+ else:
+ portage.mtimedb["resume"]={}
+ portage.mtimedb["resume"]["myopts"]=myopts
+ portage.mtimedb["resume"]["favorites"]=favorites
+ if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+ for pkgline in mydepgraph.altlist():
+ if pkgline[0]=="ebuild" and pkgline[3]=="merge":
+ y=portage.portdb.findname(pkgline[2])
+ tmpsettings = portage.config(clone=portage.settings)
+ retval=portage.doebuild(y,"digest",portage.root,tmpsettings,edebug,("--pretend" in myopts))
+ mydepgraph.merge(mydepgraph.altlist())
+
+ if portage.mtimedb.has_key("resume"):
+ del portage.mtimedb["resume"]
+ if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]:
+ print ">>> Auto-cleaning packages ..."
+ unmerge("clean", ["world"])
+ post_emerge()
diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
new file mode 100755
index 00000000..024af23e
--- /dev/null
+++ b/bin/emerge-webrsync
@@ -0,0 +1,141 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/Attic/emerge-webrsync,v 1.8.2.4 2005/02/26 11:22:38 carpaski Exp $
+# Author: Karl Trygve Kalleberg <karltk@gentoo.org>
+# Rewritten from the old, Perl-based emerge-webrsync script
+
+GENTOO_MIRRORS="${GENTOO_MIRRORS} $(/usr/lib/portage/bin/portageq gentoo_mirrors)"
+PORTDIR="$(/usr/lib/portage/bin/portageq portdir)"
+FETCHCOMMAND="$(/usr/lib/portage/bin/portageq envvar FETCHCOMMAND)"
+USERLAND="$(/usr/lib/portage/bin/portageq envvar USERLAND)"
+DISTDIR="$(/usr/lib/portage/bin/portageq envvar PORTAGE_TMPDIR)/emerge-webrsync"
+
+if [ ! -d $DISTDIR ] ; then
+ mkdir -p $DISTDIR
+fi
+
+cd "$DISTDIR"
+
+found=0
+if [ "$1" == "-v" ] ; then
+ wgetops=
+else
+ #this sucks. probably better to do 1> /dev/null
+ #that said, waiting on the refactoring.
+ if [ "${FETCHCOMMAND/wget}" != "${FETCHCOMMAND}" ]; then
+ wgetops="-q"
+ elif [ "${FETCHCOMMAND/curl}" != "${FETCHCOMMAND}" ]; then
+ wgetops="-s -f"
+ fi
+fi
+
+if type -p md5sum > /dev/null; then
+ md5_com='md5sum -c "${FILE}.md5sum"'
+elif type -p md5 > /dev/null; then
+ md5_com='[ "$(md5 -q ${FILE})" == "$(cut -d \ -f 1 ${FILE}.md5sum)" ]'
+else
+ echo "warning, unable to do md5 verification of the snapshot!"
+ echo "no suitable md5/md5sum binary was found!"
+ md5_com='true'
+fi
+
+sync_local() {
+ echo Syncing local tree...
+ if ! tar jxf $FILE; then
+ echo "Tar failed to extract the image. Please review the output."
+ echo "Executed command: tar jxf $FILE"
+ exit 1
+ fi
+ rm -f $FILE
+ # Make sure user and group file ownership is root
+ chown -R 0:0 portage
+ cd portage
+ rsync -av --progress --stats --delete --delete-after \
+ --exclude='/distfiles' --exclude='/packages' \
+ --exclude='/local' . ${PORTDIR%%/}
+ cd ..
+ echo "cleaning up"
+ rm -rf portage
+ echo "transferring metadata/cache"
+ emerge metadata
+}
+
+echo "Fetching most recent snapshot"
+
+declare -i attempts=-1
+while (( $attempts < 40 )) ; do
+ attempts=$(( attempts + 1 ))
+
+ #this too, sucks. it works in the interim though.
+ if [ "$USERLAND" == "BSD" ] || [ "$USERLAND" == "Darwin" ] ; then
+ daysbefore=$(expr $(date +"%s") - 86400 \* $attempts)
+ day=$(date -r $daysbefore +"%d")
+ month=$(date -r $daysbefore +"%m")
+ year=$(date -r $daysbefore +"%Y")
+ else
+ day=$(date -d "-$attempts day" +"%d")
+ month=$(date -d "-$attempts day" +"%m")
+ year=$(date -d "-$attempts day" +"%Y")
+ fi
+
+ FILE_ORIG="portage-${year}${month}${day}.tar.bz2"
+
+ echo "Attempting to fetch file dated: ${year}${month}${day}"
+
+ got_md5=0
+
+ if [ ! -e "${FILE_ORIG}.md5sum" ]; then
+ FILE="${FILE_ORIG}.md5sum"
+ for i in $GENTOO_MIRRORS ; do
+ URI="${i}/snapshots/${FILE}"
+ if (eval "$FETCHCOMMAND $wgetops") && [ -s "${FILE}" ]; then
+ got_md5=1
+ break
+ fi
+ done
+ else
+ got_md5=1
+ fi
+ FILE="${FILE_ORIG}"
+
+ if (($got_md5 == 0 )); then
+ echo " --- No md5sum present on the mirror. (Not yet available.)"
+ continue
+ elif [ -s "${FILE}" ]; then
+ if eval "$md5_com"; then
+ echo " === snapshot $FILE is correct, using it"
+ sync_local
+ echo
+ echo " === Snapshot has beed sync'd"
+ echo
+ exit 0
+ else
+ rm $FILE
+ fi
+ fi
+
+ for i in $GENTOO_MIRRORS ; do
+ URI="${i}/snapshots/$FILE"
+ rm -f "$FILE"
+ if (eval "$FETCHCOMMAND $wgetops") && [ -s "$FILE" ]; then
+ if ! eval "$md5_com"; then
+ echo "md5 failed on $FILE"
+ rm ${FILE}
+ continue
+ else
+ sync_local
+ echo
+ echo " *** Completed websync, please now perform a normal rsync if possible."
+ echo " Update is current as of the of YYYYMMDD: ${year}${month}${day}"
+ echo
+ exit 0
+ fi
+ fi
+
+ done
+done
+
+rm -rf portage
+
+exit 1
diff --git a/bin/emerge.orig b/bin/emerge.orig
new file mode 100755
index 00000000..c66f32ea
--- /dev/null
+++ b/bin/emerge.orig
@@ -0,0 +1,3227 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/emerge,v 1.345.2.33 2005/06/02 00:57:52 vapier Exp $
+
+import os,sys
+os.environ["PORTAGE_CALLER"]="emerge"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage
+
+import emergehelp,xpak,string,re,commands,time,shutil,traceback,atexit,signal,socket,types
+from stat import *
+from output import *
+
+import portage_util
+import portage_locks
+import portage_exception
+
+
+spinner_msgs = ["Gentoo Rocks ("+os.uname()[0]+")",
+ "Thank you for using Gentoo. :)",
+ "Are you actually trying to read this?",
+ "How many times have you stared at this?",
+ "We are generating the cache right now",
+ "You are paying too much attention.",
+ "A theory is better than its explanation.",
+ "Phasers locked on target, Captain.",
+ "Thrashing is just virtual crashing.",
+ "To be is to program.",
+ "Real Users hate Real Programmers.",
+ "When all else fails, read the instructions.",
+ "Functionality breeds Contempt.",
+ "The future lies ahead.",
+ "3.1415926535897932384626433832795028841971694",
+ "Sometimes insanity is the only alternative.",
+ "Inaccuracy saves a world of explanation.",
+ ]
+
+
+def update_basic_spinner():
+ global spinner, spinpos
+ spinpos = (spinpos+1) % 500
+ if (spinpos % 100) == 0:
+ if spinpos == 0:
+ sys.stdout.write(". ")
+ else:
+ sys.stdout.write(".")
+ sys.stdout.flush()
+
+def update_scroll_spinner():
+ global spinner, spinpos
+ if(spinpos >= len(spinner)):
+ sys.stdout.write(darkgreen(" \b\b\b"+spinner[len(spinner)-1-(spinpos%len(spinner))]))
+ else:
+ sys.stdout.write(green("\b "+spinner[spinpos]))
+ sys.stdout.flush()
+ spinpos = (spinpos+1) % (2*len(spinner))
+
+def update_twirl_spinner():
+ global spinner, spinpos
+ spinpos = (spinpos+1) % len(spinner)
+ sys.stdout.write("\b\b "+spinner[spinpos])
+ sys.stdout.flush()
+
+spinpos = 0
+spinner = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
+update_spinner = update_twirl_spinner
+if "candy" in portage.settings.features:
+ spinner = spinner_msgs[int(time.time()*100)%len(spinner_msgs)]
+ update_spinner = update_scroll_spinner
+if not sys.stdout.isatty() or ("--nospinner" in sys.argv):
+ update_spinner = update_basic_spinner
+
+
+if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]):
+ nocolor()
+
+def normpath(mystr):
+ if mystr and (mystr[0]=='/'):
+ return os.path.normpath("///"+mystr)
+ else:
+ return os.path.normpath(mystr)
+
+def userquery(prompt, responses=None, colours=None):
+ """Displays a prompt and a set of responses, then waits for a response
+ which is checked against the responses and the first to match is
+ returned.
+
+ prompt: a String.
+ responses: a List of Strings.
+ colours: a List of Functions taking and returning a String, used to
+ process the responses for display. Typically these will be functions
+ like red() but could be e.g. lambda x: "DisplayString".
+ If responses is omitted, defaults to ["Yes, "No"], [green, red].
+ If only colours is omitted, defaults to [bold, ...].
+
+ Returns a member of the List responses. (If called without optional
+ arguments, returns "Yes" or "No".)
+ KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
+ printed."""
+ if responses is None:
+ responses, colours = ["Yes", "No"], [green, red]
+ elif colours is None:
+ colours=[bold]
+ colours=(colours*len(responses))[:len(responses)]
+ print bold(prompt),
+ try:
+ while True:
+ response=raw_input("["+string.join([colours[i](responses[i]) for i in range(len(responses))],"/")+"] ")
+ for key in responses:
+ if response.upper()==key[:len(response)].upper():
+ return key
+ print "Sorry, response '%s' not understood." % response,
+ except (EOFError, KeyboardInterrupt):
+ print "Interrupted."
+ sys.exit(1)
+
+def sorted_versions(verlist):
+ ret = []
+ for ver in verlist:
+ verparts = ver.split("-")
+ if len(verparts) == 2:
+ verrev = int(verparts[1][1:])
+ else:
+ verrev = 0
+ x = 0
+ while x < len(ret):
+ retparts = ret[x].split("-")
+ verdiff = portage.vercmp(retparts[0], verparts[0])
+ if verdiff > 0:
+ break
+ elif verdiff == 0:
+ if len(retparts) == 2:
+ retrev = int(retparts[1][1:])
+ else:
+ retrev = 0
+ if retrev >= verrev:
+ break
+ x += 1
+ ret.insert(x, ver)
+ return ret
+
+if portage.settings.has_key("PORTAGE_NICENESS"):
+ try:
+ os.nice(int(portage.settings["PORTAGE_NICENESS"]))
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception,e:
+ print "!!! Failed to change nice value to '"+str(portage.settings["PORTAGE_NICENESS"])+"'"
+ print "!!!",e
+
+#Freeze the portdbapi for enhanced performance:
+portage.portdb.freeze()
+
+# Kill noauto as it will break merges otherwise.
+while 'noauto' in portage.features:
+ del portage.features[portage.features.index('noauto')]
+
+#number of ebuilds merged
+merged=0
+params=["selective", "deep", "self", "recurse", "empty"]
+actions=[
+"clean", "config", "depclean",
+"info", "inject", "metadata",
+"prune", "regen", "rsync", "search",
+"sync", "system", "unmerge", "world",
+]
+options=[
+"--ask",
+"--buildpkg", "--buildpkgonly",
+"--changelog", "--columns",
+"--debug", "--deep",
+"--digest",
+"--emptytree",
+"--fetchonly", "--fetch-all-uri",
+"--getbinpkg", "--getbinpkgonly",
+"--help", "--noconfmem",
+"--newuse", "--nocolor",
+"--nodeps", "--noreplace",
+"--nospinner", "--oneshot",
+"--onlydeps", "--pretend",
+"--quiet", "--resume",
+"--searchdesc", "--selective",
+"--skipfirst",
+"--tree",
+"--update", "--upgradeonly",
+"--usepkg", "--usepkgonly",
+"--verbose", "--version"
+]
+
+shortmapping={
+"1":"--oneshot",
+"a":"--ask",
+"b":"--buildpkg", "B":"--buildpkgonly",
+"c":"--clean", "C":"--unmerge",
+"d":"--debug", "D":"--deep",
+"e":"--emptytree",
+"f":"--fetchonly", "F":"--fetch-all-uri",
+"g":"--getbinpkg", "G":"--getbinpkgonly",
+"h":"--help",
+"i":"--inject",
+"k":"--usepkg", "K":"--usepkgonly",
+"l":"--changelog",
+"n":"--noreplace", "N":"--newuse",
+"o":"--onlydeps", "O":"--nodeps",
+"p":"--pretend", "P":"--prune",
+"q":"--quiet",
+"s":"--search", "S":"--searchdesc",
+'t':"--tree",
+"u":"--update", "U":"--upgradeonly",
+"v":"--verbose", "V":"--version"
+}
+
+myaction=None
+myopts=[]
+myfiles=[]
+edebug=0
+
+# process short actions
+tmpcmdline=sys.argv[1:]
+#tmpcmdline.extend(portage.settings["EMERGE_OPTS"].split())
+cmdline=[]
+for x in tmpcmdline:
+ if x[0:1]=="-"and x[1:2]!="-":
+ for y in x[1:]:
+ if shortmapping.has_key(y):
+ if shortmapping[y] in cmdline:
+ print
+ print "*** Warning: Redundant use of",shortmapping[y]
+ else:
+ cmdline.append(shortmapping[y])
+ else:
+ print "!!! Error: -"+y+" is an invalid short action or option."
+ sys.exit(1)
+ else:
+ cmdline.append(x)
+
+# process the options and command arguments
+for x in cmdline:
+ if not x:
+ continue
+ if len(x)>=2 and x[0:2]=="--":
+ if x in options:
+ myopts.append(x)
+ elif x[2:] in actions:
+ if x[2:]=="rsync" or x=="rsync":
+ # "emerge --rsync"
+ print
+ print red("*** '--rsync' has been deprecated.")
+ print red("*** Please use '--sync' instead.")
+ print
+ x="--sync"
+ if myaction:
+ if myaction not in ["system", "world"]:
+ myaction="--"+myaction
+ print
+ print red("!!!")+green(" Multiple actions requested... Please choose one only.")
+ print red("!!!")+" '"+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
+ print
+ sys.exit(1)
+ myaction=x[2:]
+ else:
+ print "!!! Error:",x,"is an invalid option."
+ sys.exit(1)
+ elif (not myaction) and (x in actions):
+ if x not in ["system", "world"]:
+ #print red("*** Deprecated use of action '"+x+"'")
+ if x=="rsync":
+ # "emerge rsync"
+ print
+ print red("*** 'rsync' will now install the package rsync.")
+ print red("*** To sync the tree, please use '--sync' instead.")
+ print
+ myfiles.append(x)
+ continue
+ if myaction:
+ print
+ print red("!!!")+green(" Multiple actions requested... Please choose one only.")
+ print red("!!! '")+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
+ print
+ sys.exit(1)
+ myaction=x
+ elif x[-1]=="/":
+ # this little conditional helps tab completion
+ myfiles.append(x[:-1])
+ else:
+ myfiles.append(x)
+
+
+if "moo" in myfiles:
+ print """
+
+ Gentoo (""" + os.uname()[0] + """)
+
+ _______________________
+< Have you mooed today? >
+ -----------------------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+
+"""
+
+if (myaction in ["world", "system"]) and myfiles:
+ print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
+ sys.exit(1)
+
+for x in myfiles:
+ if (x[-7:] == ".ebuild" or x[-5:] == ".tbz2") and os.path.exists(os.path.abspath(x)):
+ print "emerging by path implies --oneshot... adding --oneshot to options."
+ print red("\n*** emerging by path is broken and may not always work!!!\n")
+ break
+
+if ("--tree" in myopts) and ("--columns" in myopts):
+ print "emerge: can't specify both of \"--tree\" and \"--columns\"."
+ sys.exit(1)
+
+# Always create packages if FEATURES=buildpkg
+# Imply --buildpkg if --buildpkgonly
+if ("buildpkg" in portage.features) or ("--buildpkgonly" in myopts):
+ if "--buildpkg" not in myopts:
+ myopts.append("--buildpkg")
+
+# --tree only makes sense with --pretend
+if "--tree" in myopts and not (("--pretend" in myopts) or ("--ask" in myopts)):
+ print ">>> --tree implies --pretend... adding --pretend to options."
+ myopts.append("--pretend")
+
+# Also allow -S to invoke search action (-sS)
+if ("--searchdesc" in myopts):
+ if myaction and myaction != "search":
+ myfiles.append(myaction)
+ if "--search" not in myopts:
+ myopts.append("--search")
+ myaction = "search"
+
+# Always try and fetch binary packages if FEATURES=getbinpkg
+if ("getbinpkg" in portage.features):
+ myopts.append("--getbinpkg")
+
+if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
+ myopts.append("--usepkgonly")
+
+if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
+ myopts.append("--getbinpkg")
+
+if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
+ myopts.append("--usepkg")
+
+# Also allow -K to apply --usepkg/-k
+if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
+ myopts.append("--usepkg")
+
+# Print deprecation warning for -U
+if ("--upgradeonly" in myopts):
+ print
+ print red("*** Warning: --upgradeonly is a deprecated option in portage-"+portage.VERSION)
+ print red("*** and will likely be removed in a future version.")
+ print
+ # Also allow -U to apply --update/-u
+ if not ("--update" in myopts):
+ print ">>> --upgradeonly implies --update... adding --update to options."
+ myopts.append("--update")
+
+# Also allow -l to apply --pretend/-p, but if already in --ask mode
+if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
+ print ">>> --changelog implies --pretend... adding --pretend to options."
+ myopts.append("--pretend")
+
+# Allow -p to remove --ask
+if ("--pretend" in myopts) and ("--ask" in myopts):
+ print ">>> --pretend disables --ask... removing --ask from options."
+ myopts.remove("--ask")
+
+# forbid --ask when not in a terminal
+# note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
+if ("--ask" in myopts) and (not sys.stdin.isatty()):
+ portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n")
+ sys.exit(1)
+
+# Set so that configs will be merged regardless of remembered status
+if ("--noconfmem" in myopts):
+ portage.settings.unlock()
+ portage.settings["NOCONFMEM"]="1"
+ portage.settings.backup_changes("NOCONFMEM")
+ portage.settings.lock()
+
+# Set various debug markers... They should be merged somehow.
+if ("--debug" in myopts):
+ portage.settings.unlock()
+ portage.settings["PORTAGE_DEBUG"]="1"
+ portage.settings.backup_changes("PORTAGE_DEBUG")
+ portage.debug=1
+ portage.settings.lock()
+
+if ("--resume" in myopts):
+ if "--verbose" in myopts:
+ print "* --verbose is currently broken with --resume. Disabling..."
+ myopts.remove("--verbose")
+ if "--tree" in myopts:
+ print "* --tree is currently broken with --resume. Disabling..."
+ myopts.remove("--tree")
+
+# Set color output
+if ("--nocolor" in myopts) and (sys.stdout.isatty()):
+ nocolor()
+
+CLEAN_DELAY = 5
+EMERGE_WARNING_DELAY = 10
+if portage.settings["CLEAN_DELAY"]:
+ CLEAN_DELAY = string.atoi("0"+portage.settings["CLEAN_DELAY"])
+if portage.settings["EMERGE_WARNING_DELAY"]:
+ EMERGE_WARNING_DELAY = string.atoi("0"+portage.settings["EMERGE_WARNING_DELAY"])
+
+if "inject" == myaction:
+ print
+ print red("*** --inject has been deprecated.")
+ print red("*** If you manage a piece of software yourself, add it's name and")
+ print red("*** version (eg foo/bar-1.0) to /etc/portage/profile/package.provided.")
+ print red("*** If you want to prevent portage from upgrading a package, add it to")
+ print red("*** /etc/portage/package.mask prepending it with '>' (eg >foo/bar-1.0)")
+ print red("*** For more information on fine-grained portage control, please see")
+ print red("*** the portage man page.")
+ print
+
+def emergelog(mystr,short_msg=None):
+ if "notitles" not in portage.features:
+ if short_msg:
+ xtermTitle(short_msg)
+ else:
+ xtermTitle(mystr)
+ try:
+ #seems odd opening a file each write...
+ if not os.path.exists("/var/log/emerge.log"):
+ mylogfile=open("/var/log/emerge.log", "w")
+ os.chmod("/var/log/emerge.log", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+ os.chown("/var/log/emerge.log", portage.portage_uid, portage.portage_gid)
+ else:
+ mylogfile=open("/var/log/emerge.log", "a")
+
+ l=portage_locks.lockfile(mylogfile)
+ # seek because we may have gotten held up by the lock.
+ # if so, we may not be positioned at the end of the file.
+ mylogfile.seek(0,2)
+ mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
+ mylogfile.flush()
+ portage_locks.unlockfile(l)
+ mylogfile.close()
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ if edebug:
+ print "emergelog():",e
+ pass
+
+def emergeexit():
+ """This gets out final log message in before we quit."""
+ if "--pretend" not in myopts:
+ emergelog(" *** terminating.")
+ if "notitles" not in portage.features:
+ xtermTitleReset()
+atexit.register(emergeexit)
+
+def emergeexitsig(signum, frame):
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ portage.portageexit()
+ portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
+ sys.exit(100+signum)
+signal.signal(signal.SIGINT, emergeexitsig)
+
+def countdown(secs=5, doing="Starting"):
+ if secs:
+ print ">>> Waiting",secs,"seconds before starting..."
+ print ">>> (Control-C to abort)...\n"+doing+" in: ",
+ ticks=range(secs)
+ ticks.reverse()
+ for sec in ticks:
+ sys.stdout.write(red(str(sec+1)+" "))
+ sys.stdout.flush()
+ time.sleep(1)
+ print
+
+# formats a size given in bytes nicely
+def format_size(mysize):
+ if type(mysize) not in [types.IntType,types.LongType]:
+ return str(mysize)
+ mystr=str(mysize/1024)
+ mycount=len(mystr)
+ while (mycount > 3):
+ mycount-=3
+ mystr=mystr[:mycount]+","+mystr[mycount:]
+ return mystr+" kB"
+
+
+def getgccversion():
+ """
+ rtype: C{str}
+ return: the current in-use gcc version
+ """
+
+ gcc_env_dir = os.path.join('/', 'etc', 'env.d', 'gcc')
+ gcc_config_config = os.path.join(gcc_env_dir, 'config')
+ gcc_ver_command = 'gcc -dumpversion'
+ gcc_ver_prefix = 'gcc-'
+
+ gcc_not_found_error = red(
+ "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
+ "!!! to update the environment of this terminal and possibly\n" +
+ "!!! other terminals also."
+ )
+
+ gcc_distcc_broken_error = green(
+ '!!! Relying on the shell to locate gcc, this may break\n' +
+ '!!! DISTCC, installing gcc-config and setting your current gcc\n' +
+ '!!! profile will fix this'
+ )
+
+ def fallback():
+
+ print >>sys.stderr, gcc_distcc_broken_error
+
+ gccout = commands.getstatusoutput(gcc_ver_command)
+
+ if gccout[0] != 0:
+ print >>sys.stderr, gcc_not_found_error
+ gccver = "[unavailable]"
+ else:
+ gccver = gcc_ver_prefix + gccout[1]
+
+ return gccver
+
+ if os.path.isfile(gcc_config_config):
+ try:
+ gccver_str = open(gcc_config_config).read().strip()
+ gccver = gcc_ver_prefix + string.join(gccver_str.split('-')[4:], '-')
+ except IndexError:
+ gccver = fallback()
+
+ else:
+ import glob
+ dir_l = glob.glob(os.path.join(gcc_env_dir, '*-*'))
+
+ if len(dir_l) == 1:
+ try:
+ gccver = gcc_ver_prefix + dir_l[0].split('-')[-1]
+ except IndexError:
+ gccver = fallback()
+
+ else:
+ # There was no "config" file in /etc/env.d/gcc and there was more
+ # than one profile in /etc/env.d/gcc so we can't actively
+ # determine what version of gcc we are using so we fall back on the
+ # old way that breaks distcc
+
+ gccver = fallback()
+
+ return gccver
+
+def getportageversion():
+ try:
+ import re
+ profilever = os.path.normpath("///"+os.readlink("/etc/make.profile"))
+ basepath = os.path.normpath("///"+portage.settings["PORTDIR"]+"/profiles")
+ if re.match(basepath,profilever):
+ profilever = profilever[len(basepath)+1:]
+ else:
+ profilever = "!"+profilever
+ del basepath
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ profilever="unavailable"
+ libcver=[]
+ libclist = portage.vardbapi(portage.root).match("virtual/libc")
+ libclist += portage.vardbapi(portage.root).match("virtual/glibc")
+ libclist = portage_util.unique_array(libclist)
+ for x in libclist:
+ xs=portage.catpkgsplit(x)
+ if libcver:
+ libcver+=","+string.join(xs[1:], "-")
+ else:
+ libcver=string.join(xs[1:], "-")
+ if libcver==[]:
+ libcver="unavailable"
+
+ gccver = getgccversion()
+ unameout=os.uname()[2]+" "+os.uname()[4]
+
+ return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
+
+def help():
+ # Move all the help stuff out of this file.
+ emergehelp.help(myaction,myopts,havecolor)
+
+# check if root user is the current user for the actions where emerge needs this
+if ("--pretend" in myopts) or ("--fetchonly" in myopts or "--fetch-all-uri" in myopts) or (myaction=="search"):
+ if not portage.secpass:
+ if portage.wheelgid==portage.portage_gid:
+ print "emerge: wheel group membership required for \"--pretend\" and search."
+ print "emerge: wheel group use is being deprecated. Please update group and passwd to"
+ print " include the portage user as noted above, and then use group portage."
+ else:
+ print "emerge: portage group membership required for \"--pretend\" and search."
+ sys.exit(1)
+elif "--version" in myopts:
+ print getportageversion()
+ sys.exit(0)
+elif "--help" in myopts:
+ help()
+ sys.exit(0)
+elif portage.secpass!=2:
+ if myaction in ["search", "info", "regen"]:
+ pass
+ elif (not myaction) and (not myfiles):
+ pass
+ elif ("--pretend" in myopts) and (myaction in ["world","system","clean","prune","unmerge"]):
+ pass
+ else:
+ if "--debug" in myopts:
+ print "myaction",myaction
+ print "myopts",myopts
+ print "emerge: root access required."
+ sys.exit(1)
+
+if not "--pretend" in myopts:
+ emergelog("Started emerge on: "+time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
+ myelogstr=""
+ if myopts:
+ myelogstr=string.join(myopts, " ")
+ if myaction:
+ myelogstr+=" "+myaction
+ if myfiles:
+ myelogstr+=" "+string.join(myfiles, " ")
+ emergelog(" *** emerge "+myelogstr)
+
+#configure emerge engine parameters
+#
+# self: include _this_ package regardless of if it is merged.
+# selective: exclude the package if it is merged
+# recurse: go into the dependencies
+# empty: pretend nothing is merged
+myparams=["self","recurse"]
+add=[]
+sub=[]
+if "--update" in myopts:
+ add.extend(["selective","empty"])
+if "--emptytree" in myopts:
+ add.extend(["empty"])
+ sub.extend(["selective"])
+if "--nodeps" in myopts:
+ sub.extend(["recurse"])
+if "--noreplace" in myopts:
+ add.extend(["selective"])
+if "--deep" in myopts:
+ add.extend(["deep"])
+if "--selective" in myopts:
+ add.extend(["selective"])
+if myaction in ["world","system"]:
+ add.extend(["selective"])
+elif myaction in ["depclean"]:
+ add.extend(["empty"])
+ sub.extend(["selective"])
+for x in add:
+ if (x not in myparams) and (x not in sub):
+ myparams.append(x)
+for x in sub:
+ if x in myparams:
+ myparams.remove(x)
+
+# search functionality
+class search:
+
+ #
+ # class constants
+ #
+ VERSION_SHORT=1
+ VERSION_RELEASE=2
+
+ #
+ # public interface
+ #
+ def __init__(self):
+ """Searches the available and installed packages for the supplied search key.
+ The list of available and installed packages is created at object instantiation.
+ This makes successive searches faster."""
+ self.installcache = portage.db["/"]["vartree"]
+
+ def execute(self,searchkey):
+ """Performs the search for the supplied search key"""
+ global myopts
+ match_category = 0
+ self.searchkey=searchkey
+ self.packagematches = []
+ if "--searchdesc" in myopts:
+ self.searchdesc=1
+ self.matches = {"pkg":[], "desc":[]}
+ else:
+ self.searchdesc=0
+ self.matches = {"pkg":[]}
+ print "Searching... ",
+
+ if self.searchkey[0] == '@':
+ match_category = 1
+ self.searchkey = self.searchkey[1:]
+ if self.searchkey=="*":
+ #hack for people who aren't regular expression gurus
+ self.searchkey==".*"
+ if re.search("\+\+", self.searchkey):
+ #hack for people who aren't regular expression gurus
+ self.searchkey=re.sub("\+\+","\+\+",self.searchkey)
+ self.searchre=re.compile(self.searchkey.lower(),re.I)
+ for package in portage.portdb.cp_all():
+ update_spinner()
+
+ if match_category:
+ match_string = package[:]
+ else:
+ match_string = package.split("/")[-1]
+
+ masked=0
+ if self.searchre.search(match_string):
+ if not portage.portdb.xmatch("match-visible",package):
+ masked=1
+ self.matches["pkg"].append([package,masked])
+ elif self.searchdesc: # DESCRIPTION searching
+ full_package = portage.portdb.xmatch("bestmatch-visible",package)
+ if not full_package:
+ #no match found; we don't want to query description
+ full_package=portage.best(portage.portdb.xmatch("match-all",package))
+ if not full_package:
+ continue
+ else:
+ masked=1
+ try:
+ full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0]
+ except KeyError:
+ print "emerge: search: aux_get() failed, skipping"
+ continue
+ if self.searchre.search(full_desc):
+ self.matches["desc"].append([full_package,masked])
+ self.mlen=0
+ for mtype in self.matches.keys():
+ self.matches[mtype].sort()
+ self.mlen += len(self.matches[mtype])
+
+ def output(self):
+ """Outputs the results of the search."""
+ print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]"
+ print "[ Applications found : "+white(str(self.mlen))+" ]"
+ print " "
+ for mtype in self.matches.keys():
+ for match,masked in self.matches[mtype]:
+ if mtype=="pkg":
+ catpack=match
+ full_package = portage.portdb.xmatch("bestmatch-visible",match)
+ if not full_package:
+ #no match found; we don't want to query description
+ masked=1
+ full_package=portage.best(portage.portdb.xmatch("match-all",match))
+ else:
+ full_package = match
+ match = portage.pkgsplit(match)[0]
+
+ if full_package:
+ try:
+ desc, homepage, license = portage.portdb.aux_get(full_package,["DESCRIPTION","HOMEPAGE","LICENSE"])
+ except KeyError:
+ print "emerge: search: aux_get() failed, skipping"
+ continue
+ if masked:
+ print green("*")+" "+white(match)+" "+red("[ Masked ]")
+ else:
+ print green("*")+" "+white(match)
+ myversion = self.getVersion(full_package, search.VERSION_RELEASE)
+
+ mysum = [0,0]
+ mycat = match.split("/")[0]
+ mypkg = match.split("/")[1]
+
+ mydigest = portage.db["/"]["porttree"].dbapi.finddigest(mycat+"/"+mypkg + "-" + myversion)
+
+ try:
+ myfile = open(mydigest,"r")
+ for line in myfile.readlines():
+ mysum[0] += int(line.split(" ")[3])
+ myfile.close()
+ mystr = str(mysum[0]/1024)
+ mycount=len(mystr)
+ while (mycount > 3):
+ mycount-=3
+ mystr=mystr[:mycount]+","+mystr[mycount:]
+ mysum[0]=mystr+" kB"
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ if edebug:
+ print "!!! Exception:",e
+ mysum[0]=" [no/bad digest]"
+
+ if "--quiet" not in myopts:
+ print " ", darkgreen("Latest version available:"),myversion
+ print " ", self.getInstallationStatus(mycat+'/'+mypkg)
+ print " ", darkgreen("Size of downloaded files:"),mysum[0]
+ print " ", darkgreen("Homepage:")+" ",homepage
+ print " ", darkgreen("Description:"),desc
+ print " ", darkgreen("License:")+" ",license
+ print
+ print
+ #
+ # private interface
+ #
+ def getInstallationStatus(self,package):
+ installed_package = self.installcache.dep_bestmatch(package)
+ result = ""
+ version = self.getVersion(installed_package,search.VERSION_RELEASE)
+ if len(version) > 0:
+ result = darkgreen("Latest version installed:")+" "+version
+ else:
+ result = darkgreen("Latest version installed:")+" [ Not Installed ]"
+ return result
+
+ def getVersion(self,full_package,detail):
+ if len(full_package) > 1:
+ package_parts = portage.catpkgsplit(full_package)
+ if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
+ result = package_parts[2]+ "-" + package_parts[3]
+ else:
+ result = package_parts[2]
+ else:
+ result = ""
+ return result
+
+
+#build our package digraph
+def getlist(mode):
+ if mode=="system":
+ mylines=portage.settings.packages
+ elif mode=="world":
+ try:
+ myfile=open(portage.root+portage.WORLD_FILE,"r")
+ mylines=myfile.readlines()
+ myfile.close()
+ except OSError:
+ print "!!! Couldn't open "+pfile+"; exiting."
+ sys.exit(1)
+ except IOError:
+ #world file doesn't exist
+ mylines=[]
+ mynewlines=[]
+ for x in mylines:
+ myline=string.join(string.split(x))
+ if not len(myline):
+ continue
+ elif myline[0]=="#":
+ continue
+ elif mode=="system":
+ if myline[0]!="*":
+ continue
+ myline=myline[1:]
+ mynewlines.append(myline.strip())
+
+ # Remove everything that is package.provided from our list
+ for myatom in mynewlines[:]:
+ mykey = portage.dep_getkey(myatom)
+ if portage.settings.pprovideddict.has_key(mykey) and \
+ portage.match_from_list(myatom, portage.settings.pprovideddict[mykey]):
+ mynewlines.remove(myatom)
+
+ return mynewlines
+
+def genericdict(mylist):
+ mynewdict={}
+ for x in mylist:
+ mynewdict[portage.dep_getkey(x)]=x
+ return mynewdict
+
+olddbapi=None
+class depgraph:
+
+ def __init__(self,myaction,myopts):
+ global olddbapi
+ self.pkgsettings = portage.config(clone=portage.settings)
+ if not self.pkgsettings["ARCH"]:
+ portage.writemsg(red("\a!!! ARCH is not set... Are you missing the /etc/make.profile symlink?\n"))
+ portage.writemsg(red("\a!!! Is the symlink correct? Is your portage tree complete?\n\n"))
+ sys.exit(9)
+ self.applied_useflags = {}
+
+ self.missingbins=[]
+ self.myaction=myaction
+ self.digraph=portage.digraph()
+ self.orderedkeys=[]
+ self.outdatedpackages=[]
+ self.mydbapi={}
+ self.mydbapi["/"] = portage.fakedbapi()
+ if "empty" not in myparams:
+ for pkg in portage.db["/"]["vartree"].getallcpv():
+ self.mydbapi["/"].cpv_inject(pkg)
+ if portage.root != "/":
+ self.mydbapi[portage.root] = portage.fakedbapi()
+ if "empty" not in myparams:
+ for pkg in portage.db[portage.root]["vartree"].getallcpv():
+ self.mydbapi[portage.root].cpv_inject(pkg)
+
+ if "--usepkg" in myopts:
+ portage.db["/"]["bintree"].populate(("--getbinpkg" in myopts), ("--getbinpkgonly" in myopts))
+
+ def create(self,mybigkey,myparent=None,addme=1,myuse=None):
+ """creates the actual digraph of packages to merge. return 1 on success, 0 on failure
+ mybigkey = specification of package to merge; myparent = parent package (one depending on me);
+ addme = should I be added to the tree? (for the --onlydeps mode)"""
+ #stuff to add:
+ #SLOT-aware emerge
+ #IUSE-aware emerge
+ #"no downgrade" emerge
+ #print "mybigkey:",mybigkey
+
+ jbigkey=string.join(mybigkey)
+ if self.digraph.hasnode(jbigkey+" merge") or self.digraph.hasnode(jbigkey+" nomerge"):
+ #this conditional is needed to prevent infinite recursion on already-processed deps
+ return 1
+
+ update_spinner()
+
+ mytype,myroot,mykey=mybigkey
+ # select the correct /var database that we'll be checking against
+ vardbapi=portage.db[myroot]["vartree"].dbapi
+
+ if addme:
+ # if the package is already on the system, we add a "nomerge"
+ # directive, otherwise we add a "merge" directive.
+ if mytype=="blocks":
+ # we've encountered a "blocks" node. We will totally ignore this
+ # node and not add it to our digraph if it doesn't apply to us.
+ if "--buildpkgonly" not in myopts and myparent and (self.mydbapi[myroot].match(mykey) or vardbapi.match(mykey)):
+ mybigkey.append(myparent.split()[2])
+ self.digraph.addnode(string.join(mybigkey),myparent)
+ return 1
+
+ if myuse == None:
+ self.pkgsettings.setcpv(mykey)
+ myuse=string.split(self.pkgsettings["USE"], " ")
+
+ self.applied_useflags[mykey] = myuse
+
+ merging=1
+ if addme:
+ # this is where we add the node to the list of packages to merge
+ if not myparent:
+ # command-line specified or part of a world list...
+ if ("self" not in myparams) or (("selective" in myparams) and vardbapi.cpv_exists(mykey)):
+ # the package is on the system, so don't merge it.
+ merging=0
+ elif ("selective" in myparams) and vardbapi.cpv_exists(mykey):
+ merging=0
+
+ if (merging==0 and mytype=="ebuild" and "--newuse" in myopts and vardbapi.cpv_exists(mykey)):
+ iuses=string.split(portage.portdb.aux_get(mykey, ["IUSE"])[0])
+ old_use=string.split(vardbapi.aux_get(mykey, ["USE"])[0])
+ now_use=string.split(self.pkgsettings["USE"])
+ for x in iuses:
+ if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)):
+ merging=1
+ break
+ else:
+ #onlydeps mode; don't merge
+ merging=2
+ if merging==1:
+ mybigkey.append("merge")
+ else:
+ mybigkey.append("nomerge")
+
+ # whatever the case, we need to add the node to our digraph so
+ # that children can depend upon it.
+ self.digraph.addnode(string.join(mybigkey),myparent)
+ if ("deep" not in myparams) and (not merging):
+ return 1
+ elif "recurse" not in myparams:
+ return 1
+
+ edepend={}
+ if mytype=="binary":
+ mypkgparts=portage.catpkgsplit(mykey)
+ tbz2name = string.split(mykey, "/")[1]+".tbz2"
+ if tbz2name in portage.db[portage.root]["bintree"].invalids:
+ sys.stderr.write("\nINVALID PACKAGE (is required to continue): "+str(mykey)+"\n")
+ sys.exit(1)
+ if portage.db[portage.root]["bintree"].isremote(mykey):
+ edepend = portage.db[portage.root]["bintree"].remotepkgs[tbz2name]
+ edepend["DEPEND"] =""
+ edepend["RDEPEND"]=string.join(string.split(edepend["RDEPEND"])," ")
+ edepend["PDEPEND"]=string.join(string.split(edepend["PDEPEND"])," ")
+ edepend["SLOT"] =string.strip(edepend["SLOT"])
+ #portage.db[portage.root]["bintree"].gettbz2(mykey)
+ else: # It's local.
+ mytbz2=xpak.tbz2(portage.db[portage.root]["bintree"].getname(mykey))
+ edepend["DEPEND"] =""
+ edepend["RDEPEND"]=string.join(mytbz2.getelements("RDEPEND")," ")
+ edepend["PDEPEND"]=string.join(mytbz2.getelements("PDEPEND")," ")
+ edepend["SLOT"] =mytbz2.getfile("SLOT",mypkgparts[2])
+ elif mytype=="ebuild":
+ try:
+ mymeta = ["DEPEND","RDEPEND","PDEPEND"]
+ myfoo = portage.portdb.aux_get(mykey, mymeta)
+ for index in range(0,len(mymeta)):
+ edepend[mymeta[index]] = myfoo[index]
+ if "--buildpkgonly" in myopts:
+ edepend["RDEPEND"] = ""
+ except (KeyError,IOError):
+ print "emerge: create(): aux_get() error on",mykey+"; aborting..."
+ sys.exit(1)
+ mydep={}
+ mp=string.join(mybigkey)
+
+ if myroot=="/":
+ mydep["/"]=edepend["DEPEND"]+" "+edepend["RDEPEND"]
+ if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse):
+ return 0
+ else:
+ mydep["/"]=edepend["DEPEND"]
+ mydep[myroot]=edepend["RDEPEND"]
+ if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse):
+ return 0
+ if not self.select_dep(myroot,mydep[myroot],myparent=mp,myuse=myuse):
+ return 0
+
+ if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
+ # Post Depend -- Add to the list without a parent, as it depends
+ # on a package being present AND must be built after that package.
+ if not self.select_dep(myroot,edepend["PDEPEND"],myuse=myuse):
+ return 0
+
+ return 1
+
+ def select_files(self,myfiles):
+ "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
+ myfavorites=[]
+ for x in myfiles:
+ if x[-5:]==".tbz2":
+ if not os.path.exists(x):
+ if os.path.exists(self.pkgsettings["PKGDIR"]+"/All/"+x):
+ x=self.pkgsettings["PKGDIR"]+"/All/"+x
+ elif os.path.exists(self.pkgsettings["PKGDIR"]+"/"+x):
+ x=self.pkgsettings["PKGDIR"]+"/"+x
+ else:
+ print "\n\n!!! Binary package '"+str(x)+"' does not exist."
+ print "!!! Please ensure the tbz2 exists as specified.\n"
+ sys.exit(1)
+ mytbz2=xpak.tbz2(x)
+ mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(x)[:-5]
+ if os.path.realpath(portage.db["/"]["bintree"].getname(mykey)) != os.path.realpath(x):
+ print red("\n*** You need to adjust PKGDIR to emerge this package.\n")
+ sys.exit(1)
+ if not self.create(["binary",portage.root,mykey],None,"--onlydeps" not in myopts):
+ return (0,myfavorites)
+ elif not "--oneshot" in myopts:
+ myfavorites.append(mykey)
+ elif x[-7:]==".ebuild":
+ x = os.path.realpath(x)
+ mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.basename(x)[:-7]
+ ebuild_path = portage.db["/"]["porttree"].dbapi.findname(mykey)
+ if ebuild_path:
+ if os.path.realpath(ebuild_path) != x:
+ print red("\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
+ sys.exit(1)
+ if mykey not in portage.db["/"]["porttree"].dbapi.xmatch("match-visible", portage.dep_getkey(mykey)):
+ print red("\n*** You are emerging a masked package. It is MUCH better to use")
+ print red("*** /etc/portage/package.* to accomplish this. See portage(5) man")
+ print red("*** page for details.")
+ countdown(EMERGE_WARNING_DELAY, "Continuing...")
+ else:
+ print red("\n*** "+x+" does not exist")
+ sys.exit(1)
+ if not self.create(["ebuild",portage.root,mykey],None,"--onlydeps" not in myopts):
+ return (0,myfavorites)
+ elif not "--oneshot" in myopts:
+ myfavorites.append(mykey)
+ else:
+ try:
+ mykey=portage.dep_expand(x,mydb=portage.portdb)
+ except ValueError, errpkgs:
+ print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
+ print "!!! one of the following fully-qualified ebuild names instead:\n"
+ for i in errpkgs[0]:
+ print " " + green(i)
+ print
+ sys.exit(1)
+
+ # select needs to return 0 on dep_check failure
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+
+ try:
+ self.mysd = self.select_dep(portage.root,mykey,arg=x)
+ except portage_exception.MissingSignature, e:
+ portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
+ portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+ portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+ portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n")
+ portage.writemsg("!!! Affected file: %s\n" % (e))
+ sys.exit(1)
+ except portage_exception.InvalidSignature, e:
+ portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
+ portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+ portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+ portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n")
+ portage.writemsg("!!! Affected file: %s\n" % (e))
+ sys.exit(1)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ if "--debug" in myopts:
+ raise
+ print "\n\n!!! Problem in",mykey,"dependencies."
+ print "!!!",str(e),e.__module__
+ sys.exit(1)
+
+ if not self.mysd:
+ return (0,myfavorites)
+ elif not "--oneshot" in myopts:
+ myfavorites.append(mykey)
+
+ missing=0
+ if "--usepkgonly" in myopts:
+ for x in self.digraph.dict.keys():
+ xs=string.split(x," ")
+ if (xs[0] != "binary") and (xs[3]=="merge"):
+ if missing == 0:
+ print
+ missing += 1
+ print "Missing binary for:",xs[2]
+
+ # We're true here unless we are missing binaries.
+ return (not missing,myfavorites)
+
+ def is_newer_ver_installed(self,myroot,pkg,pkgver):
+ "if there is a version of pkg installed newer than pkgver, return it"
+ vardbapi=portage.db[myroot]["vartree"].dbapi
+
+ matches=portage.db[myroot]["vartree"].dbapi.match(pkg)
+ if matches:
+ myslot=portage.db["/"]["porttree"].getslot(pkgver)
+ for match in matches:
+ if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(match)[1:]) < 0:
+ curslot=portage.db[myroot]["vartree"].getslot(match)
+ if curslot == myslot:
+ return match
+
+ def select_dep(self,myroot,depstring,myparent=None,arg=None,myuse=None):
+ "given a dependency string, create the appropriate depgraph and return 1 on success and 0 on failure"
+ if "--debug" in myopts:
+ print
+ print "Parent: ",myparent
+ print "Depstring:",depstring
+ if not arg:
+ #processing dependencies
+ mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse,use_binaries=("--usepkg" in myopts))
+ #mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse)
+
+ if not mycheck[0]:
+ mymerge=[]
+ else:
+ mymerge=mycheck[1]
+
+ else:
+ #we're processing a command-line argument; unconditionally merge it even if it's already merged
+ mymerge=[depstring]
+
+ # dep_check has been run so we can now add our parent to our
+ # build state to update virtuals and other settings. This
+ # happens after the package is added to the tree so that a
+ # package can depend on a virtual which it satisfies.
+ if myparent:
+ myp = myparent.split()
+ if myp[3]=="merge":
+ self.mydbapi[myroot].cpv_inject(myp[2])
+ if myp[0]=="binary":
+ self.pkgsettings.setinst(myp[2],portage.db["/"]["bintree"].dbapi)
+ else:
+ self.pkgsettings.setinst(myp[2],portage.db[myroot]["porttree"].dbapi)
+
+ if not mymerge:
+ return 1
+
+ if "--debug" in myopts:
+ print "Candidates:",mymerge
+ for x in mymerge:
+ myk=None
+ binpkguseflags=None
+ if x[0]=="!":
+ # if this package is myself, don't append it to block list.
+ if "--debug" in myopts:
+ print "Myparent",myparent
+ if (myparent):
+ if myparent.split()[2] in portage.portdb.xmatch("match-all", x[1:]):
+ # myself, so exit.
+ continue
+ # adding block
+ myk=["blocks",myroot,x[1:]]
+ else:
+ #We are not processing a blocker but a normal dependency
+ myeb=None
+ myeb_matches = portage.portdb.xmatch("match-visible",x)
+ if ("--usepkgonly" not in myopts):
+ myeb=portage.best(myeb_matches)
+
+ myeb_pkg=None
+ if ("--usepkg" in myopts):
+ # The next line assumes the binarytree has been populated.
+ # XXX: Need to work out how we use the binary tree with roots.
+ myeb_pkg_matches=portage.db["/"]["bintree"].dbapi.match(x)
+ if ("--usepkgonly" not in myopts):
+ # Remove any binary package entries that are masked in the portage tree (#55871)
+ for idx in range(len(myeb_pkg_matches)-1,-1,-1):
+ if myeb_pkg_matches[idx] not in myeb_matches:
+ del myeb_pkg_matches[idx]
+ myeb_pkg = portage.best(myeb_pkg_matches)
+
+ if not myeb_pkg:
+ myeb_pkg = None
+ elif ("--newuse" in myopts):
+ iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["IUSE"])[0])
+ old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["USE"])[0])
+ self.pkgsettings.setcpv(myeb_pkg)
+ now_use=string.split(self.pkgsettings["USE"])
+ self.pkgsettings.reset()
+ for x in iuses:
+ if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)):
+ myeb_pkg = None
+ break
+
+ if (not myeb) and (not myeb_pkg):
+ if not arg:
+ xinfo='"'+x+'"'
+ else:
+ xinfo='"'+arg+'"'
+ if myparent:
+ xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"])")
+ alleb=portage.portdb.xmatch("match-all",x)
+ if alleb:
+ if "--usepkgonly" not in myopts:
+ print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
+ print "!!! One of the following masked packages is required to complete your request:"
+ oldcomment = ""
+ for p in alleb:
+ mreasons = portage.getmaskingstatus(p)
+ print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")"
+ comment = portage.getmaskingreason(p)
+ if comment and comment != oldcomment:
+ print comment
+ oldcomment = comment
+ print
+ print "For more information, see MASKED PACKAGES section in the emerge man page or "
+ print "section 2.2 \"Software Availability\" in the Gentoo Handbook."
+ if myparent:
+ print "!!! "+red(xfrom)
+ print
+ else:
+ print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
+ print "!!! Either add a suitable binary package or compile from an ebuild."
+ else:
+ print "\nemerge: there are no ebuilds to satisfy "+xinfo+"."
+ if myparent:
+ print xfrom
+ print
+ return 0
+
+ if "--debug" in myopts:
+ print "ebuild:",myeb
+ print "binpkg:",myeb_pkg
+
+ if myeb and myeb_pkg:
+ myeb_s = portage.catpkgsplit(myeb)
+ myeb_s = [myeb_s[0]+"/"+myeb_s[1], myeb_s[2], myeb_s[3]]
+ myeb_pkg_s = portage.catpkgsplit(myeb_pkg)
+ myeb_pkg_s = [myeb_pkg_s[0]+"/"+myeb_pkg_s[1], myeb_pkg_s[2], myeb_pkg_s[3]]
+
+ if portage.pkgcmp(myeb_s, myeb_pkg_s) == 0: # pkg is same version as ebuild
+ myeb = None
+ else:
+ myeb_pkg = None
+
+ if "--upgradeonly" in myopts:
+ # Check that there isn't a newer version of this package already installed
+ cand = None
+ try:
+ # XXX: This can throw an exception if the ebuild doesn't exist
+ if myeb:
+ cand=self.is_newer_ver_installed(myroot,x,myeb)
+ elif myeb_pkg:
+ cand=self.is_newer_ver_installed(myroot,x,myeb_pkg)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "Warning: "+str(e)
+ if cand:
+ myeb=cand
+
+ if myeb:
+ myk=["ebuild",myroot,myeb]
+ elif myeb_pkg:
+ binpkguseflags=portage.db[portage.root]["bintree"].get_use(myeb_pkg)
+ myk=["binary",myroot,myeb_pkg]
+ else:
+ sys.stderr.write("!!! Confused... Don't know what I'm using for dependency info. :(\n")
+ sys.exit(1)
+
+ #if "--usepkg" in myopts:
+ # #If we want to use packages, see if we have a pre-built one...
+ # mypk=portage.db["/"]["bintree"].dbapi.match(x)
+ # if myeb in mypk:
+ # #Use it only if it's exactly the version we want.
+ # myk=["binary",myroot,myeb]
+ # else:
+ # myk=["ebuild",myroot,myeb]
+ #else:
+ # myk=["ebuild",myroot,myeb]
+ if myparent:
+ #we are a dependency, so we want to be unconditionally added
+ if not self.create(myk,myparent,myuse=binpkguseflags):
+ return 0
+ else:
+ #if mysource is not set, then we are a command-line dependency and should not be added
+ #if --onlydeps is specified.
+ if not self.create(myk,myparent,"--onlydeps" not in myopts,myuse=binpkguseflags):
+ return 0
+
+ if "--debug" in myopts:
+ print "Exiting...",myparent
+ return 1
+
+
+ def altlist(self):
+ mygraph=self.digraph.copy()
+ dolist=["/"]
+ retlist=[]
+ for x in portage.db.keys():
+ portage.db[x]["merge"]=[]
+ if x not in dolist:
+ dolist.append(x)
+ while (not mygraph.empty()):
+ mycurkey=mygraph.firstzero()
+ if not mycurkey:
+ print "!!! Error: circular dependencies:"
+ print
+ for x in mygraph.dict.keys():
+ for y in mygraph.dict[x][1]:
+ print y,"depends on",x
+ print
+ sys.exit(1)
+ splitski=string.split(mycurkey)
+ #I'm not sure of the significance of the following lines (vestigal?) so I'm commenting 'em out.
+ #These lines remove already-merged things from our alt-list
+ #if "--update" in myopts:
+ # if not portage.db["/"]["vartree"].exists_specific(splitski[2]):
+ # portage.db["/"]["merge"].append(splitski)
+ #else:
+ portage.db[splitski[1]]["merge"].append(splitski)
+ mygraph.delnode(mycurkey)
+ for x in dolist:
+ for y in portage.db[x]["merge"]:
+ retlist.append(y)
+ return retlist
+
+ def xcreate(self,mode="system"):
+ global syslist
+ if mode=="system":
+ mylist=syslist
+ else:
+ #world mode
+ worldlist=getlist("world")
+ sysdict=genericdict(syslist)
+ worlddict=genericdict(worldlist)
+ #we're effectively upgrading sysdict to contain all new deps from worlddict
+ for x in worlddict.keys():
+ #only add the world node if the package is:
+ #actually installed -- this prevents the remerging of already unmerged packages when we do a world --update;
+ #actually available -- this prevents emerge from bombing out due to no match being found (we want a silent ignore)
+ if "empty" in myparams:
+ if portage.db["/"]["vartree"].dbapi.match(x):
+ sysdict[x]=worlddict[x]
+ elif portage.db[portage.root]["vartree"].dbapi.match(x):
+ #package is installed
+ sysdict[x]=worlddict[x]
+ else:
+ print "\n*** Package in world file is not installed: "+x
+ mylist = sysdict.keys()
+
+ for mydep in mylist:
+ myeb=portage.portdb.xmatch("bestmatch-visible",mydep)
+ if not myeb:
+ #this is an unavailable world entry; just continue
+ continue
+
+ if "--upgradeonly" in myopts:
+ cand=self.is_newer_ver_installed(portage.root,mydep,myeb)
+ if cand:
+ myeb=cand
+
+ #THIS NEXT BUNCH OF CODE NEEDS TO BE REPLACED TO SUPPORT WORLD ANTI-DEPS
+ #if mydep2[0]=="!":, etc.
+ binpkguseflags = None
+ if "--usepkg" in myopts:
+ mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep)
+ if myeb==mypk:
+ myk=["binary",portage.root,mypk]
+ binpkguseflags=portage.db[portage.root]["bintree"].get_use(mypk)
+ if ("--newuse" in myopts):
+ iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["IUSE"])[0])
+ old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["USE"])[0])
+ self.pkgsettings.setcpv(mypk)
+ now_use=string.split(self.pkgsettings["USE"])
+ self.pkgsettings.reset()
+ for x in iuses:
+ if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)):
+ myk=["ebuild",portage.root,myeb]
+ binpkguseflags=None
+ break
+ elif "--usepkgonly" in myopts:
+ if not mypk:
+ self.missingbins += [myeb]
+ myk=["binary",portage.root,myeb]
+ else:
+ myk=["binary",portage.root,mypk]
+ else:
+ myk=["ebuild",portage.root,myeb]
+ else:
+ myk=["ebuild",portage.root,myeb]
+
+ if not self.create(myk,myuse=binpkguseflags):
+ print
+ print "!!! Problem with dependencies under ",myk[0],myk[2]
+ print "!!! Possibly a DEPEND/*DEPEND problem."
+ print
+ return 0
+ return 1
+
+ def match(self,mydep,myroot=portage.root,mykey=None):
+ # support mutual exclusive deps
+ mydep2=mydep
+ if mydep2[0]=="!":
+ mydep2=mydep[1:]
+
+ if mydep[0]=="!":
+ #add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example)
+ myk="blocks "+myroot+" "+mydep2
+ else:
+ myeb=portage.db[portage.root]["porttree"].dep_bestmatch(mydep2)
+ if not myeb:
+ if not mykey:
+ print "\n!!! Error: couldn't find match for",mydep
+ else:
+ print "\n!!! Error: couldn't find match for",mydep,"in",mykey
+ print
+ sys.exit(1)
+
+ if "--usepkg" in myopts:
+ mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep)
+ if myeb==mypk:
+ myk="binary "+portage.root+" "+mypk
+ else:
+ myk="ebuild "+myroot+" "+myeb
+ else:
+ myk="ebuild "+myroot+" "+myeb
+
+ return myk
+
+ def display(self,mylist):
+ changelogs=[]
+ p=[]
+ totalsize=0
+
+ if "--verbose" in myopts:
+ overlays = string.split(portage.settings['PORTDIR_OVERLAY'])
+
+ if "--tree" in myopts:
+ mylist.reverse()
+ mygraph=self.digraph.copy()
+
+ i = 0
+ while i < len(mylist):
+ if mylist[i][-1]=="nomerge":
+ if not ("--tree" in myopts):
+ # we don't care about this elements
+ mylist.pop(i)
+ continue
+ if (i == (len(mylist) - 1)) \
+ or (mygraph.depth(string.join(mylist[i])) \
+ >= mygraph.depth(string.join(mylist[i+1]))):
+ # end of a useless branch (may be the last one)
+ # -> delete the element and test the previous one
+ mylist.pop(i)
+ if i > 0:
+ i -= 1
+ continue
+ # the branch continues, or we've found a good element.
+ # -> let's see what's next, if anything
+ i += 1
+
+ display_overlays=False
+ # files to fetch list - avoids counting a same file twice
+ # in size display (verbose mode)
+ myfetchlist=[]
+ for x in mylist:
+ fetch=" "
+
+ if x[0]=="blocks":
+ addl=""+red("B")+" "+fetch+" "
+ resolved=portage.db[x[1]]["vartree"].resolve_key(x[2])
+ print "["+x[0]+" "+addl+"]",red(resolved),
+ if resolved!=x[2]:
+ if x[3]:
+ print red("(\""+x[2]+"\" is blocking "+x[3]+")")
+ else:
+ print red("(\""+x[2]+"\")")
+ else:
+ if x[3]:
+ print red("(is blocking "+x[3]+")")
+ else:
+ print
+ else:
+ if (x[0]!="binary") and ("fetch" in string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])):
+ fetch = red("F")
+ if portage.portdb.fetch_check(x[2], portage.settings):
+ fetch = green("f")
+
+ #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
+ #param is used for -u, where you still *do* want to see when something is being upgraded.
+ myoldbest=""
+ if (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific(x[2]):
+ addl=" "+yellow("R")+fetch+" "
+ elif (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific_cat(x[2]):
+ if x[0] == "binary":
+ mynewslot=portage.db["/"]["bintree"].getslot(x[2])
+ elif x[0] == "ebuild":
+ mynewslot=portage.db["/"]["porttree"].getslot(x[2])
+ myoldlist=portage.db[x[1]]["vartree"].dbapi.match(portage.pkgsplit(x[2])[0])
+ myinslotlist=filter((lambda p: portage.db[portage.root]["vartree"].getslot(p)==mynewslot),myoldlist)
+ if myinslotlist:
+ myoldbest=portage.best(myinslotlist)
+ addl=" "+fetch
+ if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
+ # Downgrade in slot
+ addl+=turquoise("U")+blue("D")
+ else:
+ # Update in slot
+ addl+=turquoise("U")+" "
+ else:
+ # New slot, mark it new.
+ addl=" "+green("NS")+fetch+" "
+
+ if "--changelog" in myopts:
+ changelogs.extend(self.calc_changelog(
+ portage.portdb.findname(x[2]),
+ portage.db["/"]["vartree"].dep_bestmatch('/'.join(portage.catpkgsplit(x[2])[:2])),
+ x[2]
+ ))
+ else:
+ addl=" "+green("N")+" "+fetch+" "
+
+ verboseadd=""
+ if "--verbose" in myopts:
+ # iuse verbose
+ try:
+ if x[0] == "binary":
+ iuse_split = string.split(portage.db["/"]["bintree"].dbapi.aux_get(x[2],["IUSE"])[0])
+ elif x[0] == "ebuild":
+ iuse_split = string.split(portage.portdb.aux_get(x[2],["IUSE"])[0])
+ else:
+ iuse_split = []
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ portage.writemsg("!!! Error getting IUSE (report this to bugs.gentoo.org)\n")
+ portage.writemsg("!!! %s\n" % x)
+ iuse_split = []
+ iuse_split.sort()
+ old_use=None
+ if myoldbest:
+ pkg=myoldbest
+ else:
+ pkg=x[2]
+ if portage.db["/"]["vartree"].dbapi.cpv_exists(pkg):
+ try:
+ old_use=string.split(portage.db["/"]["vartree"].dbapi.aux_get(pkg, ["USE"])[0])
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+ iuse=""
+ now_use=self.applied_useflags[x[2]]
+ for ebuild_iuse in portage_util.unique_array(iuse_split):
+ usechange=""
+ if old_use:
+ if (old_use.count(ebuild_iuse) and not now_use.count(ebuild_iuse)) or (not old_use.count(ebuild_iuse) and now_use.count(ebuild_iuse)):
+ usechange="*"
+
+ if ebuild_iuse in self.applied_useflags[x[2]]:
+ if usechange == "*":
+ iuse=green("+"+ebuild_iuse)
+ else:
+ iuse=red("+"+ebuild_iuse)
+ elif ebuild_iuse in portage.settings.usemask:
+ iuse=blue("(-"+ebuild_iuse+")")
+ else:
+ iuse=blue("-"+ebuild_iuse)
+ verboseadd+=iuse+usechange+" "
+
+ # size verbose
+ mysize=0
+ if x[0] == "ebuild" and x[-1]!="nomerge":
+ myfilesdict=portage.portdb.getfetchsizes(x[2], useflags=self.applied_useflags[x[2]], debug=edebug)
+ if myfilesdict==None:
+ myfilesdict="[empty/missing/bad digest]"
+ else:
+ for myfetchfile in myfilesdict.keys():
+ if myfetchfile not in myfetchlist:
+ mysize+=myfilesdict[myfetchfile]
+ myfetchlist.append(myfetchfile)
+ totalsize+=mysize
+ verboseadd+=format_size(mysize)+" "
+
+ # overlay verbose
+ # XXX: Invalid binaries have caused tracebacks here. 'if file_name'
+ # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
+ file_name=portage.portdb.findname(x[2])
+ if file_name: # It might not exist in the tree
+ dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
+ if (overlays.count(dir_name)>0):
+ verboseadd+=teal("["+str(overlays.index(os.path.normpath(dir_name))+1)+"]")+" "
+ display_overlays=True
+ else:
+ verboseadd += "[No ebuild?]"
+
+ xs=portage.pkgsplit(x[2])
+ if xs[2]=="r0":
+ xs[2]=""
+ else:
+ xs[2]="-"+xs[2]
+
+ if self.pkgsettings.has_key("COLUMNWIDTH"):
+ mywidth=int(self.pkgsettings.settings["COLUMNWIDTH"])
+ else:
+ mywidth=130
+ oldlp=mywidth-30
+ newlp=oldlp-30
+
+ indent=""
+ if ("--tree" in myopts):
+ indent=" "*mygraph.depth(string.join(x))
+
+ if myoldbest:
+ myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
+ if myoldbest[-3:]=="-r0":
+ myoldbest=myoldbest[:-3]
+ myoldbest=blue("["+myoldbest+"]")
+
+ if x[1]!="/":
+ if "--columns" in myopts:
+ myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+ if (newlp-nc_len(myprint)) > 0:
+ myprint=myprint+(" "*(newlp-nc_len(myprint)))
+ myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
+ if (oldlp-nc_len(myprint)) > 0:
+ myprint=myprint+" "*(oldlp-nc_len(myprint))
+ myprint=myprint+myoldbest
+ myprint=myprint+darkgreen(" to "+x[1])+" "+verboseadd
+ else:
+ myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+darkgreen("to "+x[1])+" "+verboseadd
+ else:
+ if "--columns" in myopts:
+ myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+ if (newlp-nc_len(myprint)) > 0:
+ myprint=myprint+(" "*(newlp-nc_len(myprint)))
+ myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
+ if (oldlp-nc_len(myprint)) > 0:
+ myprint=myprint+(" "*(oldlp-nc_len(myprint)))
+ myprint=myprint+myoldbest+" "+verboseadd
+ else:
+ if x[3]=="nomerge":
+ myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
+ else:
+ myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
+ p.append(myprint)
+
+ if ("--tree" not in myopts):
+ mysplit=portage.pkgsplit(x[2])
+
+ # XXX mysplit _can_ be None.... Why?
+ if mysplit and (len(mysplit)==3):
+ if "--emptytree" not in myopts:
+ if mysplit[0]=="sys-apps/portage":
+ if ((mysplit[1]+mysplit[2]) != portage.VERSION) and \
+ ("livecvsportage" not in portage.settings.features):
+ if mylist.index(x)<len(mylist)-1:
+ p.append(red("*** Portage will stop merging at this point and reload itself,"))
+ p.append(red(" recalculate dependencies, and complete the merge."))
+ if "--update" not in myopts:
+ p.append(darkgreen(" You may avoid the remerging of packages by updating portage on its own."))
+ print
+ else:
+ if mysplit[0]=="sys-apps/portage" and ("--emptytree" in myopts):
+ if mysplit[1]+mysplit[2]!=portage.VERSION:
+ p.append(red("***")+" Please update portage to the above version before proceeding.")
+ p.append(" Failure to do so may result in failed or improper merges.")
+ p.append(" A simple '"+green("emerge -u portage")+"' is sufficient.")
+ p.append("")
+ del mysplit
+
+ for x in p:
+ print x
+
+ if "--verbose" in myopts:
+ print
+ print "Total size of downloads: "+format_size(totalsize)
+ if overlays and display_overlays:
+ print "Portage overlays:"
+ y=0
+ for x in overlays:
+ y=y+1
+ print " "+teal("["+str(y)+"]"),x
+
+ if "--changelog" in myopts:
+ print
+ for revision,text in changelogs:
+ print bold('*'+revision)
+ sys.stdout.write(text)
+
+ def calc_changelog(self,ebuildpath,current,next):
+ current = '-'.join(portage.catpkgsplit(current)[1:])
+ if current.endswith('-r0'): current = current[:-3]
+ next = '-'.join(portage.catpkgsplit(next)[1:])
+ if next.endswith('-r0'): next = next[:-3]
+ changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
+ try:
+ changelog = open(changelogpath).read()
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ return []
+ divisions = self.find_changelog_tags(changelog)
+ #print 'XX from',current,'to',next
+ #for div,text in divisions: print 'XX',div
+ # skip entries for all revisions above the one we are about to emerge
+ for i in range(len(divisions)):
+ if divisions[i][0]==next:
+ divisions = divisions[i:]
+ break
+ # find out how many entries we are going to display
+ for i in range(len(divisions)):
+ if divisions[i][0]==current:
+ divisions = divisions[:i]
+ break
+ else:
+ # couldnt find the current revision in the list. display nothing
+ return []
+ return divisions
+
+ def find_changelog_tags(self,changelog):
+ divs = []
+ release = None
+ while 1:
+ match = re.search(r'^\*\ ?([-a-zA-Z0-9_.]*)(?:\ .*)?\n',changelog,re.M)
+ if match is None:
+ if release is not None:
+ divs.append((release,changelog))
+ return divs
+ if release is not None:
+ divs.append((release,changelog[:match.start()]))
+ changelog = changelog[match.end():]
+ release = match.group(1)
+ if release.endswith('.ebuild'):
+ release = release[:-7]
+ if release.endswith('-r0'):
+ release = release[:-3]
+
+ def outdated(self):
+ return self.outdatedpackages
+
+ def merge(self,mylist):
+ returnme=0
+ mymergelist=[]
+
+ #check for blocking dependencies
+ if ("--fetchonly" not in myopts) and ("--buildpkgonly" not in myopts):
+ for x in mylist:
+ if x[0]=="blocks":
+ print "\n!!! Error: the "+x[2]+" package conflicts with another package."
+ print "!!! both can't be installed on the same system together."
+ print "!!! Please use 'emerge --pretend' to determine blockers."
+ print
+ if ("--pretend" not in myopts):
+ sys.exit(1)
+
+ #buildsyspkg: I need mysysdict also on resume (moved from the else block)
+ mysysdict=genericdict(syslist)
+ if ("--resume" in myopts):
+ # We're resuming.
+ print green("*** Resuming merge...")
+ emergelog(" *** Resuming merge...")
+ mymergelist=portage.mtimedb["resume"]["mergelist"][:]
+ if ("--skipfirst" in myopts) and mymergelist:
+ del portage.mtimedb["resume"]["mergelist"][0]
+ del mymergelist[0]
+ else:
+ myfavs=portage.grabfile(portage.root+portage.WORLD_FILE)
+ myfavdict=genericdict(myfavs)
+ for x in range(len(mylist)):
+ if mylist[x][3]!="nomerge":
+ # Add to the mergelist
+ mymergelist.append(mylist[x])
+ else:
+ myfavkey=portage.cpv_getkey(mylist[x][2])
+ if "--onlydeps" in myopts:
+ continue
+ # Add to the world file. Since we won't be able to later.
+ if (not "--fetchonly" in myopts) and (myfavkey in favorites):
+ #don't record if already in system profile or already recorded
+ if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+ #we don't have a favorites entry for this package yet; add one
+ myfavdict[myfavkey]=myfavkey
+ print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+ if not "--fetchonly" in myopts:
+ portage.writedict(myfavdict,portage.root+portage.WORLD_FILE,writekey=0)
+
+ portage.mtimedb["resume"]["mergelist"]=mymergelist[:]
+
+ # We need to yank the harmful-to-new-builds settings from features.
+ myorigfeat=self.pkgsettings["FEATURES"]
+ myfeat=myorigfeat.split()
+ while ("keeptemp" in myfeat):
+ del myfeat[myfeat.index("keeptemp")]
+ while ("keepwork" in myfeat):
+ del myfeat[myfeat.index("keepwork")]
+
+ self.pkgsettings["FEATURES"]=string.join(myfeat)
+
+ mergecount=0
+ if "--fetchonly" in myopts:
+ mynewmergelist = []
+ for x in mymergelist:
+ if x[0] != "blocks":
+ mynewmergelist.append(x)
+ mymergelist = mynewmergelist
+ for x in mymergelist:
+ mergecount+=1
+ myroot=x[1]
+ pkgindex=2
+ if x[0]=="blocks":
+ pkgindex=3
+ y=portage.portdb.findname(x[pkgindex])
+ if not "--pretend" in myopts:
+ print ">>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+")",x[pkgindex],"to",x[1]
+ emergelog(" >>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" to "+x[1])
+
+ self.pkgsettings["EMERGE_FROM"] = x[0][:]
+ self.pkgsettings.backup_changes("EMERGE_FROM")
+
+ #buildsyspkg: Check if we need to _force_ binary package creation
+ issyspkg = ("buildsyspkg" in myfeat) \
+ and x[0] != "blocks" \
+ and mysysdict.has_key(portage.cpv_getkey(x[2])) \
+ and not ("--buildpkg" in myopts)
+ if x[0] in ["ebuild","blocks"]:
+ if (x[0]=="blocks") and ("--fetchonly" not in myopts):
+ raise Exception, "Merging a blocker"
+ elif ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts):
+ if x[0] == "blocks":
+ continue
+ if ("--fetch-all-uri" in myopts):
+ retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1,fetchall=1)
+ else:
+ retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1)
+ if (retval == None) or retval:
+ print
+ print "!!! Fetch for",y,"failed, continuing..."
+ print
+ returnme=1
+ continue
+ elif "--buildpkg" in myopts or issyspkg:
+ #buildsyspkg: Sounds useful to display something, but I don't know if we should also log it
+ if issyspkg:
+ print ">>> This is a system package, let's pack a rescue tarball."
+ #emergelog(">>> This is a system package, let's pack a rescue tarball.")
+ #create pkg, then merge pkg
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Packaging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"package",myroot,self.pkgsettings,edebug)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ #dynamically update our database
+ if "--buildpkgonly" not in myopts:
+ portage.db[portage.root]["bintree"].inject(x[2])
+ mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+
+ self.pkgsettings["EMERGE_FROM"] = "binary"
+ self.pkgsettings.backup_changes("EMERGE_FROM")
+
+ retval=portage.pkgmerge(mytbz2,myroot,self.pkgsettings)
+ if retval==None:
+ sys.exit(1)
+ else:
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"merge",myroot,self.pkgsettings,edebug)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+ #dynamically update our database
+ elif x[0]=="binary":
+ #merge the tbz2
+ mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
+ if portage.db[portage.root]["bintree"].isremote(x[2]):
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Fetch"
+ emergelog(" --- ("+str(mergecount)+" of "+str(len(mymergelist))+") Fetching Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
+ portage.db[portage.root]["bintree"].gettbz2(x[2])
+
+ if ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts):
+ continue
+
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
+ retval=portage.pkgmerge(mytbz2,x[1],self.pkgsettings)
+ if retval==None:
+ sys.exit(1)
+ #need to check for errors
+ if "--buildpkgonly" not in myopts:
+ portage.db[x[1]]["vartree"].inject(x[2])
+ myfavkey=portage.cpv_getkey(x[2])
+ if "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts and myfavkey in favorites:
+ myfavs=portage.grabfile(myroot+portage.WORLD_FILE)
+ myfavdict=genericdict(myfavs)
+ mysysdict=genericdict(syslist)
+ #don't record if already in system profile or already recorded
+ if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+ #we don't have a favorites entry for this package yet; add one
+ myfavdict[myfavkey]=myfavkey
+ print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Updating world file ("+x[pkgindex]+")")
+ portage.writedict(myfavdict,myroot+portage.WORLD_FILE,writekey=0)
+
+ if ("noclean" not in portage.features) and (x[0] != "binary"):
+ short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean Post"
+ emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Post-Build Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg)
+ retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1)
+ if (retval == None):
+ portage_util.writemsg("Unable to run required binary.\n")
+ sys.exit(127)
+ if retval:
+ sys.exit(retval)
+
+ if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
+ # Clean the old package that we have merged over top of it.
+ if self.pkgsettings["AUTOCLEAN"]=="yes":
+ xsplit=portage.pkgsplit(x[2])
+ emergelog(" >>> AUTOCLEAN: "+xsplit[0])
+ retval=unmerge("clean", [xsplit[0]])
+ if not retval:
+ emergelog(" --- AUTOCLEAN: Nothing unmerged.")
+
+ # Figure out if we need a restart.
+ mysplit=portage.pkgsplit(x[2])
+ if mysplit[0]=="sys-apps/portage":
+ myver=mysplit[1]+"-"+mysplit[2]
+ if myver[-3:]=='-r0':
+ myver=myver[:-3]
+ if (myver != portage.VERSION) and \
+ ("livecvsportage" not in portage.settings.features):
+ if len(mymergelist) > mergecount:
+ myargv=sys.argv
+ myr=0
+ for myra in range(len(myargv)):
+ if myargv[myr][0:len("portage")]=="portage":
+ del myargv[myr]
+ myr-=1
+ if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage":
+ del myargv[myr]
+ myr-=1
+ myr+=1
+ emergelog(" *** RESTARTING emerge via exec() after change of portage version.")
+ portage.portageexit()
+ # Remove --ask from options before restarting
+ mynewargv=[]
+ badlongopts = ["--ask","--tree","--changelog"]
+ badshortopts = ["a","t","l"]
+ for arg in myargv:
+ if arg[0:2] == "--":
+ if arg in badlongopts:
+ continue
+ mynewargv += [arg]
+ elif arg[0] == "-":
+ myarg = "-"
+ for ch in arg[1:]:
+ if ch in badshortopts:
+ continue
+ myarg += ch
+ mynewargv += [myarg]
+ else:
+ mynewargv += [arg]
+ os.execv("/usr/lib/portage/bin/emerge", mynewargv)
+
+ if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
+ emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1])
+
+ # Unsafe for parallel merges
+ del portage.mtimedb["resume"]["mergelist"][0]
+
+ emergelog(" *** Finished. Cleaning up...")
+
+ # We're out of the loop... We're done. Delete the resume data.
+ if portage.mtimedb.has_key("resume"):
+ del portage.mtimedb["resume"]
+
+ if ("--pretend" not in myopts):
+ if ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts):
+ if (mergecount>0):
+ if retval:
+ portage.env_update()
+
+ #by doing an exit this way, --fetchonly can continue to try to
+ #fetch everything even if a particular download fails.
+ if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+ if returnme:
+ print "\n\n!!! Some fetch errors were encountered. Please see above for details.\n\n"
+ sys.exit(returnme)
+ else:
+ sys.exit(0)
+
+def unmerge(unmerge_action, unmerge_files):
+ candidate_catpkgs=[]
+ global_unmerge=0
+
+ realsyslist = getlist("system")
+ syslist = []
+ for x in realsyslist:
+ mycp = portage.dep_getkey(x)
+ if mycp in portage.settings.virtuals:
+ syslist.extend(portage.settings.virtuals[mycp])
+ syslist.append(mycp)
+
+ global myopts
+ mysettings = portage.config(clone=portage.settings)
+
+ if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files:
+ if "unmerge"==unmerge_action:
+ print
+ print bold("emerge unmerge")+" can only be used with specific package names, not with "+bold("world")+" or"
+ print bold("system")+" targets."
+ print
+ return 0
+ else:
+ global_unmerge=1
+
+ localtree=portage.db[portage.root]["vartree"]
+ # process all arguments and add all valid db entries to candidate_catpkgs
+ if global_unmerge:
+ if not unmerge_files or "world" in unmerge_files:
+ candidate_catpkgs.extend(localtree.getallnodes())
+ elif "system" in unmerge_files:
+ candidate_catpkgs.extend(getlist("system"))
+ else:
+ #we've got command-line arguments
+ if not unmerge_files:
+ print "\nNo packages to unmerge have been provided.\n"
+ return 0
+ for x in unmerge_files:
+ arg_parts=x.split('/')
+ if (x[0] not in [".","/"]) and (arg_parts[-1][-7:] != ".ebuild"):
+ #possible cat/pkg or dep; treat as such
+ candidate_catpkgs.append(x)
+ elif unmerge_action in ["prune","clean"]:
+ print "\n!!! Prune and clean do not accept individual ebuilds as arguments;\n skipping.\n"
+ continue
+ else:
+ # it appears that the user is specifying an installed ebuild and we're in "unmerge" mode, so it's
+ # ok.
+ if not os.path.exists(x):
+ print "\n!!! The path '"+x+"' doesn't exist.\n"
+ return 0
+
+ absx = os.path.abspath(x)
+ sp_absx = absx.split("/")
+ if sp_absx[-1][-7:] == ".ebuild":
+ del sp_absx[-1]
+ absx = string.join(sp_absx,"/")
+
+ sp_absx_len = len(sp_absx)
+
+ vdb_path = portage.root+portage.VDB_PATH
+ vdb_len = len(vdb_path)
+
+ sp_vdb = vdb_path.split("/")
+ sp_vdb_len = len(sp_vdb)
+
+ if not os.path.exists(absx+"/CONTENTS"):
+ print "!!! Not a valid db dir: "+str(absx)
+ return 0
+
+ if sp_absx_len <= sp_vdb_len:
+ # The Path is shorter... so it can't be inside the vdb.
+ print spabsx
+ print absx
+ print "\n!!!",x,"cannot be inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n"
+ return 0
+
+ for idx in range(0,sp_vdb_len):
+ if (idx >= sp_absx_len) or (sp_vdb[idx] != sp_absx[idx]):
+ print sp_absx
+ print absx
+ print "\n!!!",x,"is not inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n"
+ return 0
+
+ print "="+string.join(sp_absx[sp_vdb_len:],"/")
+ candidate_catpkgs.append("="+string.join(sp_absx[sp_vdb_len:],"/"))
+
+ if ("--pretend" in myopts) or ("--ask" in myopts):
+ print darkgreen("\n>>> These are the packages that I would unmerge:")
+
+ pkgmap={}
+ numselected=0
+ for x in candidate_catpkgs:
+ #cycle through all our candidate deps and determine what will and will not get unmerged
+ try:
+ mymatch=localtree.dep_match(x)
+ except KeyError:
+ mymatch=None
+ except ValueError, errpkgs:
+ print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify"
+ print "!!! one of the following fully-qualified ebuild names instead:\n"
+ for i in errpkgs[0]:
+ print " " + green(i)
+ print
+ sys.exit(1)
+
+ if not mymatch and x[0] not in "<>=~":
+ #add a "=" if missing
+ mymatch=localtree.dep_match("="+x)
+ if not mymatch:
+ print "\n--- Couldn't find " + white(x) + " to "+unmerge_action+"."
+ continue
+ mykey=portage.key_expand(portage.dep_getkey(mymatch[0]),portage.db["/"]["vartree"].dbapi)
+ if not pkgmap.has_key(mykey):
+ pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
+ if unmerge_action=="unmerge":
+ for y in mymatch:
+ if y not in pkgmap[mykey]["selected"]:
+ pkgmap[mykey]["selected"].append(y)
+ numselected=numselected+len(mymatch)
+
+ else:
+ #unmerge_action in ["prune", clean"]
+ slotmap={}
+ for mypkg in mymatch:
+ if unmerge_action=="clean":
+ myslot=localtree.getslot(mypkg)
+ else:
+ #since we're pruning, we don't care about slots and put all the pkgs in together
+ myslot=0
+ if not slotmap.has_key(myslot):
+ slotmap[myslot]={}
+ slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
+ for myslot in slotmap.keys():
+ counterkeys=slotmap[myslot].keys()
+ counterkeys.sort()
+ if not counterkeys:
+ continue
+ counterkeys.sort()
+ pkgmap[mykey]["protected"].append(slotmap[myslot][counterkeys[-1]])
+ del counterkeys[-1]
+ #be pretty and get them in order of merge:
+ for ckey in counterkeys:
+ pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
+ numselected=numselected+1
+ #ok, now the last-merged package is protected, and the rest are selected
+ if global_unmerge and not numselected:
+ print "\n>>> No outdated packages were found on your system.\n"
+ return 0
+
+ if not numselected:
+ print "\n>>>",unmerge_action+": No packages selected for removal.\n"
+ return 0
+
+ for x in pkgmap.keys():
+ for y in localtree.dep_match(x):
+ if y not in pkgmap[x]["omitted"] and \
+ y not in pkgmap[x]["selected"] and \
+ y not in pkgmap[x]["protected"]:
+ pkgmap[x]["omitted"].append(y)
+ if global_unmerge and not pkgmap[x]["selected"]:
+ #avoid cluttering the preview printout with stuff that isn't getting unmerged
+ continue
+ if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
+ print red("\a\n\n!!! '%s' is part of your system profile. '%s'" % (mykey))
+ print yellow("\a!!! Unmerging it may be damaging to your system.\n")
+ if "--pretend" not in myopts and "--ask" not in myopts:
+ global EMERGE_WARNING_DELAY
+ countdown(EMERGE_WARNING_DELAY,red("Press Ctrl-C to Stop"))
+ print "\n "+white(x)
+ for mytype in ["selected","protected","omitted"]:
+ print string.rjust(mytype,12)+":",
+ if pkgmap[x][mytype]:
+ for mypkg in pkgmap[x][mytype]:
+ mysplit=portage.catpkgsplit(mypkg)
+ if mysplit[3]=="r0":
+ myversion=mysplit[2]
+ else:
+ myversion=mysplit[2]+"-"+mysplit[3]
+ if mytype=="selected":
+ print red(myversion),
+ else:
+ print green(myversion),
+ else:
+ print "none",
+ print
+
+ print "\n>>>",red("'Selected'"),"packages are slated for removal."
+ print ">>>",green("'Protected'"),"and",green("'omitted'"),"packages will not be removed.\n"
+
+ if "--pretend" in myopts:
+ #we're done... return
+ return 0
+ if "--ask" in myopts:
+ if userquery("Do you want me to unmerge these packages?")=="No":
+ # enter pretend mode for correct formatting of results
+ myopts+=["--pretend"]
+ print
+ print "Quitting."
+ print
+ return 0
+ #the real unmerging begins, after a short delay....
+
+ global CLEAN_DELAY
+ countdown(CLEAN_DELAY, ">>> Unmerging")
+
+ for x in pkgmap.keys():
+ for y in pkgmap[x]["selected"]:
+ print ">>> Unmerging "+y+"..."
+ emergelog("=== Unmerging... ("+y+")")
+ mysplit=string.split(y,"/")
+ #unmerge...
+ retval=portage.unmerge(mysplit[0],mysplit[1],portage.root,mysettings,unmerge_action not in ["clean","prune"])
+ if retval:
+ emergelog(" !!! unmerge FAILURE: "+y)
+ else:
+ emergelog(" >>> unmerge success: "+y)
+ #run ldconfig, etc...
+ portage.env_update()
+ if not numselected:
+ return 0
+ else:
+ return 1
+
+
+def chk_updated_info_files(retval):
+ root=portage.root
+
+ infodirs=[]
+ infodirs.extend(string.split(portage.settings["INFOPATH"], ":"))
+ infodirs.extend(string.split(portage.settings["INFODIR"], ":"))
+
+ print
+ if os.path.exists("/usr/bin/install-info"):
+ regen_infodirs=[]
+ for z in infodirs:
+ if z=='':
+ continue
+ inforoot=normpath(root+z)
+ if os.path.isdir(inforoot):
+ try:
+ infomtime=os.stat(inforoot)[ST_MTIME]
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ infomtime=0
+
+ if not portage.mtimedb.has_key("info"):
+ portage.mtimedb["info"]={}
+ if portage.mtimedb["info"].has_key(inforoot):
+ if portage.mtimedb["info"][inforoot]==infomtime:
+ pass
+ else:
+ portage.mtimedb["info"][inforoot]=infomtime
+ regen_infodirs.append(inforoot)
+ else:
+ regen_infodirs.append(inforoot)
+
+ if not regen_infodirs:
+ print " "+green("*")+" GNU info directory index is up-to-date."
+ else:
+ print " "+green("*")+" Regenerating GNU info directory index..."
+
+ icount=0
+ badcount=0
+ for inforoot in regen_infodirs:
+ if inforoot=='':
+ continue
+ try:
+ os.rename(inforoot+"/dir",inforoot+"/dir.old")
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+
+ if not os.path.isdir(inforoot):
+ continue
+ errmsg = ""
+ for x in os.listdir(inforoot):
+ if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
+ continue
+ myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
+ existsstr="already exists, for file `"
+ if myso!="":
+ if re.search(existsstr,myso):
+ # Already exists... Don't increment the count for this.
+ pass
+ elif myso[:44]=="install-info: warning: no info dir entry in ":
+ # This info file doesn't contain a DIR-header: install-info produces this
+ # (harmless) warning (the --quiet switch doesn't seem to work).
+ # Don't increment the count for this.
+ pass
+ else:
+ badcount=badcount+1
+ errmsg += myso + "\n"
+ icount=icount+1
+
+ #update mtime so we can potentially avoid regenerating.
+ portage.mtimedb["info"][inforoot]=os.stat(inforoot)[ST_MTIME]
+
+ if badcount:
+ print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
+ print errmsg
+ else:
+ print " "+green("*")+" Processed",icount,"info files."
+
+
+def post_emerge(retval=0):
+ global myopts
+ os.chdir("/")
+ if "--pretend" in myopts:
+ sys.exit(retval)
+
+ emergelog(" *** exiting successfully.")
+
+ if "noinfo" not in portage.settings.features:
+ chk_updated_info_files(retval)
+
+ chk_updated_cfg_files()
+ sys.exit(retval)
+
+
+def chk_updated_cfg_files():
+ if portage.settings["CONFIG_PROTECT"]:
+ #number of directories with some protect files in them
+ procount=0
+ for x in string.split(portage.settings["CONFIG_PROTECT"]):
+ if os.path.isdir(x):
+ a=commands.getstatusoutput("cd "+x+"; find . -iname '._cfg????_*'")
+ if a[0]!=0:
+ print " "+red("*")+" error scanning",x
+ else:
+ files=string.split(a[1])
+ if files:
+ procount=procount+1
+ print " "+yellow("* IMPORTANT:")+"",len(files),"config files in",x,"need updating."
+ if procount:
+ #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+ print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+ print
+
+# general options that should be taken into account before any action
+if "--debug" in myopts:
+ edebug=1
+
+if myaction in ["sync","rsync","metadata"] and (not "--help" in myopts):
+ if "--pretend" in myopts:
+ print "emerge: \"sync\" actions do not support \"--pretend.\""
+ sys.exit(1)
+
+ emergelog(" === "+str(myaction))
+ myportdir=portage.settings["PORTDIR"]
+ if myportdir[-1]=="/":
+ myportdir=myportdir[:-1]
+ if not os.path.exists(myportdir):
+ print ">>>",myportdir,"not found, creating it."
+ os.makedirs(myportdir,0755)
+ syncuri=string.rstrip(portage.settings["SYNC"])
+ os.umask(0022)
+ if myaction == "metadata":
+ if "--ask" in myopts:
+ if userquery("Are you sure?") == "No":
+ sys.exit(1)
+ print "skipping sync"
+ updatecache_flg = True
+ tmpservertimestampfile = None
+ elif syncuri[:8]=="rsync://":
+ if not os.path.exists("/usr/bin/rsync"):
+ print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
+ print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
+ sys.exit(1)
+ mytimeout=180
+ if portage.settings.has_key("RSYNC_TIMEOUT"):
+ try:
+ mytimeout=int(portage.settings["RSYNC_TIMEOUT"])
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+
+ rsync_flags = [
+ "--recursive", # Recurse directories
+ "--links", # Consider symlinks
+ "--safe-links", # Ignore links outside of tree
+ "--perms", # Preserve permissions
+ "--times", # Preserive mod times
+ "--compress", # Compress the data transmitted
+ "--force", # Force deletion on non-empty dirs
+ "--whole-file", # Don't do block transfers, only entire files
+ "--delete", # Delete files that aren't in the master tree
+ "--delete-after", # Delete only after everything else is done
+ "--stats", # Show final statistics about what was transfered
+ "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
+ "--exclude='/distfiles'", # Exclude distfiles from consideration
+ "--exclude='/local'", # Exclude local from consideration
+ "--exclude='/packages'", # Exclude packages from consideration
+ ]
+
+ if "--quiet" in myopts:
+ rsync_flags.append("--quiet") # Shut up a lot
+ else:
+ rsync_flags.append("--progress") # Progress meter for each file
+
+ if "--verbose" in myopts:
+ rsync_flags.append("--verbose") # More noise? Not really sure what
+
+ if "--debug" in myopts:
+ rsync_flags.append("--checksum") # Force checksum on all files
+
+ if portage.settings.has_key("RSYNC_EXCLUDEFROM"):
+ if os.path.exists(portage.settings["RSYNC_EXCLUDEFROM"]):
+ rsync_flags.append("--exclude-from="+portage.settings["RSYNC_EXCLUDEFROM"])
+ else:
+ print "!!! RSYNC_EXCLUDEFROM specified, but file does not exist."
+
+ if portage.settings.has_key("RSYNC_RATELIMIT"):
+ rsync_flags.append("--bwlimit="+portage.settings["RSYNC_RATELIMIT"])
+
+ rsynccommand = "/usr/bin/rsync " + string.join(rsync_flags, " ")
+
+ servertimestampdir = portage.settings.depcachedir+"/"
+ servertimestampfile = portage.settings.depcachedir+"/timestamp.chk"
+ tmpservertimestampdir = portage.settings["PORTAGE_TMPDIR"]+"/"
+ tmpservertimestampfile = portage.settings["PORTAGE_TMPDIR"]+"/timestamp.chk"
+
+ # We only use the backup if a timestamp exists in the portdir.
+ content=None
+ if os.path.exists(myportdir+"/metadata/timestamp.chk"):
+ content=portage.grabfile(servertimestampfile)
+ if (not content):
+ content=portage.grabfile(myportdir+"/metadata/timestamp.chk")
+
+ if (content):
+ try:
+ mytimestamp=time.mktime(time.strptime(content[0], "%a, %d %b %Y %H:%M:%S +0000"))
+ except ValueError:
+ mytimestamp=0
+ else:
+ mytimestamp=0
+
+ if not os.path.exists(servertimestampdir):
+ os.mkdir(servertimestampdir)
+ os.chown(servertimestampdir, os.getuid(), portage.portage_gid)
+ os.chmod(servertimestampdir, 02775)
+
+ #exitcode=0
+ try:
+ maxretries=int(portage.settings["RSYNC_RETRIES"])
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ maxretries=3 #default number of retries
+
+ retries=0
+ hostname, port=re.split("rsync://([^:/]*)(:[0-9]+)?", syncuri)[1:3];
+ if port==None:
+ port=""
+ updatecache_flg=True
+
+ ips=[]
+ while (1):
+ if ips:
+ del ips[0]
+ if ips==[]:
+ try:
+ ips=socket.gethostbyname_ex(hostname)[2]
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "Notice:",str(e)
+ dosyncuri=syncuri
+
+ if ips:
+ try:
+ dosyncuri=string.replace(syncuri, "//"+hostname+port+"/", "//"+ips[0]+port+"/", 1)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "Notice:",str(e)
+ dosyncuri=syncuri
+
+ if (retries==0):
+ if "--ask" in myopts:
+ if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
+ print
+ print "Quitting."
+ print
+ sys.exit(0)
+ emergelog(">>> starting rsync with "+dosyncuri)
+ if "--quiet" not in myopts:
+ print ">>> starting rsync with "+dosyncuri+"..."
+ else:
+ emergelog(">>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri))
+ print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
+
+ if "--quiet" not in myopts:
+ print ">>> checking server timestamp ..."
+ mycommand=rsynccommand+" "+dosyncuri+"/metadata/timestamp.chk "+tmpservertimestampdir
+ exitcode=portage.spawn(mycommand,portage.settings,free=1)
+ if (exitcode==0):
+ try:
+ servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000"))
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ servertimestamp = 0
+
+ if (servertimestamp != 0) and (servertimestamp == mytimestamp):
+ emergelog(">>> Cancelling sync -- Already current.")
+ print
+ print ">>>"
+ print ">>> Timestamps on the server and in the local repository are the same."
+ print ">>> Cancelling all further sync action. You are already up to date."
+ print ">>>"
+ print
+ sys.exit(0)
+ elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
+ emergelog(">>> Server out of date: %s" % dosyncuri)
+ print
+ print ">>>"
+ print ">>> SERVER OUT OF DATE: %s" % dosyncuri
+ print ">>>"
+ print
+ elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
+ # actual sync
+ mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir
+ exitcode=portage.spawn(mycommand,portage.settings,free=1)
+ if exitcode in [0,1,2,3,4,11,14,20,21]:
+ break
+ elif exitcode in [0,1,2,3,4,11,14,20,21]:
+ break
+
+ retries=retries+1
+
+ if retries<=maxretries:
+ print ">>> retry ..."
+ time.sleep(11)
+ else:
+ # over retries
+ # exit loop
+ updatecache_flg=False
+ break
+
+ if (exitcode==0):
+ emergelog("=== Sync completed with %s" % dosyncuri)
+ elif (exitcode>0):
+ print
+ if exitcode==1:
+ print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
+ print darkred("!!!")+green(" that your SYNC statement is proper.")
+ print darkred("!!!")+green(" SYNC="+portage.settings["SYNC"])
+ elif exitcode==11:
+ print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
+ print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
+ print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
+ print darkred("!!!")+green(" and try again after the problem has been fixed.")
+ print darkred("!!!")+green(" PORTDIR="+portage.settings["PORTDIR"])
+ elif exitcode==20:
+ print darkred("!!!")+green(" Rsync was killed before it finished.")
+ else:
+ print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
+ print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
+ print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
+ print darkred("!!!")+green(" temporary problem unless complications exist with your network")
+ print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
+ print
+ sys.exit(exitcode)
+ elif syncuri[:6]=="cvs://":
+ if not os.path.exists("/usr/bin/cvs"):
+ print "!!! /usr/bin/cvs does not exist, so rsync support is disabled."
+ print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
+ sys.exit(1)
+ cvsroot=syncuri[6:]
+ cvsdir=os.path.dirname(myportdir)
+ if not os.path.exists(myportdir+"/CVS"):
+ #initial checkout
+ print ">>> starting initial cvs checkout with "+syncuri+"..."
+ if not portage.spawn("cd "+cvsdir+"; cvs -d "+cvsroot+" login",portage.settings,free=1):
+ print "!!! cvs login error; exiting."
+ sys.exit(1)
+ if os.path.exists(cvsdir+"/gentoo-x86"):
+ print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
+ sys.exit(1)
+ if not portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",portage.settings,free=1):
+ print "!!! cvs checkout error; exiting."
+ sys.exit(1)
+ if cvsdir!=myportdir:
+ portage.movefile(cvsdir,portage.settings["PORTDIR"])
+ sys.exit(0)
+ else:
+ #cvs update
+ print ">>> starting cvs update with "+syncuri+"..."
+ sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",portage.settings,free=1))
+ else:
+ print "!!! rsync setting: ",syncuri,"not recognized; exiting."
+ sys.exit(1)
+
+ try: # Prevent users from affecting ebuild.sh.
+ os.close(sys.stdin.fileno())
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+
+ if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
+ if "--quiet" not in myopts:
+ print "\n>>> Updating Portage cache: ",
+ os.umask(0002)
+ cachedir = os.path.normpath(portage.settings.depcachedir)
+ if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
+ "/lib", "/opt", "/proc", "/root", "/sbin",
+ "/sys", "/tmp", "/usr", "/var"]:
+ print "!!! PORTAGE_CACHEDIR IS SET TO A PRIMARY ROOT DIRECTORY ON YOUR SYSTEM."
+ print "!!! This is ALMOST CERTAINLY NOT what you want: "+str(cachedir)
+ sys.exit(73)
+ if not os.path.exists(cachedir):
+ os.mkdir(cachedir)
+
+ # Potentially bad
+ #if os.path.exists(cachedir+"/"+myportdir):
+ # portage.spawn("rm -Rf "+cachedir+"/"+myportdir+"/*",portage.settings,free=1)
+
+ # save timestamp.chk for next timestamp check.
+ try:
+ if tmpservertimestampfile != None:
+ portage.movefile(tmpservertimestampfile, servertimestampfile)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except Exception, e:
+ print "!!! Failed to save current timestamp."
+ print "!!!",e
+
+ portage.portdb.flush_cache()
+
+ try:
+ os.umask(002)
+ os.chown(cachedir, os.getuid(), portage.portage_gid)
+ os.chmod(cachedir, 02775)
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+ # we don't make overlay trees cache here.
+ backup_porttrees=portage.portdb.porttrees
+ porttree_root = portage.portdb.porttree_root
+ portage.portdb.porttrees=[porttree_root]
+ cp_list=portage.portdb.cp_all()
+ cp_list.sort()
+ pcnt=0
+ pcntstr=""
+ pcntcount=len(cp_list)/100.0
+ nextupdate=pcntcount
+ current=1
+ def cleanse_cache(cat, saves, porttree_root=porttree_root):
+ if len(saves):
+ d={}
+ for v in saves:
+ d[portage.catsplit(v)[1]] = True
+ for pv in portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat].keys():
+ if pv not in d:
+ portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat].del_key(pv)
+ else:
+ portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat].clear()
+ del portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat]
+ savelist = []
+ catlist = []
+ oldcat = portage.catsplit(cp_list[0])[0]
+ for cp in cp_list:
+ current += 1
+ if current >= nextupdate:
+ pcnt += 1
+ nextupdate += pcntcount
+ if "--quiet" not in myopts:
+ pcntstr = str(pcnt)
+ sys.stdout.write("\b"*(len(pcntstr)+1)+pcntstr+"%")
+ sys.stdout.flush()
+ cat = portage.catsplit(cp)[0]
+ if cat != oldcat:
+ catlist.append(oldcat)
+ cleanse_cache(oldcat, savelist)
+ savelist = []
+ oldcat = cat
+ mymatches = portage.db["/"]["porttree"].dbapi.xmatch("match-all", cp)
+ savelist.extend(mymatches)
+ for cpv in mymatches:
+ try: portage.db["/"]["porttree"].dbapi.aux_get(cpv, ["IUSE"],metacachedir=myportdir+"/metadata/cache",debug=("cachedebug" in portage.features))
+ except SystemExit: raise
+ except Exception, e: print "\nFailed cache update:",cpv,e
+ catlist.append(oldcat)
+ catlist.append("local")
+ cleanse_cache(oldcat, savelist)
+ filelist = portage.listdir(cachedir+"/"+myportdir)
+ for x in filelist:
+ found = False
+ for y in catlist:
+ if x.startswith(y):
+ found = True
+ break
+ if not found:
+ portage.spawn("cd /; rm -Rf "+cachedir+"/"+myportdir+"/"+x,portage.settings,free=1,droppriv=1)
+
+
+ portage.portdb.porttrees=backup_porttrees
+ sys.stdout.write("\n\n")
+ sys.stdout.flush()
+
+ portage.portageexit()
+ reload(portage)
+ mybestpv=portage.portdb.xmatch("bestmatch-visible","sys-apps/portage")
+ mypvs=portage.best(portage.db[portage.root]["vartree"].dbapi.match("sys-apps/portage"))
+
+ chk_updated_cfg_files()
+
+ if(mybestpv != mypvs):
+ print
+ print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
+ print red(" * ")+"that you update portage now, before any other packages are updated."
+ print red(" * ")+"Please do so and then update "+bold("ALL")+" of your configuration files."
+ print
+elif myaction=="regen":
+ emergelog(" === regen")
+ #regenerate cache entries
+ print "Regenerating cache entries... "
+ try:
+ os.close(sys.stdin.fileno())
+ except SystemExit, e:
+ raise # Needed else can't exit
+ except:
+ pass
+ sys.stdout.flush()
+ mynodes=portage.portdb.cp_all()
+ for x in mynodes:
+ mymatches=portage.portdb.xmatch("match-all",x)
+ if not "--quiet" in myopts:
+ print "processing",x
+ for y in mymatches:
+ try:
+ foo=portage.portdb.aux_get(y,["DEPEND"],debug=1)
+ except SystemExit, e:
+ # sys.exit is an exception... And consequently, we can't catch it.
+ raise
+ except Exception, e:
+ print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
+ print "done!"
+# HELP action
+elif "config"==myaction:
+ if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
+ print red("!!! config can only take a single package atom at this time\n")
+ sys.exit(1)
+
+ print
+ pkgs = portage.db[portage.root]["vartree"].dbapi.match(myfiles[0])
+ if len(pkgs) == 0:
+ print "No packages found.\n"
+ sys.exit(0)
+ elif len(pkgs) > 1:
+ if "--ask" in myopts:
+ options = []
+ print "Please select a package to configure:"
+ idx = 0
+ for pkg in pkgs:
+ idx += 1
+ options.append(str(idx))
+ print options[-1]+") "+pkg
+ print "X) Cancel"
+ options.append("X")
+ idx = userquery("Selection?", options)
+ if idx == "X":
+ sys.exit(0)
+ pkg = pkgs[int(idx)-1]
+ else:
+ print "The following packages available:"
+ for pkg in pkgs:
+ print "* "+pkg
+ print "\nPlease use a specific atom or the --ask option."
+ sys.exit(1)
+ else:
+ pkg = pkgs[0]
+
+ print
+ if "--ask" in myopts:
+ if userquery("Ready to configure "+pkg+"?") == "No":
+ sys.exit(0)
+ else:
+ print "Configuring pkg..."
+ print
+ ebuildpath = portage.db[portage.root]["vartree"].dbapi.findname(pkg)
+ mysettings = portage.config(clone=portage.settings)
+ portage.doebuild(ebuildpath,"config",portage.root,mysettings,debug=("--debug" in myopts),cleanup=True)
+ print
+
+# INFO action
+elif "info"==myaction:
+ unameout=commands.getstatusoutput("uname -mrp")[1]
+ print getportageversion()
+ print "================================================================="
+ print "System uname: "+unameout
+ if os.path.exists("/etc/gentoo-release"):
+ os.system("cat /etc/gentoo-release")
+ else:
+ print "Unknown Host Operating System"
+
+ output=commands.getstatusoutput("distcc --version")
+ if not output[0]:
+ print str(string.split(output[1],"\n",1)[0]),
+ if "distcc" in portage.features:
+ print "[enabled]"
+ else:
+ print "[disabled]"
+
+ output=commands.getstatusoutput("ccache -V")
+ if not output[0]:
+ print str(string.split(output[1],"\n",1)[0]),
+ if "ccache" in portage.features:
+ print "[enabled]"
+ else:
+ print "[disabled]"
+
+ myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
+ "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
+ myvars += portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_pkgs")
+ myvars = portage_util.unique_array(myvars)
+ myvars.sort()
+
+ for x in myvars:
+ if portage.isvalidatom(x):
+ pkg_matches = portage.db["/"]["vartree"].dbapi.match(x)
+ pkgs = []
+ for y in pkg_matches:
+ mycpv = portage.catpkgsplit(y)
+ if(mycpv[3] != "r0"):
+ pkgs += [mycpv[2] + "-" + mycpv[3]]
+ else:
+ pkgs += [mycpv[2]]
+ if not pkgs:
+ pkgs = "[Not Present]"
+ else:
+ pkgs = ", ".join(sorted_versions(pkgs))
+ print "%-20s %s" % (x+":", pkgs)
+ else:
+ print "%-20s %s" % (x+":", "[NOT VALID]")
+
+ libtool_vers = string.join(portage.db["/"]["vartree"].dbapi.match("sys-devel/libtool"), ",")
+
+ if "--verbose" in myopts:
+ myvars=portage.settings.keys()
+ else:
+ myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
+ 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
+ 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
+ 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES']
+
+ myvars.extend(portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_vars"))
+
+ myvars = portage_util.unique_array(myvars)
+ unset_vars = []
+ myvars.sort()
+ for x in myvars:
+ if portage.settings.has_key(x):
+ print x+'="'+portage.settings[x]+'"'
+ else:
+ unset_vars.append(x)
+ if unset_vars:
+ print "Unset: "+", ".join(unset_vars)
+ print
+
+ if "--debug" in myopts:
+ for x in dir(portage):
+ module = getattr(portage, x)
+ if "cvs_id_string" in dir(module):
+ print "%s: %s" % (str(x), str(module.cvs_id_string))
+
+# SEARCH action
+elif "search"==myaction:
+ if not myfiles:
+ print "emerge: no search terms provided."
+ else:
+ searchinstance = search()
+ for mysearch in myfiles:
+ try:
+ searchinstance.execute(mysearch)
+ except re.error, comment:
+ print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
+ sys.exit(1)
+ searchinstance.output()
+elif "inject"==myaction:
+ if not myfiles:
+ print "emerge: please specify at least one cat/pkg-ver to inject."
+ sys.exit(1)
+ if "--pretend" in myopts:
+ print "emerge: the \"inject\" action does not support \"--pretend.\""
+ sys.exit(1)
+ for x in myfiles:
+ if x[0] in [">","<","=","!"]:
+ print "!!! '"+x+"' is an invalid specification."
+ print "!!! Must be 'category/package-version' with no other symbols."
+ print
+ continue
+ mycps=portage.catpkgsplit(x)
+ if (not mycps) or (mycps[0]=="null"):
+ print "!!!",x,"is not a specific cat/pkg-version, skipping..."
+ continue
+ if portage.db["/"]["vartree"].exists_specific(x):
+ print "!!! Not injecting",x+"; Package already exists."
+ else:
+ if "--ask" in myopts:
+ if userquery("Do you want to inject the package %s?" % x)=="No":
+ print
+ print "Quitting."
+ print
+ sys.exit(0)
+ portage.db["/"]["vartree"].dbapi.cpv_inject(x)
+ print ">>> Injected",x+"."
+ emergelog(" === inject: "+x)
+elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
+ if 1==unmerge(myaction, myfiles):
+ post_emerge()
+
+elif "depclean"==myaction:
+ # Kill packages that aren't explicitly merged or are required as a
+ # dependency of another package. World file is explicit.
+
+ print
+ print red("*** WARNING ***")+" : DEPCLEAN CAN SERIOUSLY IMPAIR YOUR SYSTEM. USE CAUTION."
+ print red("*** WARNING ***")+" : (Cancel: CONTROL-C) -- ALWAYS VERIFY ALL PACKAGES IN THE"
+ print red("*** WARNING ***")+" : CANDIDATE LIST FOR SANITY BEFORE ALLOWING DEPCLEAN TO"
+ print red("*** WARNING ***")+" : UNMERGE ANY PACKAGES."
+ print red("*** WARNING ***")+" :"
+ print red("*** WARNING ***")+" : USE FLAGS MAY HAVE AN EXTREME EFFECT ON THE OUTPUT."
+ print red("*** WARNING ***")+" : SOME LIBRARIES MAY BE USED BY PACKAGES BUT ARE NOT"
+ print red("*** WARNING ***")+" : CONSIDERED TO BE A DEPEND DUE TO USE FLAG SETTINGS."
+ print red("*** WARNING ***")+" : emerge --update --deep --newuse world TO VERIFY"
+ print red("*** WARNING ***")+" : SANITY IN THIS REGARD."
+ print red("*** WARNING ***")+" :"
+ print red("*** WARNING ***")+" : Packages in the list that are desired may be added"
+ print red("*** WARNING ***")+" : directly to the world file to cause them to be ignored"
+ print red("*** WARNING ***")+" : by depclean and maintained in the future. BREAKAGES DUE"
+ print red("*** WARNING ***")+" : TO UNMERGING AN ==IN-USE LIBRARY== MAY BE REPAIRED BY"
+ print red("*** WARNING ***")+" : MERGING *** THE PACKAGE THAT COMPLAINS *** ABOUT THE"
+ print red("*** WARNING ***")+" : MISSING LIBRARY."
+ print
+ if ("--pretend" not in myopts) and ("--ask" not in myopts):
+ countdown(EMERGE_WARNING_DELAY, ">>> Depclean")
+ emergelog(" >>> depclean")
+
+ mydepgraph=depgraph(myaction,myopts)
+ syslist=getlist("system")
+ worldlist=getlist("world")
+
+ print "Calculating",myaction,"dependencies ",
+ if not mydepgraph.xcreate("world"):
+ print "\n!!! Failed to create deptree."
+ sys.exit(1)
+ print "\b\b ... done!"
+
+ if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
+ sys.stderr.write(red("The following binaries are not available for merging...\n"))
+ for x in mydepgraph.missingbins:
+ sys.stderr.write(" "+str(x)+"\n")
+ sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
+ sys.exit(1)
+
+ alldeps=mydepgraph.digraph.allnodes()
+ myvarlist=portage.vardbapi(portage.root).cp_all()
+
+ if not syslist:
+ print "!!! You have no system list. Cannot determine system from world."
+ if not worldlist:
+ print "!!! You have no world file. Cannot determine explicit merges."
+ if not myvarlist:
+ print "!!! You have no installed package tree (%s). This is a problem." % portage.VDB_PATH
+ if not alldeps:
+ print "!!! You have no dependencies. Impossible. Bug."
+
+ if not (syslist and worldlist and myvarlist and alldeps):
+ print
+ sys.exit(1)
+
+ reallist=[]
+ for x in alldeps:
+ myparts=portage.catpkgsplit(string.split(x)[2])
+ if not myparts:
+ sys.stderr.write(
+ red("!!! There appears to be a problem with the following package:\n")+
+ red("!!! "+str(string.split(x)[2])+"\n\n")+
+ "!!! Please ensure that blocking/conflicting packages are not merged."+
+ "!!! 'emerge -p "+str(string.split(x)[2])+"\n\n")
+ if ("--pretend" not in myopts) and ("--ask" not in myopts):
+ countdown(EMERGE_WARNING_DELAY, "*** Continuing")
+ continue
+
+ catpack=myparts[0]+"/"+myparts[1]
+ if catpack not in reallist:
+ reallist.append(catpack)
+
+ cleanlist=[]
+ for x in myvarlist:
+ if x not in reallist:
+ if x not in cleanlist:
+ cleanlist.append(x)
+
+ for x in syslist+worldlist:
+ myparts = portage.catpkgsplit(x)
+ if myparts:
+ if myparts[0][0] in ('<','>','='):
+ myparts[0] = myparts[0][1:]
+ if myparts[0][0] in ('<','>','='):
+ myparts[0] = myparts[0][1:]
+ catpack=myparts[0]+"/"+myparts[1]
+ else:
+ catpack=x
+ if catpack in cleanlist:
+ cleanlist.remove(catpack)
+
+ #print "\n\n\nCleaning: "
+ #for x in cleanlist:
+ # print x
+ #print
+
+ if len(cleanlist):
+ unmerge("unmerge", cleanlist)
+
+ print
+ print "Packages installed: "+str(len(myvarlist))
+ print "Packages in world: "+str(len(worldlist))
+ print "Packages in system: "+str(len(syslist))
+ print "Unique package names: "+str(len(reallist))
+ print "Required packages: "+str(len(alldeps))
+ if "--pretend" in myopts:
+ print "Number to remove: "+str(len(cleanlist))
+ else:
+ print "Number removed: "+str(len(cleanlist))
+ post_emerge()
+
+# "update", "system", or just process files:
+else:
+ favorites=[]
+ syslist=getlist("system")
+ if (("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts)) or ("--ask" in myopts):
+ if "--tree" in myopts:
+ print
+ print darkgreen("These are the packages that I would merge, in reverse order:")
+ print
+ else:
+ print
+ print darkgreen("These are the packages that I would merge, in order:")
+ print
+
+ if ("--resume" in myopts) and portage.mtimedb.has_key("resume"):
+ myresumeopts=portage.mtimedb["resume"]["myopts"][:]
+
+ while "--skipfirst" in myresumeopts:
+ myresumeopts.remove("--skipfirst")
+ while "--ask" in myresumeopts:
+ myresumeopts.remove("--ask")
+
+ for myopt in myopts:
+ if myopt not in myresumeopts:
+ myresumeopts.append(myopt)
+ myopts=myresumeopts
+ mydepgraph=depgraph("resume",myopts)
+ if "--resume" not in myopts:
+ myopts+=["--resume"]
+ else:
+ if ("--resume" in myopts):
+ del myopts[myopts.index("--resume")]
+ print darkgreen("emerge: It seems we have nothing to resume...")
+ sys.exit(0)
+
+ mydepgraph=depgraph(myaction,myopts)
+ if myaction in ["system","world"]:
+ print "Calculating",myaction,"dependencies ",
+ sys.stdout.flush()
+ if not mydepgraph.xcreate(myaction):
+ print "!!! Depgraph creation failed."
+ sys.exit(1)
+ print "\b\b ...done!"
+ else:
+ if not myfiles:
+ print "emerge: please tell me what to do."
+ help()
+ sys.exit(1)
+ #we don't have any files to process; skip this step and exit
+ print "Calculating dependencies ",
+ sys.stdout.flush()
+ retval,favorites=mydepgraph.select_files(myfiles)
+ if not retval:
+ sys.exit(1)
+ print "\b\b ...done!"
+
+ if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
+ sys.stderr.write(red("The following binaries are not available for merging...\n"))
+
+ if mydepgraph.missingbins:
+ for x in mydepgraph.missingbins:
+ sys.stderr.write(" "+str(x)+"\n")
+ sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
+ sys.exit(1)
+
+ if "--ask" in myopts:
+ if "--resume" in myopts:
+ mydepgraph.display(portage.mtimedb["resume"]["mergelist"])
+ prompt="Do you want me to resume merging these packages?"
+ else:
+ mydepgraph.display(mydepgraph.altlist())
+ mergecount=0
+ hasblocks = False
+ for x in mydepgraph.altlist():
+ if x[3]!="nomerge":
+ mergecount+=1
+ #check for blocking dependencies
+ if x[0]=="blocks":
+ hasblocks = True
+ if mergecount==0:
+ if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]:
+ prompt="Nothing to merge; do you want me to auto-clean packages?"
+ else:
+ print
+ print "Nothing to merge; quitting."
+ print
+ sys.exit(0)
+ elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+ prompt="Do you want me to fetch the source files for these packages?"
+ elif hasblocks:
+ print "\n!!! Error: The above package list contains packages which cannot be installed"
+ print "!!! on the same system."
+ print
+ sys.exit(1)
+ else:
+ prompt="Do you want me to merge these packages?"
+ print
+ if userquery(prompt)=="No":
+ print
+ print "Quitting."
+ print
+ sys.exit(0)
+ # Don't ask again (e.g. when auto-cleaning packages after merge)
+ myopts.remove("--ask")
+
+ if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+ if ("--resume" in myopts):
+ mydepgraph.display(portage.mtimedb["resume"]["mergelist"])
+ else:
+ mydepgraph.display(mydepgraph.altlist())
+ else:
+ if ("--buildpkgonly" in myopts):
+ if not mydepgraph.digraph.hasallzeros():
+ print "\n!!! --buildpkgonly requires all dependencies to be merged."
+ print "!!! Cannot merge requested packages. Merge deps and try again.\n"
+ sys.exit(1)
+
+ if ("--resume" in myopts):
+ favorites=portage.mtimedb["resume"]["favorites"]
+ mydepgraph.merge(portage.mtimedb["resume"]["mergelist"])
+ else:
+ portage.mtimedb["resume"]={}
+ portage.mtimedb["resume"]["myopts"]=myopts
+ portage.mtimedb["resume"]["favorites"]=favorites
+ if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+ for pkgline in mydepgraph.altlist():
+ if pkgline[0]=="ebuild" and pkgline[3]=="merge":
+ y=portage.portdb.findname(pkgline[2])
+ tmpsettings = portage.config(clone=portage.settings)
+ retval=portage.doebuild(y,"digest",portage.root,tmpsettings,edebug,("--pretend" in myopts))
+ mydepgraph.merge(mydepgraph.altlist())
+
+ if portage.mtimedb.has_key("resume"):
+ del portage.mtimedb["resume"]
+ if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]:
+ print ">>> Auto-cleaning packages ..."
+ unmerge("clean", ["world"])
+ post_emerge()
diff --git a/bin/env-update b/bin/env-update
new file mode 100755
index 00000000..a6042876
--- /dev/null
+++ b/bin/env-update
@@ -0,0 +1,11 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/env-update,v 1.9 2004/10/04 13:56:50 vapier Exp $
+
+import os,sys
+os.environ["PORTAGE_CALLER"] = "env-update"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage
+portage.env_update()
diff --git a/bin/env-update.sh b/bin/env-update.sh
new file mode 100755
index 00000000..5edc2da6
--- /dev/null
+++ b/bin/env-update.sh
@@ -0,0 +1,221 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/env-update.sh,v 1.2 2004/10/04 13:56:50 vapier Exp $
+
+############################################
+############################################
+# ENVIRONMENT SETUP
+############################################
+
+if [[ ${EUID} -ne 0 ]] ; then
+ echo "$0: must be root."
+ exit 1
+fi
+
+# Make sure our environment is sane
+if [[ ! -z "${MAKELINKS}" ]] ; then
+ export MAKELINKS=0
+else
+ export MAKELINKS=1
+fi
+export ROOT="${ROOT:=/}"
+[[ ${ROOT} == */ ]] || export ROOT="${ROOT}/"
+
+export ENVDIR="${ROOT}etc/env.d"
+mkdir -p ${ENVDIR}
+chmod 755 ${ENVDIR}
+specials="
+ KDEDIRS PATH CLASSPATH LDPATH MANPATH INFODIR INFOPATH ROOTPATH
+ CONFIG_PROTECT CONFIG_PROTECT_MASK PRELINK_PATH PYTHONPATH
+ PRELINK_PATH_MASK ADA_INCLUDE_PATH ADA_OBJECTS_PATH"
+colon_separated="
+ ADA_INCLUDE_PATH ADA_OBJECTS_PATH LDPATH PATH MANPATH ROOTPATH
+ PRELINK_PATH PRELINK_PATH_MASK PYTHON_PATH"
+
+export LDSOCONF="${ROOT}etc/ld.so.conf"
+
+export PRELINKCONF="${ROOT}etc/prelink.conf"
+defaultprelinkpaths=":/bin:/sbin:/usr/bin:/usr/sbin:/lib:/usr/lib"
+
+export PROFILEENV="${ROOT}etc/profile.env"
+export CSHENV="${ROOT}etc/csh.env"
+
+# make sure we aren't tricked with previous 'my_envd_' variables
+unset $(set | grep '^my_envd_' | cut -d= -f1)
+
+############################################
+############################################
+# ENV.D PARSING
+############################################
+
+do_has() {
+ local x
+ local me="$1"
+ shift
+
+ for x in "$@" ; do
+ [[ ${x} == ${me} ]] && return 0
+ done
+ return 1
+}
+has() {
+ local ret
+ local ifs="${IFS}"
+ unset IFS
+ do_has $1 ${!2}
+ ret=$?
+ export IFS="${ifs}"
+ return ${ret}
+}
+is_special() {
+ has $1 specials
+}
+is_colon_separated() {
+ has $1 colon_separated
+}
+
+for envd in $(ls ${ENVDIR} | sort) ; do
+ # make sure file is a vaild env'd entry and not a backup file
+ num="${envd:0:2}"
+ if [[ ! -z ${num//[0-9]} ]] ; then
+ continue
+ elif [[ ${envd} == *~ || ${envd} == *.bak ]] ; then
+ continue
+ fi
+
+ # use bash to make sure the file is valid
+ envd="${ENVDIR}/${envd}"
+ if ! (source "${envd}") ; then
+ echo "!!! Error parsing ${envd}!"
+ exit 1
+ fi
+
+ # parse env.d entries
+ cnfvars="$(grep '^[[:alpha:]_][[:alnum:]_]*=' "${envd}")"
+ export IFS=$'\n'
+ for cnfv in ${cnfvars} ; do
+ var="${cnfv/=*}"
+ val="${cnfv:${#var}+1}"
+ if [ "${val:0:1}" == "\"" ] ; then
+ val="${val:1:${#val}-2}"
+ fi
+ myvar="my_envd_${var}"
+ if is_special ${var} ; then
+ if [[ ! -z "${!myvar}" ]] ; then
+ if is_colon_separated ${var} ; then
+ sep=":"
+ else
+ sep=" "
+ fi
+ else
+ sep=""
+ fi
+ export ${myvar}="${!myvar}${sep}${val}"
+ else
+ export ${myvar}="${val}"
+ fi
+ done
+ unset IFS
+done
+
+############################################
+############################################
+# LD.SO.CONF HANDLING
+############################################
+
+# create a : sep list from ld.so.conf
+export OLD_LDPATH=""
+if [ -s "${LDSOCONF}" ] ; then
+ while read line ; do
+ if [[ "${line:0:1}" == "#" ]] ; then
+ continue
+ fi
+ export OLD_LDPATH="${OLD_LDPATH}:${line}"
+ done < ${LDSOCONF}
+ export OLD_LDPATH="${OLD_LDPATH:1}"
+fi
+
+# has the ldpath changed ? if so, recreate
+if [[ "${OLD_LDPATH}" != "${my_envd_LDPATH}" ]] ; then
+ cat << EOF > ${LDSOCONF}
+# ld.so.conf autogenerated by env-update; make all changes to
+# contents of /etc/env.d directory
+${my_envd_LDPATH//:/
+}
+EOF
+fi
+
+############################################
+############################################
+# HANDLE PRELINK PATHS
+############################################
+
+if prelink --version >& /dev/null ; then
+ # we assume LDPATH and PATH aren't empty ... if they were, we got other problems
+ envdprelinkcheckpaths="${my_envd_LDPATH}:${my_envd_PATH}"
+ if [[ ! -z "${my_envd_PRELINK_PATH}" ]] ; then
+ envdprelinkcheckpaths="${envdprelinkcheckpaths}:${my_envd_PRELINK_PATH}"
+ fi
+
+ if [[ ! -z "${my_envd_PRELINK_PATH_MASK}" ]] ; then
+ export prelink_mask=":${PRELINK_PATH_MASK}:"
+ envdprelinkpaths=""
+ export IFS=":"
+ for dir in ${envdprelinkcheckpaths} ; do
+ if [[ ${dir:0-1} == / ]] ; then
+ noslashdir="${dir:0:${#dir}-1}"
+ else
+ dir="${dir}/"
+ noslashdir="${dir}"
+ fi
+ if [[ ${prelink_mask/:${dir}:/} == ${prelink_mask} \
+ && ${prelink_mask/:${noslashdir}:/} == ${prelink_mask} ]] ; then
+ envdprelinkpaths="${envdprelinkpaths}:${dir}"
+ fi
+ done
+ unset IFS
+ else
+ envdprelinkpaths=":${envdprelinkcheckpaths}"
+ fi
+
+ cat << EOF > ${PRELINKCONF}
+# prelink.conf autogenerated by env-update; make all changes to
+# contents of /etc/env.d directory
+${defaultprelinkpaths//:/
+-l }
+${envdprelinkpaths//:/
+-h }
+EOF
+fi
+unset my_envd_LDPATH
+
+############################################
+############################################
+# RUN EXTERNAL PROGRAMS NOW
+############################################
+
+echo ">>> Regenerating ${ROOT}etc/ld.so.cache..."
+if [[ ${MAKELINKS} -eq 0 ]] ; then
+ (cd / ; /sbin/ldconfig -X -r ${ROOT} >& /dev/null)
+else
+ (cd / ; /sbin/ldconfig -r ${ROOT} >& /dev/null)
+fi
+
+cat << EOF > ${PROFILEENV}
+# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.
+# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES
+# GO INTO /etc/profile NOT /etc/profile.env
+
+$(set | grep '^my_envd_' | sed -e 's:^my_envd_:export :')
+EOF
+
+cat << EOF > ${CSHENV}
+# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.
+# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES
+# GO INTO /etc/csh.cshrc NOT /etc/csh.env
+
+$(set | grep '^my_envd_' | sed -e 's:^my_envd_\([[:alpha:]_][[:alnum:]_]*\)=:setenv \1 :')
+EOF
+
+[[ ${ROOT} == / ]] && /sbin/depscan.sh
diff --git a/bin/etc-update b/bin/etc-update
new file mode 100755
index 00000000..e8ea9376
--- /dev/null
+++ b/bin/etc-update
@@ -0,0 +1,407 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/etc-update,v 1.23.2.5 2005/05/29 12:40:08 jstubbs Exp $
+
+# Author Brandon Low <lostlogic@gentoo.org>
+#
+# Previous version (from which I've borrowed a few bits) by:
+# Jochem Kossen <j.kossen@home.nl>
+# Leo Lipelis <aeoo@gentoo.org>
+# Karl Trygve Kalleberg <karltk@gentoo.org>
+
+export PORTAGE_CALLER="etc-update"
+
+eval $(python -c 'import portage; print "export PORTAGE_TMPDIR="+portage.settings["PORTAGE_TMPDIR"]; print "export USERLAND="+portage.settings["USERLAND"]')
+
+if [ "$USERLAND" == "BSD" ] ; then
+ function sed() { gsed "$@"; }
+elif [ "$USERLAND" == "Darwin" ] && [ -x /bin/gsed ]; then
+ function sed() { gsed "$@"; }
+fi
+
+function get_config() {
+ item=$1
+
+ # First strip off comment lines, then grab the configuration
+ # item. If there's more than one of the same configuration item,
+ # then allow the last setting to take precedence.
+ cut -d'#' -f1-1 /etc/etc-update.conf | \
+ sed -ne "s/^ *$item *= *\([\"']\{0,1\}\)\(.*\)\1/\2/p" |sed -e '$p;d'
+}
+
+function scan() {
+
+ echo "Scanning Configuration files..."
+ rm -rf ${TMP}/files > /dev/null 2>&1
+ mkdir ${TMP}/files || die "Failed mkdir command!" 1
+ count=0
+ input=0
+
+ for path in ${CONFIG_PROTECT}; do if [ -d ${path} ]; then
+ ofile=""
+ for file in `find ${path}/ -iname "._cfg????_*" |
+ sed -e "s:\(^.*/\)\(\._cfg[0-9]*_\)\(.*$\):\1\2\3\%\2\%\3:" |
+ sort -t'%' -k3 -k2 | LANG=POSIX LC_ALL=POSIX cut -f1 -d'%'`; do
+ rpath=`echo "${file/\/\///}" | sed -e "s:/[^/]*$::"`
+ rfile=`echo "${file/\/\///}" | sed -e "s:^.*/::"`
+ for mpath in ${CONFIG_PROTECT_MASK}; do
+ if [[ "${rpath}" == "${mpath}"* ]]; then
+ mv ${rpath}/${rfile} ${rpath}/${rfile:10}
+ break
+ fi
+ done
+ [ ! -f ${file} ] && continue
+
+
+ if [[ "${ofile:10}" != "${rfile:10}" ]] ||
+ [[ ${opath} != ${rpath} ]]; then
+ MATCHES=0
+ if [[ "${EU_AUTOMERGE}" == "yes" ]]; then
+ if [ ! -e "${rpath}/${rfile}" ] || [ ! -e "${rpath}/${rfile:10}" ]; then
+ MATCHES=0
+ else
+ diff -Bbua ${rpath}/${rfile} ${rpath}/${rfile:10} | egrep '^[+-]' | egrep -v '^[+-][\t ]*#|^--- |^\+\+\+ ' | egrep -qv '^[-+][\t ]*$'
+ MATCHES=$?
+ fi
+ elif [[ -z `diff -Nua ${rpath}/${rfile} ${rpath}/${rfile:10}|
+ grep "^[+-][^+-]"|grep -v '# .Header:.*'` ]]; then
+ MATCHES=1
+ fi
+ if [[ "${MATCHES}" == "1" ]]; then
+ echo "Automerging trivial changes in: ${rfile:10}"
+ mv ${rpath}/${rfile} ${rpath}/${rfile:10}
+ continue
+ else
+ count=${count}+1
+ echo "${rpath}/${rfile:10}" > ${TMP}/files/${count}
+ echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
+ ofile="${rfile}"
+ opath="${rpath}"
+ continue
+ fi
+ fi
+
+ if [[ -z `diff -Nua ${rpath}/${rfile} ${rpath}/${ofile}|
+ grep "^[+-][^+-]"|grep -v '# .Header:.*'` ]]; then
+ mv ${rpath}/${rfile} ${rpath}/${ofile}
+ continue
+ else
+ echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
+ ofile="${rfile}"
+ opath="${rpath}"
+ fi
+ done
+ fi; done
+
+}
+
+function sel_file() {
+ local -i isfirst=0
+ until [ -f ${TMP}/files/${input} ] || [ ${input} == -1 ] || [ ${input} == -3 ]; do
+ for file in `ls ${TMP}/files|sort -n`; do
+ if (( ${isfirst} == 0 )); then
+ isfirst=${file}
+ fi
+ echo -n "${file}${PAR} "
+ if (( ${mode} == 0 )); then
+ for word in `cat ${TMP}/files/${file}`; do
+ echo ${word}
+ done
+ else
+ head -n1 ${TMP}/files/${file}
+ fi
+ done > ${TMP}/menuitems
+
+ if [ "${OVERWRITE_ALL}" == "yes" ]; then
+ input=0
+ else
+ if (( ${mode} == 0 )); then
+ echo "The following is the list of files which need updating, each
+configuration file is followed by a list of possible replacement files."
+ else
+ local my_title="Please select a file to update"
+ fi
+
+ if (( ${mode} == 0 )); then
+ cat ${TMP}/menuitems
+ echo "Please select a file to edit by entering the corresponding number."
+ echo " (don't use -3 or -5 if you're unsure what to do)"
+ echo " (-1 to exit) (-3 to auto merge all remaining files)"
+ echo -n " (-5 to auto-merge AND not use 'mv -i'): "
+ read input
+ else
+ dialog --title "${title}" --menu "${my_title}" \
+ 0 0 0 `echo "-1 Exit";cat ${TMP}/menuitems` \
+ 2> ${TMP}/input
+ input=`cat ${TMP}/input`
+ fi
+ if (( ${input} == -5 )); then
+ input=-3
+ export mv_opts=""
+ fi
+ if (( ${input} == -3 )); then
+ input=0
+ export OVERWRITE_ALL="yes"
+ fi
+ fi # -3 automerge
+ if (( ${input} == 0 )); then
+ input=${isfirst}
+ fi
+ done
+}
+
+function do_file() {
+ echo
+ local -i my_input
+ local -i fcount=0
+ until (( `cat ${TMP}/files/${input}|wc -l` < 2 )); do
+ my_input=0
+ if (( `cat ${TMP}/files/${input}|wc -l` == 2 )); then
+ my_input=1
+ fi
+ until (( ${my_input} > 0 )) && (( ${my_input} < `cat ${TMP}/files/${input}|wc -l` )); do
+ fcount=0
+
+ if [ "${OVERWRITE_ALL}" == "yes" ]; then
+ my_input=0
+ else
+ for line in `cat ${TMP}/files/${input}`; do
+ if (( ${fcount} > 0 )); then
+ echo -n "${fcount}${PAR} "
+ echo "${line}"
+ else
+ if (( ${mode} == 0 )); then
+ echo "Below are the new config files for ${line}:"
+ else
+ local my_title="Please select a file to process for ${line}"
+ fi
+ fi
+ fcount=${fcount}+1
+ done > ${TMP}/menuitems
+
+ if (( ${mode} == 0 )); then
+ cat ${TMP}/menuitems
+ echo -n "Please select a file to process (-1 to exit this file): "
+ read my_input
+ else
+ dialog --title "${title}" --menu "${my_title}" \
+ 0 0 0 `cat ${TMP}/menuitems;echo "${fcount} Exit"` \
+ 2> ${TMP}/input
+ my_input=`cat ${TMP}/input`
+ fi
+ fi # OVERWRITE_ALL
+
+ if (( ${my_input} == 0 )); then
+ my_input=1
+ elif (( ${my_input} == -1 )); then
+ input=0
+ return
+ elif (( ${my_input} == ${fcount} )); then
+ break
+ fi
+ done
+ if (( ${my_input} == ${fcount} )); then
+ break
+ fi
+
+ fcount=${my_input}+1
+
+ file=`cat ${TMP}/files/${input} | sed -e "${fcount}p;d"`
+ ofile=`head -n1 ${TMP}/files/${input}`
+
+ do_cfg "${file}" "${ofile}"
+
+ cat ${TMP}/files/${input}|sed -e "${fcount}!p;d" > ${TMP}/files/sed
+ mv ${TMP}/files/sed ${TMP}/files/${input}
+
+ if (( ${my_input} == -1 )); then
+ break
+ fi
+ done
+ echo
+ rm ${TMP}/files/${input}
+ count=${count}-1
+}
+
+function do_cfg() {
+
+ local file="${1}"
+ local ofile="${2}"
+ local -i my_input=0
+
+ until (( ${my_input} == -1 )) || [ ! -f ${file} ]; do
+ if [ "${OVERWRITE_ALL}" == "yes" ]; then
+ my_input=1
+ else
+ showdiffcmd=$(echo "${diff_command}" |
+ sed -e "s:%file1:${ofile}:" -e "s:%file2:${file}:")
+
+ if [ "${using_editor}" == 0 ]; then
+ (
+ echo "Showing differences between ${ofile} and ${file}"
+ ${showdiffcmd}
+ ) | ${pager}
+ else
+ echo "Beginning of differences between ${ofile} and ${file}"
+ ${showdiffcmd}
+ echo "End of differences between ${ofile} and ${file}"
+ fi
+ if [ -L "${file}" ]; then
+ echo
+ echo "-------------------------------------------------------------"
+ echo "NOTE: File is a symlink to another file. REPLACE recommended."
+ echo " The original file may simply have moved. Please review."
+ echo "-------------------------------------------------------------"
+ echo
+ fi
+ echo -n "1) Replace original with update
+2) Delete update, keeping original as is
+3) Interactively merge original with update
+4) Show differences again
+Please select from the menu above (-1 to ignore this update): "
+ read my_input
+ fi
+
+ case ${my_input} in
+ 1) echo "Replacing ${ofile} with ${file}"
+ mv ${mv_opts} ${file} ${ofile}
+ my_input=-1
+ continue
+ ;;
+ 2) echo "Deleting ${file}"
+ rm ${rm_opts} ${file}
+ continue
+ ;;
+ 3) do_merge "${file}" "${ofile}"
+ my_input=${?}
+# [ ${my_input} == 255 ] && my_input=-1
+ continue
+ ;;
+ 4) continue
+ ;;
+ *) continue
+ ;;
+ esac
+ done
+}
+
+function do_merge() {
+
+ local file="${1}"
+ local ofile="${2}"
+ local mfile="${2}.merged"
+ local -i my_input=0
+ echo "${file} ${ofile} ${mfile}"
+
+ if [ -e ${mfile} ] ; then
+ echo "A previous version of the merged file exists, cleaning..."
+ rm ${rm_opts} ${mfile}
+ fi
+
+ until (( ${my_input} == -1 )); do
+ echo "Merging ${file} and ${ofile}"
+ `echo "${merge_command}" |
+ sed -e "s:%merged:${mfile}:g" \
+ -e "s:%orig:${ofile}:g" \
+ -e "s:%new:${file}:g"`
+ until (( ${my_input} == -1 )); do
+ echo -n "1) Replace ${ofile} with merged file
+2) Show differences between merged file and original
+3) Remerge original with update
+4) Edit merged file
+5) Return to the previous menu
+Please select from the menu above (-1 to exit, losing this merge): "
+ read my_input
+ case ${my_input} in
+ 1) echo "Replacing ${ofile} with ${mfile}"
+ chmod --reference=${ofile} ${mfile}
+ mv ${mv_opts} ${mfile} ${ofile}
+ rm ${rm_opts} ${file}
+ return 255
+ ;;
+ 2) ( echo "Showing differences between ${ofile} and ${mfile}"
+ `echo "${diff_command}" | \
+ sed -e "s:%file1:${ofile}:" \
+ -e "s:%file2:${mfile}:"` ) | ${pager}
+ continue
+ ;;
+ 3) break
+ ;;
+ 4) ${EDITOR:-nano -w} "${mfile}"
+ continue
+ ;;
+ 5) rm ${rm_opts} ${mfile}
+ return 0
+ ;;
+ *) continue
+ ;;
+ esac
+ done
+ done
+ rm ${rm_opts} ${mfile}
+ return 255
+}
+
+function die() {
+ trap "" term
+ trap "" kill
+ echo "Exiting: ${1}"
+ rm -rf ${TMP}
+ exit ${2}
+}
+
+#
+# Run the script
+#
+scriptname=`basename $0`
+
+trap die term
+
+TMP="${PORTAGE_TMPDIR}/$$"
+rm -rf ${TMP} 2> /dev/null
+mkdir ${TMP} || die "failed mkdir command!" 1
+
+# I need the CONFIG_PROTECT value
+CONFIG_PROTECT=$(/usr/lib/portage/bin/portageq config_protect)
+CONFIG_PROTECT_MASK=$(/usr/lib/portage/bin/portageq config_protect_mask)
+
+# load etc-config's configuration
+EU_AUTOMERGE=`get_config eu_automerge`
+rm_opts=`get_config rm_opts`
+mv_opts=`get_config mv_opts`
+cp_opts=`get_config cp_opts`
+pager=`get_config pager`
+diff_command=`get_config diff_command`
+using_editor=`get_config using_editor`
+merge_command=`get_config merge_command`
+declare -i mode=`get_config mode`
+[ -z ${mode} ] && mode=0
+[ -z "${pager}" ] && pager="cat"
+
+#echo "rm_opts: $rm_opts, mv_opts: $mv_opts, cp_opts: $cp_opts"
+#echo "pager: $pager, diff_command: $diff_command, merge_command: $merge_command"
+
+if (( ${mode} == 0 )); then
+ PAR=")"
+else
+ PAR=""
+fi
+
+declare -i count=0
+declare -i input=0
+declare title="Gentoolkit's etc-update tool!"
+
+scan
+
+until (( ${input} == -1 )); do
+ if (( ${count} == 0 )); then
+ die "Nothing left to do; exiting. :)" 0
+ fi
+ sel_file
+ if (( ${input} != -1 )); then
+ do_file
+ fi
+done
+
+die "User termination!" 0
diff --git a/bin/find-requires b/bin/find-requires
new file mode 100755
index 00000000..44bc51da
--- /dev/null
+++ b/bin/find-requires
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/find-requires,v 1.5 2004/10/04 13:56:50 vapier Exp $
+
+# note this works for both a.out and ELF executables
+# it also auto-generates requirment lines for shell scripts
+
+ulimit -c 0
+
+filelist=`sed "s/['\"]/\\\&/g"`
+exelist=`echo $filelist | $XARGS file | grep ":.*executable" | cut -d: -f1 `
+scriptlist=`echo $filelist | $XARGS file | egrep ":.* (commands|script) " | cut -d: -f1 `
+liblist=`echo $filelist | $XARGS file | grep ":.*shared object" | cut -d : -f1 `
+
+for f in $exelist; do
+ if [ -x $f ]; then
+ ldd $f | awk '/=>/ { print $1 }'
+ fi
+done | sort -u | sed "s/['\"]/\\\&/g" | $XARGS -n 1 basename | grep -v 'libNoVersion.so' | sort -u
+
+for f in $liblist; do
+ ldd $f | awk '/=>/ { print $1 }'
+done | sort -u | sed "s/['\"]/\\\&/g" | $XARGS -n 1 basename | grep -v 'libNoVersion.so' | sort -u
+
+for f in $scriptlist; do
+ if [ -x $f ]; then
+ head -1 $f | sed -e 's/^\#\![ ]*//' | cut -d" " -f1
+ fi
+done | sort -u
+
+#for f in $liblist $exelist ; do
+# objdump -p $f | awk '
+# BEGIN { START=0; LIBNAME=""; }
+# /Version References:/ { START=1; }
+# /required from/ && (START==1) {
+# sub(/:/, "", $3);
+# LIBNAME=$3;
+# }
+# (START==1) && (LIBNAME!="") && ($4~/^GLIBC_*/) { print LIBNAME "(" $4 ")"; }
+# /^$/ { START=0; }
+# '
+#done | sort -u
+
diff --git a/bin/fix-db.py b/bin/fix-db.py
new file mode 100755
index 00000000..d185580f
--- /dev/null
+++ b/bin/fix-db.py
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/fix-db.py,v 1.8 2004/10/11 04:01:00 jstubbs Exp $
+
+import os,sys,re
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+from stat import *
+from output import *
+from portage import lockfile,unlockfile,VDB_PATH,root
+
+
+mylog = open("/var/log/emerge_fix-db.log", "a")
+def writemsg(msg):
+ if msg[-1] != '\n':
+ msg += "\n"
+ sys.stderr.write(msg)
+ sys.stderr.flush()
+ mylog.write(msg)
+ mylog.flush()
+
+def fix_global_counter(value):
+ myf = open("/var/cache/edb/counter")
+ newvalue = value+1000
+ myf.write(str(newvalue))
+ myf.flush()
+ myf.close()
+ return newvalue
+
+bad = {}
+counters = {}
+times = {}
+
+try:
+ real_counter = long(open("/var/cache/edb/counter").read())
+except SystemExit, e:
+ raise # This needs to be propogated
+except:
+ writemsg("ERROR: Real counter is invalid.\n")
+ real_counter = 0
+
+vardbdir = root+VDB_PATH+"/"
+for cat in os.listdir(vardbdir):
+ catdir = vardbdir+cat+"/"
+ if not os.path.isdir(catdir):
+ writemsg("Invalid file: '%s'\n" % catdir[:-1])
+ continue
+ for pkg in os.listdir(catdir):
+ pkgdir = catdir+pkg+"/"
+ catpkg = cat+"/"+pkg
+
+ if not os.path.isdir(catdir):
+ writemsg("Invalid file: '%s'\n" % pkgdir)
+ continue
+
+ bad[catpkg] = []
+
+ pkgdirlist = os.listdir(pkgdir)
+ if not pkgdirlist:
+ writemsg("ERROR: Package directory is empty for '%s'\n" % catpkg)
+ writemsg(" Deleting this directory. Remerge if you want it back.\n")
+ os.rmdir(pkgdir)
+ del bad[catpkg]
+ continue
+
+ if "CONTENTS" not in pkgdirlist:
+ bad[catpkg] += ["CONTENTS is missing"]
+ times[catpkg] = -1
+ writemsg("ERROR: Contents file is missing from the package directory.\n")
+ writemsg(" '%s' is corrupt and should be deleted.\n" % catpkg)
+ else:
+ times[catpkg] = None
+ for line in open(pkgdir+"CONTENTS").readlines():
+ mysplit = line.split()
+ if mysplit[0] == "obj":
+ try:
+ times[catpkg] = long(mysplit[-1])
+ except SystemExit, e:
+ raise # This needs to be propogated
+ except:
+ times[catpkg] = -1
+ bad[catpkg] += ["CONTENTS is corrupt"]
+ writemsg("ERROR: Corrupt CONTENTS file in '%s'\n" % catpkg)
+ writemsg(" This package should be deleted.\n")
+ break
+ if times[catpkg] == None:
+ times[catpkg] = os.stat(pkgdir+"CONTENTS")[ST_MTIME]
+
+ if "COUNTER" not in pkgdirlist:
+ bad[catpkg] += ["COUNTER is missing"]
+ writemsg("ERROR: COUNTER file missing from '%s'.\n" % catpkg)
+ counters[catpkg] = -1
+ else:
+ try:
+ counters[catpkg] = long(open(pkgdir+"COUNTER").read().strip())
+ if counters[catpkg] > real_counter:
+ writemsg("ERROR: Global counter is lower than the '%s' COUNTER." % catpkg)
+ real_counter = fix_global_counter(counters[catpkg])
+ except SystemExit, e:
+ raise # This needs to be propogated
+ except:
+ bad[catpkg] += ["COUNTER is corrupt"]
+ counters[catpkg] = -1
+
+ if "SLOT" not in pkgdirlist:
+ writemsg("ERROR: SLOT file missing from '%s'.\n" % catpkg)
+ writemsg(" RE-MERGE this exact package version or unmerge and remerge.\n")
+ bad[catpkg] += ["SLOT is missing"]
+ else:
+ myslot = open(pkgdir+"SLOT").read()
+ if myslot and myslot[-1]=="\n":
+ #writemsg("WARN: SLOT file has a newline. '%s'\n" % catpkg)
+ myslot = myslot[:-1]
+ if not myslot:
+ bad[catpkg] += ["SLOT is empty"]
+ writemsg("ERROR: SLOT file is empty for '%s'.\n" % catpkg)
+ writemsg(" RE-MERGE this exact package version or unmerge and remerge it.\n")
+ elif re.search("[^-a-zA-Z0-9\._]", myslot):
+ bad[catpkg] += ["SLOT is corrupt"]
+ writemsg("ERROR: SLOT file is corrupt for '%s'.\n" % catpkg)
+ writemsg(" RE-MERGE this exact package version or unmerge and remerge it.\n")
+ elif myslot.strip() != myslot:
+ writemsg("WARN: SLOT file has invalid characters. '%s'\n" % catpkg)
+ bad[catpkg] += ["SLOT is invalid"]
+
+ if not bad[catpkg]:
+ del bad[catpkg]
+
+
+actions = {}
+writemsg("\n\n")
+for catpkg in bad.keys():
+ bad[catpkg].sort()
+
+ mystr = ""
+ for x in bad[catpkg]:
+ mystr += " "+str(x)+"\n"
+
+ if bad[catpkg] == ["CONTENTS is missing", "SLOT is missing"]:
+ writemsg("%s: (possibly injected)\n%s\n" % (green(catpkg), mystr))
+ actions[catpkg] = ["ignore"]
+ elif bad[catpkg] == ["SLOT is empty"]:
+ writemsg("%s: (old package) []\n%s\n" % (yellow(catpkg), mystr))
+ actions[catpkg] = ["remerge"]
+ else:
+ writemsg("%s: (damaged/invalid) []\n%s\n" % (red(catpkg), mystr))
+ actions[catpkg] = ["merge exact"]
+
+if (len(sys.argv) > 1) and (sys.argv[1] == "--fix"):
+ writemsg("These are only directions, at the moment.")
+ for catpkg in actions.keys():
+ action = actions[catpkg]
+ writemsg("We will now '%s' '%s'..." % (action, catpkg))
+ #if action ==
+else:
+ #writemsg("Run with '--fix' to attempt automatic correction.")
+ pass
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bin/fixdbentries b/bin/fixdbentries
new file mode 100755
index 00000000..a9c3e184
--- /dev/null
+++ b/bin/fixdbentries
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/fixdbentries,v 1.3 2004/10/04 13:56:50 vapier Exp $
+
+# Script to adjust the contents of the DB entries after a package move.
+# Fairly straight forward... ./movedbentry 'from/here' 'to/here' /over/here
+
+VAR=$1
+NEW=$2
+SPATH=$3
+
+grep -FrZl "${VAR}" "${SPATH}" |
+sed "s#${SPATH}[^\d000]\+/CONTENTS\d000##g" |
+$XARGS -0 sed -i -e "
+s#${VAR}\$#${NEW}#g;
+s#${VAR}\([[:space:]]\)#${NEW}\1#g;
+s#${VAR}\(-[^a-zA-Z]\)#${NEW}\1#g;
+s#${VAR}\([^a-zA-Z0-9-]\)#${NEW}\1#g
+"
diff --git a/bin/fixpackages b/bin/fixpackages
new file mode 100755
index 00000000..f8d1948a
--- /dev/null
+++ b/bin/fixpackages
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/fixpackages,v 1.6 2004/10/04 13:56:50 vapier Exp $
+
+import os,sys
+os.environ["PORTAGE_CALLER"]="fixpackages"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage
+
+print
+print "Done."
+print
diff --git a/bin/fowners b/bin/fowners
new file mode 100755
index 00000000..cc13372a
--- /dev/null
+++ b/bin/fowners
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/fowners,v 1.6 2004/10/04 13:56:50 vapier Exp $
+
+if [ ${#} -lt 2 ] ; then
+ echo "${0}: at least two arguments needed"
+ exit 1
+fi
+
+OWNER="${1}"
+shift
+for FILE in $*; do
+ chown "${OWNER}" "${D}${FILE}"
+done
diff --git a/bin/fperms b/bin/fperms
new file mode 100755
index 00000000..ce72126e
--- /dev/null
+++ b/bin/fperms
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/fperms,v 1.6 2004/10/04 13:56:50 vapier Exp $
+
+if [ ${#} -lt 2 ] ; then
+ echo "${0}: at least two arguments needed"
+ exit 1
+fi
+
+PERM="${1}"
+shift
+for FILE in $*; do
+ chmod "${PERM}" "${D}${FILE}"
+done
diff --git a/bin/md5check.py b/bin/md5check.py
new file mode 100755
index 00000000..e64d54a9
--- /dev/null
+++ b/bin/md5check.py
@@ -0,0 +1,102 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/md5check.py,v 1.4 2004/10/10 10:07:20 carpaski Exp $
+
+import os,sys,string
+os.environ["PORTAGE_CALLER"]="mirror"
+os.environ["FEATURES"]="mirror cvs"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage
+from threading import *
+from output import red,green,blue,bold
+from random import shuffle
+from time import sleep
+
+
+def cstrip(mystr,mychars):
+ newstr = ""
+ for x in mystr:
+ if x not in mychars:
+ newstr += x
+ return newstr
+
+md5_list = {}
+bn_list = []
+col_list = []
+
+hugelist = []
+for mycp in portage.db["/"]["porttree"].dbapi.cp_all():
+ hugelist += portage.db["/"]["porttree"].dbapi.cp_list(mycp)
+hugelist.sort()
+
+for mycpv in hugelist:
+ pv = string.split(mycpv, "/")[-1]
+
+ newuri = portage.db["/"]["porttree"].dbapi.aux_get(mycpv,["SRC_URI"])[0]
+ newuri = string.split(newuri)
+
+ digestpath = portage.db["/"]["porttree"].dbapi.findname(mycpv)
+ digestpath = os.path.dirname(digestpath)+"/files/digest-"+pv
+ md5sums = portage.digestParseFile(digestpath)
+
+ if md5sums == None:
+ portage.writemsg("Missing digest: %s\n" % mycpv)
+ md5sums = {}
+
+ for x in md5sums.keys():
+ if x[0] == '/':
+ del md5sums[x]
+
+ #portage.writemsg("\n\ndigestpath: %s\n" % digestpath)
+ #portage.writemsg("md5sums: %s\n" % md5sums)
+ #portage.writemsg("newuri: %s\n" % newuri)
+
+ bn_list = []
+ for x in newuri:
+ if not x:
+ continue
+ if (x in [")","(",":","||"]) or (x[-1] == "?"):
+ # ignore it. :)
+ continue
+ x = cstrip(x,"()|?")
+ if not x:
+ continue
+
+ mybn = os.path.basename(x)
+ if mybn not in bn_list:
+ bn_list += [mybn]
+ else:
+ continue
+
+ if mybn not in md5sums.keys():
+ portage_util.writemsg("Missing md5sum: %s in %s\n" % (mybn, mycpv))
+ else:
+ if mybn in md5_list.keys():
+ if (md5_list[mybn]["MD5"] != md5sums[mybn]["MD5"]) or \
+ (md5_list[mybn]["size"] != md5sums[mybn]["size"]):
+
+ # This associates teh md5 with each file. [md5/size]
+ md5joins = string.split(md5_list[mybn][2],",")
+ md5joins = string.join(md5joins," ["+md5_list[mybn][0]+"/"+md5_list[mybn][1]+"],")
+ md5joins += " ["+md5_list[mybn][0]+"/"+md5_list[mybn][1]+"]"
+
+ portage.writemsg("Colliding md5: %s of %s [%s/%s] and %s\n" % (mybn,mycpv,md5sums[mybn][0],md5sums[mybn][1],md5joins))
+ col_list += [mybn]
+ else:
+ md5_list[mybn][2] += ","+mycpv
+ else:
+ md5_list[mybn] = md5sums[mybn]+[mycpv]
+ del md5sums[mybn]
+
+ #portage.writemsg(str(bn_list)+"\n")
+ for x in md5sums.keys():
+ if x not in bn_list:
+ portage.writemsg("Extra md5sum: %s in %s\n" % (x, mycpv))
+
+
+print col_list
+print
+print str(len(md5_list.keys()))+" unique distfile md5s."
+print str(len(bn_list))+" unique distfile names."
diff --git a/bin/md5check.sh b/bin/md5check.sh
new file mode 100755
index 00000000..a4f9f3fd
--- /dev/null
+++ b/bin/md5check.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/md5check.sh,v 1.2 2004/10/04 13:56:50 vapier Exp $
+
+# pipe in the data.
+
+sort -u - > md5check.tmp
+grep '^Extra' md5check.tmp > md5check.tmp.extra
+grep '^Missing' md5check.tmp > md5check.tmp.missing
+grep '^Coll' md5check.tmp > md5check.tmp.colliding
+
+sed -i "
+s:^Col:\nCol:
+s:,:\n :g
+s: of :\n :g
+s: and :\n :g" md5check.tmp.colliding
+sed -i "s/^[^ ]\+ md5sum: \(.*\) in \(.*\)$/ \2: \1/g" md5check.tmp.missing
+sed -i "s/^[^ ]\+ md5sum: \(.*\) in \(.*\)$/ \2: \1/g" md5check.tmp.extra
+
+#echo "Colliding files:" > md5check.colliding
+#sort -u md5check.tmp.colliding >> md5check.colliding
+cp md5check.tmp.colliding md5check.colliding
+
+echo "Missing from digest:" > md5check.missing
+sort -u md5check.tmp.missing >> md5check.missing
+
+echo "Extra files in digest:" > md5check.extra
+sort -u md5check.tmp.extra >> md5check.extra
+
+rm md5check.tmp*
diff --git a/bin/mirror.py b/bin/mirror.py
new file mode 100755
index 00000000..1e08574a
--- /dev/null
+++ b/bin/mirror.py
@@ -0,0 +1,167 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/mirror.py,v 1.3 2004/10/10 10:07:20 carpaski Exp $
+
+# Defines the number of threads carrying out the downloading.
+maxsems=5
+
+import os,sys,string
+os.environ["PORTAGE_CALLER"]="mirror"
+os.environ["FEATURES"]="mirror cvs"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage
+from threading import *
+from output import red,green,blue,bold
+from random import shuffle
+from time import sleep
+
+
+def cstrip(mystr,mychars):
+ newstr = ""
+ for x in mystr:
+ if x not in mychars:
+ newstr += x
+ return newstr
+
+class fetcher(Thread):
+ def __init__(self, filename, urilist, dest, md5sum):
+ self.filename = filename
+ self.myurilist = urilist
+ self.myuri = None
+ self.mydest = dest
+ self.destpath = self.mydest+"/"+self.filename
+ self.md5sum = md5sum
+ self.result = None
+ Thread.__init__(self)
+
+ def fetch(self):
+ #print "Started",self.filename
+ sys.stderr.write(".")
+ sys.stderr.flush()
+ portage.spawn("wget -q -P "+str(self.mydest)+" "+self.myuri, free=1)
+
+ def finished(self):
+ if os.path.exists(self.destpath) and self.md5sum:
+ ok,reason = portage_checksum.verify_all(self.destpath, md5sum)
+ if not ok:
+ portage_util.writemsg("Failed verification:" + reason + "\n")
+ return 1
+ return 0
+
+ def delete(self):
+ if os.path.exists(self.destpath):
+ #print "Unlink:",self.destpath
+ os.unlink(self.destpath)
+
+ def run(self):
+ if not self.finished():
+ self.delete()
+
+ while not self.finished():
+ if self.myurilist:
+ self.myuri = self.myurilist.pop(0)+"/"+self.filename
+ self.fetch()
+ else:
+ self.delete()
+ self.result = 0
+ #print "Failed:",self.filename
+ return 1
+
+ #print "Finished:",self.filename
+ self.result = 1
+ return 0
+
+
+uri_list = {}
+fetchers = []
+fetcher_sem = BoundedSemaphore(value=maxsems)
+failures = 0
+successes = 0
+
+def clean_fetchers():
+ global fetcher_sem,fetchers,uri_list,failures,successes,maxsems
+ while len(fetchers) == maxsems:
+ for x in fetchers:
+ if not x.isAlive():
+ failures += (x.result == 0)
+ successes += (x.result == 1)
+ if x.filename in uri_list.keys():
+ del uri_list[x.filename]
+ del fetchers[fetchers.index(x)]
+ fetcher_sem.release()
+ if len(fetchers) == maxsems:
+ sleep(1)
+
+
+def start_fetcher(fname, urilist, dest, md5sum):
+ global fetcher_sem,fetchers,uri_list,failures,successes
+ fetcher_sem.acquire()
+ fetchers.append(fetcher(fname, urilist, dest, md5sum))
+ fetchers[-1].start()
+
+
+tpm = portage.thirdpartymirrors
+destdir = portage.settings["DISTDIR"][:]
+
+hugelist = []
+for mycp in portage.db["/"]["porttree"].dbapi.cp_all():
+ hugelist += portage.db["/"]["porttree"].dbapi.cp_list(mycp)
+shuffle(hugelist)
+
+mycount = -1
+for mycpv in hugelist:
+ pv = string.split(mycpv, "/")[-1]
+
+ clean_fetchers()
+
+ mycount += 1
+ if ((mycount % 20) == 0):
+ sys.stdout.write("\nCompleted: %s\n" % mycount)
+ sys.stdout.flush()
+ newuri = portage.db["/"]["porttree"].dbapi.aux_get(mycpv,["SRC_URI"])[0]
+ newuri = string.split(newuri)
+
+ digestpath = portage.db["/"]["porttree"].dbapi.findname(mycpv)
+ digestpath = os.path.dirname(digestpath)+"/files/digest-"+pv
+ md5sums = portage.digestParseFile(digestpath)
+
+ for x in newuri:
+ clean_fetchers()
+ if not x:
+ continue
+ if (x in [")","(",":","||"]) or (x[-1] == "?"):
+ # ignore it. :)
+ continue
+ x = cstrip(x,"()|?")
+ if not x:
+ continue
+ mybn = os.path.basename(x)
+ mydn = os.path.dirname(x)
+ if mybn not in uri_list.keys():
+ if (len(mybn) > len("mirror://")) and (mybn[:len("mirror://")] == "mirror://"):
+ mysite = string.split(x[len("mirror://"):], "/")[0]
+ shuffle(tpm[mysite])
+ uri_list[mybn] = tpm[mysite][:]
+ else:
+ uri_list[mybn] = [os.path.dirname(x)]
+ clean_fetchers()
+ if (not md5sums) or (mybn not in md5sums.keys()):
+ start_fetcher(mybn, uri_list[mybn], destdir, None)
+ else:
+ start_fetcher(mybn, uri_list[mybn], destdir, md5sums[mybn])
+ else:
+ break
+
+sys.stderr.write("\n\nWaiting last set\n")
+sys.stderr.flush()
+while fetchers:
+ if fetchers[0].isAlive():
+ fetchers[0].join()
+ clean_fetchers()
+
+print
+print
+print "Successes:",successes
+print "Failures: ",failures
diff --git a/bin/newbin b/bin/newbin
new file mode 100755
index 00000000..6c7904cd
--- /dev/null
+++ b/bin/newbin
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newbin,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dobin "${T}/${2}"
diff --git a/bin/newconfd b/bin/newconfd
new file mode 100755
index 00000000..662b40ed
--- /dev/null
+++ b/bin/newconfd
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newconfd,v 1.2 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doconfd "${T}/${2}"
diff --git a/bin/newdoc b/bin/newdoc
new file mode 100755
index 00000000..a3c43a2f
--- /dev/null
+++ b/bin/newdoc
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newdoc,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dodoc "${T}/${2}"
diff --git a/bin/newenvd b/bin/newenvd
new file mode 100755
index 00000000..0ceec650
--- /dev/null
+++ b/bin/newenvd
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newenvd,v 1.2 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doenvd "${T}/${2}"
diff --git a/bin/newexe b/bin/newexe
new file mode 100755
index 00000000..a2585b3f
--- /dev/null
+++ b/bin/newexe
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newexe,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doexe "${T}/${2}"
diff --git a/bin/newinitd b/bin/newinitd
new file mode 100755
index 00000000..cb23dd79
--- /dev/null
+++ b/bin/newinitd
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newinitd,v 1.2 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doinitd "${T}/${2}"
diff --git a/bin/newins b/bin/newins
new file mode 100755
index 00000000..965ff94b
--- /dev/null
+++ b/bin/newins
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newins,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Error: Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doins "${T}/${2}"
diff --git a/bin/newlib.a b/bin/newlib.a
new file mode 100755
index 00000000..3ec62a3e
--- /dev/null
+++ b/bin/newlib.a
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newlib.a,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Error: Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dolib.a "${T}/${2}"
diff --git a/bin/newlib.so b/bin/newlib.so
new file mode 100755
index 00000000..aa9f9a17
--- /dev/null
+++ b/bin/newlib.so
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newlib.so,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Error: Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dolib.so "${T}/${2}"
diff --git a/bin/newman b/bin/newman
new file mode 100755
index 00000000..227411a5
--- /dev/null
+++ b/bin/newman
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newman,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doman "${T}/${2}"
diff --git a/bin/newsbin b/bin/newsbin
new file mode 100755
index 00000000..eadfba22
--- /dev/null
+++ b/bin/newsbin
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/newsbin,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+if [ -z "${T}" ] || [ -z "${2}" ] ; then
+ echo "Nothing defined to do."
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dosbin "${T}/${2}"
diff --git a/bin/pemerge.py b/bin/pemerge.py
new file mode 100755
index 00000000..08de6eda
--- /dev/null
+++ b/bin/pemerge.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python -O
+
+import profile,time,sys,os
+sys.path = ["/usr/lib/portage/bin","/usr/lib/portage/pym"]+sys.path
+
+def clock():
+ return time.time()
+profile.time.clock = clock
+
+profile.run("import emerge", os.getcwd()+"/prof")
+
+class StatsProcesser:
+ def __init__(self, stats):
+ self.output = []
+ self.last = ""
+ import sys
+ sys.stdout = self
+ stats.print_stats()
+ sys.stdout = sys.__stdout__
+ funcs = ["?"]
+ for line in self.output:
+ spline = line.split()
+ if len(spline) == 6 and spline[0][0].isdigit():
+ func = spline[5][spline[5].index("(")+1:-1]
+ print line
+ if func not in funcs:
+ funcs.append(func)
+ func = "\\(" + func + "\\)"
+ stats.print_callers(func)
+
+ def write(self, text):
+ new = self.last + text
+ new = new.split("\n")
+ if len(new) > 1:
+ self.output += new[:-1]
+ self.last = new[-1]
+
+import pstats
+p = pstats.Stats("prof")
+dir(p)
+p.sort_stats("time")
+p.print_stats()
+
+sp = StatsProcesser(p)
diff --git a/bin/pkgmerge b/bin/pkgmerge
new file mode 100755
index 00000000..2bbb5f68
--- /dev/null
+++ b/bin/pkgmerge
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/pkgmerge,v 1.8 2004/10/04 13:56:50 vapier Exp $
+
+import sys,os,string
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage,xpak
+
+#build our package digraph
+
+def digraph_create(digraph,mykey,myprovides=None):
+ mytbz2=xpak.tbz2(bintree.getname(mykey))
+ mydep=mytbz2.getelements("RDEPEND")
+ digraph.addnode(mykey,myprovides)
+ mycheck=roottree.depcheck(string.join(mydep," "))
+ if mycheck[0]==0:
+ print "!!! Error: RDEPEND string formatted incorrectly:",mydep
+ return None
+ for x in mycheck[1]:
+ mymatch=bintree.dep_bestmatch(x)
+ if mymatch=="":
+ print "!!! Error: can't resolve dependency --",x
+ return None
+ if not digraph_create(digraph,mymatch,mykey):
+ return None
+ return 1
+
+#main program loop
+myvirtuals=portage.getvirtuals(portage.root)
+roottree=portage.vartree(portage.root,myvirtuals)
+bintree=portage.binarytree("/",myvirtuals)
+pretend=0
+if len(sys.argv)>=2:
+ if sys.argv[1]=="--pretend":
+ print "These are the packages that I would merge, in order:"
+ pretend=1
+ del sys.argv[1]
+ elif sys.argv[1]=="--help":
+ print "Usage: pkgmerge [--pretend] pkg1.tbz2 [pkg2.tbz2]..."
+ sys.exit(1)
+for mypkg in sys.argv[1:]:
+ digraph=portage.digraph()
+ mytbz2=xpak.tbz2(mypkg)
+ mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(mypkg)[:-5]
+ digraph_create(digraph,mykey)
+ while not digraph.empty():
+ mykey=digraph.firstzero()
+ if not mykey:
+ print "!!! Error: circular dependencies"
+ sys.exit(1)
+ mytbz2=bintree.getname(mykey)
+ if pretend:
+ print mytbz2
+ else:
+ portage.pkgmerge(mytbz2,portage.settings["ROOT"])
+ digraph.delnode(mykey)
+
diff --git a/bin/pkgmerge.new b/bin/pkgmerge.new
new file mode 100755
index 00000000..66dbe167
--- /dev/null
+++ b/bin/pkgmerge.new
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/pkgmerge.new,v 1.7 2004/10/04 13:56:50 vapier Exp $
+
+import os,string,sys
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage,xpak
+
+#beautiful directed graph functions
+
+def dig_addnode(digraph,mykey,myprovides):
+ if not digraph.has_key(mykey):
+ if myprovides==None:
+ digraph[mykey]=[0,[]]
+ else:
+ digraph[mykey]=[0,[myprovides]]
+ digraph[myprovides][0]=digraph[myprovides][0]+1
+ return
+ digraph[mykey]=[digraph[mykey][0],digraph[mykey][1].append(myprovides)]
+
+def dig_delnode(digraph,mykey):
+ if not digraph.has_key(mykey):
+ return
+ for x in digraph[mykey][1]:
+ digraph[x][0]=digraph[x][0]-1
+ del digraph[mykey]
+
+def dig_firstzero(digraph):
+ for x in digraph.keys():
+ if digraph[x][0]==0:
+ return x
+ return None
+
+#build our package digraph
+
+def digraph_create(digraph,mykey,myprovides=None):
+ mytbz2=xpak.tbz2(bintree.getname(mykey))
+ mydep=mytbz2.getelements("RDEPEND")
+ dig_addnode(digraph,mykey,myprovides)
+ mycheck=roottree.depcheck(string.join(mydep," "))
+ if mycheck[0]==0:
+ print "!!! Error: RDEPEND string formatted incorrectly:",mydep
+ return None
+ for x in mycheck[1]:
+ mymatch=bintree.dep_bestmatch(x)
+ if mymatch=="":
+ print "!!! Error: can't resolve dependency --",x
+ return None
+ if not digraph_create(digraph,mymatch,mykey):
+ return None
+ return 1
+
+#main program loop
+myvirtuals=portage.getvirtual(portage.root)
+roottree=portage.vartree(portage.root,myvirtuals)
+bintree=portage.binarytree("/",myvirtuals)
+pretend=0
+if len(sys.argv)>=2:
+ if sys.argv[1]=="--pretend":
+ print "These are the packages that I would merge, in order:"
+ pretend=1
+ del sys.argv[1]
+ elif sys.argv[1]=="--help":
+ print "Usage: pkgmerge [--pretend] pkg1.tbz2 [pkg2.tbz2]..."
+ sys.exit(1)
+for mypkg in sys.argv[1:]:
+ digraph={}
+ mytbz2=xpak.tbz2(mypkg)
+ mykey=mytbz2.getelements("CATEGORY")[0]+"/"+mypkg[:-5]
+ digraph_create(digraph,mykey)
+ while (len(digraph)):
+ mykey=dig_firstzero(digraph)
+ if not mykey:
+ print "!!! Error: circular dependencies"
+ sys.exit(1)
+ mytbz2=bintree.getname(mykey)
+ if pretend:
+ print mytbz2
+ else:
+ portage.pkgmerge(mytbz2)
+ dig_delnode(digraph,mykey)
+
diff --git a/bin/pkgname b/bin/pkgname
new file mode 100755
index 00000000..22be6f1d
--- /dev/null
+++ b/bin/pkgname
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/pkgname,v 1.8 2004/10/04 13:56:50 vapier Exp $
+
+import sys
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage
+
+a=portage.pkgsplit(sys.argv[1])
+if a:
+ print a[0],a[1],a[2][1:]
+ sys.exit(0)
+else:
+ print '!!! Error: package name is invalid.'
+ sys.exit(1)
diff --git a/bin/portage_gpg_update.sh b/bin/portage_gpg_update.sh
new file mode 100755
index 00000000..a20d9bc1
--- /dev/null
+++ b/bin/portage_gpg_update.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/portage_gpg_update.sh,v 1.2 2004/10/04 13:56:50 vapier Exp $
+
+wget -O - http://www.gentoo.org/proj/en/devrel/roll-call/userinfo.xml | sed 's:.*\(0x[0-9a-fA-F]\+\)[^0-9a-fA-F].*:\1:gp;d' | xargs gpg -vvv --no-default-keyring --no-permission-warning --homedir /usr/portage/metadata --keyring "gentoo.gpg" --keyserver subkeys.pgp.net --recv-keys &> gpg.log
diff --git a/bin/portageq b/bin/portageq
new file mode 100755
index 00000000..6bd6c402
--- /dev/null
+++ b/bin/portageq
@@ -0,0 +1,256 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/portageq,v 1.13.2.1 2005/04/12 12:23:41 jstubbs Exp $
+
+import sys, os
+os.environ["PORTAGE_CALLER"] = "portageq"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import portage,types,string
+
+
+#-----------------------------------------------------------------------------
+#
+# To add functionality to this tool, add a function below.
+#
+# The format for functions is:
+#
+# def function(argv):
+# """<list of options for this function>
+# <description of the function>
+# """
+# <code>
+#
+# "argv" is an array of the command line parameters provided after the command.
+#
+# Make sure you document the function in the right format. The documentation
+# is used to display help on the function.
+#
+# You do not need to add the function to any lists, this tool is introspective,
+# and will automaticly add a command by the same name as the function!
+#
+
+
+def has_version(argv):
+ """<root> <category/package>
+ Return code 0 if it's available, 1 otherwise.
+ """
+ if (len(argv) < 2):
+ print "ERROR: insufficient parameters!"
+ sys.exit(2)
+ try:
+ mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
+ if mylist:
+ sys.exit(0)
+ else:
+ sys.exit(1)
+ except KeyError:
+ sys.exit(1)
+
+
+def best_version(argv):
+ """<root> <category/package>
+ Returns category/package-version (without .ebuild).
+ """
+ if (len(argv) < 2):
+ print "ERROR: insufficient parameters!"
+ sys.exit(2)
+ try:
+ mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
+ print portage.best(mylist)
+ except KeyError:
+ sys.exit(1)
+
+
+def mass_best_version(argv):
+ """<root> [<category/package>]+
+ Returns category/package-version (without .ebuild).
+ """
+ if (len(argv) < 2):
+ print "ERROR: insufficient parameters!"
+ sys.exit(2)
+ try:
+ for pack in argv[1:]:
+ mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
+ print pack+":"+portage.best(mylist)
+ except KeyError:
+ sys.exit(1)
+
+
+def best_visible(argv):
+ """<root> [<category/package>]+
+ Returns category/package-version (without .ebuild).
+ """
+ if (len(argv) < 2):
+ print "ERROR: insufficient parameters!"
+ sys.exit(2)
+ try:
+ mylist=portage.db[argv[0]]["porttree"].dbapi.match(argv[1])
+ print portage.best(mylist)
+ except KeyError:
+ sys.exit(1)
+
+
+def mass_best_visible(argv):
+ """<root> [<category/package>]+
+ Returns category/package-version (without .ebuild).
+ """
+ if (len(argv) < 2):
+ print "ERROR: insufficient parameters!"
+ sys.exit(2)
+ try:
+ for pack in argv[1:]:
+ mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack)
+ print pack+":"+portage.best(mylist)
+ except KeyError:
+ sys.exit(1)
+
+
+def all_best_visible(argv):
+ """<root>
+ Returns all best_visible packages (without .ebuild).
+ """
+ if (len(argv) < 1):
+ print "ERROR: insufficient parameters!"
+
+ #print portage.db[argv[0]]["porttree"].dbapi.cp_all()
+ for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all():
+ mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg))
+ if mybest:
+ print mybest
+
+def match(argv):
+ """<root> <category/package>
+ Returns \n seperated list of category/package-version
+ """
+ if (len(argv) < 2):
+ print "ERROR: insufficient parameters!"
+ sys.exit(2)
+ try:
+ print string.join(portage.db[argv[0]]["vartree"].dbapi.match(argv[1]),"\n")
+ except KeyError:
+ sys.exit(1)
+
+
+def vdb_path(argv):
+ """
+ Returns the path used for the var(installed) package database for the
+ set environment/configuration options.
+ """
+ print portage.root+portage.VDB_PATH
+
+def gentoo_mirrors(argv):
+ """
+ Returns the mirrors set to use in the portage configuration.
+ """
+ print portage.settings["GENTOO_MIRRORS"]
+
+
+def portdir(argv):
+ """
+ Returns the PORTDIR path as defined in the portage configuration.
+ """
+ print portage.settings["PORTDIR"]
+
+
+def config_protect(argv):
+ """
+ Returns the CONFIG_PROTECT paths as defined in the portage configuration.
+ """
+ print portage.settings["CONFIG_PROTECT"]
+
+
+def config_protect_mask(argv):
+ """
+ Returns the CONFIG_PROTECT_MASK paths as defined in the portage configuration.
+ """
+ print portage.settings["CONFIG_PROTECT_MASK"]
+
+
+def portdir_overlay(argv):
+ """
+ Returns the PORTDIR_OVERLAY path as defined in the portage configuration.
+ """
+ print portage.settings["PORTDIR_OVERLAY"]
+
+
+def pkgdir(argv):
+ """
+ Returns the PKGDIR path as defined in the portage configuration.
+ """
+ print portage.settings["PKGDIR"]
+
+
+def distdir(argv):
+ """
+ Returns the DISTDIR path as defined in the portage configuration.
+ """
+ print portage.settings["DISTDIR"]
+
+
+def envvar(argv):
+ """<variable>
+ Returns a specific environment variable as exists prior to ebuild.sh.
+ Similar to: emerge --verbose --info | egrep '^<variable>='
+ """
+ print portage.settings[argv[0]]
+
+
+#-----------------------------------------------------------------------------
+#
+# DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
+#
+
+def usage():
+ rev="$Revision: 1.13.2.1 $"
+ ver=string.split(rev, ' ')[1]
+ print ">>> Portage information query tool -- version "+ver
+ print ">>> Usage: portageq <command> [<option> ...]"
+ print ""
+ print "Available commands:"
+
+ #
+ # Show our commands -- we do this by scanning the functions in this
+ # file, and formatting each functions documentation.
+ #
+ for name in globals().keys():
+ # Drop python stuff, modules, and our own support functions.
+ if (name in ("usage", "__doc__", "__name__", "main", "os", "portage", "sys", "__builtins__", "types", "string")):
+ continue
+
+ # Drop non-functions
+ obj = globals()[name]
+ if (type(obj) != types.FunctionType):
+ continue
+
+ doc = obj.__doc__
+ if (doc == None):
+ print " "+name
+ print " MISSING DOCUMENTATION!"
+ print ""
+ continue
+
+ lines = string.split(doc, '\n')
+ print " "+name+" "+string.strip(lines[0])
+ for line in lines[1:]:
+ print " "+string.strip(line)
+
+
+def main():
+ if (len(sys.argv) < 2):
+ usage()
+ sys.exit()
+
+ cmd = sys.argv[1]
+ try:
+ function = globals()[cmd]
+ function(sys.argv[2:])
+ except KeyError:
+ usage()
+ sys.exit()
+
+main()
+
+
+#-----------------------------------------------------------------------------
diff --git a/bin/prepall b/bin/prepall
new file mode 100755
index 00000000..3826f74f
--- /dev/null
+++ b/bin/prepall
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepall,v 1.10 2004/10/14 23:31:33 ferringb Exp $
+
+prepallman
+prepallinfo
+prepallstrip
+
+#this should help to ensure that all (most?) shared libraries are executable
+for i in "${D}"opt/*/lib{,32,64} \
+ "${D}"lib{,32,64} \
+ "${D}"usr/lib{,32,64} \
+ "${D}"usr/X11R6/lib{,32,64} ; do
+ [ ! -d "${i}" ] && continue
+
+ for j in "${i}"/*.so.* "${i}"/*.so ; do
+ [ ! -e "${j}" ] && continue
+ [ -L "${j}" ] && continue
+ echo "making executable: /${j/${D}/}"
+ chmod +x "${j}"
+ done
+done
+
+# Move aclocals
+for i in `find "${D}"/ -name "aclocal" -type d 2>/dev/null` ; do
+ [ -z "${i}" ] && continue
+
+ # Strip double '/'
+ dir1="`echo "${i}" | sed -e 's:/\{2,\}:/:g'`"
+ dir2="`echo "${D}/usr/share/aclocal" | sed -e 's:/\{2,\}:/:g'`"
+
+ [ "${dir1}" == "${dir2}" ] && continue
+
+ echo "moving aclocal: /${i/${D}/}"
+ install -d "${D}"usr/share/aclocal
+ mv "${i}"/* "${D}"usr/share/aclocal
+ rm -fr "${i}"
+done
diff --git a/bin/prepalldocs b/bin/prepalldocs
new file mode 100755
index 00000000..26ac80ca
--- /dev/null
+++ b/bin/prepalldocs
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepalldocs,v 1.6 2004/10/04 13:56:50 vapier Exp $
+
+z="`find "${D}"usr/share/doc \( -type f -or -type l \) -not -name "*.gz" -not -name "*.js" 2>/dev/null`"
+
+for y in ${z} ; do
+ if [ -L "${y}" ] ; then
+ # Symlink ...
+ mylink="${y}"
+ linkto="`readlink "${y}"`"
+
+ if [ "${linkto##*.}" != "gz" ] ; then
+ linkto="${linkto}.gz"
+ fi
+ if [ "${mylink##*.}" != "gz" ] ; then
+ mylink="${mylink}.gz"
+ fi
+
+ echo "fixing doc symlink: ${mylink##*/}"
+ ln -snf "${linkto}" "${mylink}"
+ if [ "${y}" != "${mylink}" ] ; then
+ echo "removing old symlink: ${y##*/}"
+ rm -f "${y}"
+ fi
+ else
+ if [ "${y##*.}" != "gz" ] ; then
+ echo "gzipping doc: ${y##*/}"
+ gzip -f -9 "${y}"
+ fi
+ fi
+done
diff --git a/bin/prepallinfo b/bin/prepallinfo
new file mode 100755
index 00000000..134e8326
--- /dev/null
+++ b/bin/prepallinfo
@@ -0,0 +1,9 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepallinfo,v 1.6 2004/10/04 13:56:50 vapier Exp $
+
+[ ! -d "${D}usr/share/info" ] && exit 0
+
+echo "info:"
+prepinfo
diff --git a/bin/prepallman b/bin/prepallman
new file mode 100755
index 00000000..26486fda
--- /dev/null
+++ b/bin/prepallman
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepallman,v 1.10 2004/10/04 13:56:50 vapier Exp $
+
+echo "man:"
+for x in "${D}"opt/*/man "${D}"usr/share/man "${D}"usr/local/man "${D}"usr/X11R6/man ; do
+ if [ -d "${x}" ]
+ then
+ prepman "`echo "${x}" | sed -e "s:${D}::" -e "s:/man[/]*$::"`"
+ fi
+done
diff --git a/bin/prepallstrip b/bin/prepallstrip
new file mode 100755
index 00000000..57994738
--- /dev/null
+++ b/bin/prepallstrip
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepallstrip,v 1.12 2004/10/04 13:56:50 vapier Exp $
+
+if [ "${FEATURES//*nostrip*/true}" == "true" ] || [ "${RESTRICT//*nostrip*/true}" == "true" ] ; then
+ exit 0
+fi
+
+echo "prepallstrip:"
+prepstrip "${D}"
diff --git a/bin/prepinfo b/bin/prepinfo
new file mode 100755
index 00000000..65bfba32
--- /dev/null
+++ b/bin/prepinfo
@@ -0,0 +1,45 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepinfo,v 1.6.2.1 2005/05/29 12:40:08 jstubbs Exp $
+
+if [ -z "$1" ] ; then
+ z="${D}usr/share/info"
+else
+ if [ -d "${D}$1/share/info" ] ; then
+ z="${D}$1/share/info"
+ else
+ z="${D}$1/info"
+ fi
+fi
+
+[ ! -d "${z}" ] && exit 0
+
+rm -f "${z}"/{dir,dir.info,dir.info.gz}
+
+for x in `find "${z}"/ -mindepth 1 -maxdepth 1 \( -type f -or -type l \) 2>/dev/null` ; do
+ if [ -L "${x}" ] ; then
+ # Symlink ...
+ mylink="${x}"
+ linkto="`readlink "${x}"`"
+
+ if [ "${linkto##*.}" != "gz" ] ; then
+ linkto="${linkto}.gz"
+ fi
+ if [ "${mylink##*.}" != "gz" ] ; then
+ mylink="${mylink}.gz"
+ fi
+
+ echo "fixing GNU info symlink: ${mylink##*/}"
+ ln -snf "${linkto}" "${mylink}"
+ if [ "${x}" != "${mylink}" ] ; then
+ echo "removing old symlink: ${x##*/}"
+ rm -f "${x}"
+ fi
+ else
+ if [ "${x##*.}" != "gz" ] ; then
+ echo "gzipping GNU info page: ${x##*/}"
+ gzip -f -9 "${x}"
+ fi
+ fi
+done
diff --git a/bin/preplib b/bin/preplib
new file mode 100755
index 00000000..2a431260
--- /dev/null
+++ b/bin/preplib
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/preplib,v 1.7.2.1 2005/01/02 09:36:02 jstubbs Exp $
+
+LIBDIR_VAR="LIBDIR_${ABI}"
+if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+ CONF_LIBDIR="${!LIBDIR_VAR}"
+fi
+unset LIBDIR_VAR
+
+if [ -z "${CONF_LIBDIR}" ]; then
+ # we need this to default to lib so that things dont break
+ CONF_LIBDIR="lib"
+fi
+
+if [ -z "$1" ] ; then
+ z="${D}usr/${CONF_LIBDIR}"
+else
+ z="${D}$1/${CONF_LIBDIR}"
+fi
+
+if [ -d "${z}" ] ; then
+ ldconfig -n -N "${z}"
+fi
diff --git a/bin/preplib.so b/bin/preplib.so
new file mode 100755
index 00000000..13d67d9c
--- /dev/null
+++ b/bin/preplib.so
@@ -0,0 +1,10 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/preplib.so,v 1.10.2.1 2004/12/06 03:01:43 carpaski Exp $
+
+for x in "$@" ; do
+ if [ -d "${D}${x}" ] ; then
+ ldconfig -n -N "${D}${x}"
+ fi
+done
diff --git a/bin/prepman b/bin/prepman
new file mode 100755
index 00000000..2042c4d3
--- /dev/null
+++ b/bin/prepman
@@ -0,0 +1,46 @@
+#!/bin/bash
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepman,v 1.10.2.3 2005/05/29 12:40:08 jstubbs Exp $
+
+if [ -z "$1" ] ; then
+ z="${D}usr/share/man"
+else
+ z="${D}$1/man"
+fi
+
+[ ! -d "${z}" ] && exit 0
+
+for x in `find "${z}"/ -type d 2>/dev/null` ; do
+ for y in `find "${x}"/ -mindepth 1 -maxdepth 1 \( -type f -or -type l \) ! -name '.keep' 2>/dev/null` ; do
+ if [ -L "${y}" ] ; then
+ # Symlink ...
+ mylink="${y}"
+ linkto="`readlink "${y}"`"
+
+ # Do NOT change links to directories
+ if [ -d "${z}/${linkto}" ] ; then
+ continue
+ fi
+
+ if [ "${linkto##*.}" != "gz" ] && [ "${linkto##*.}" != "bz2" ]; then
+ linkto="${linkto}.gz"
+ fi
+ if [ "${mylink##*.}" != "gz" ] && [ "${mylink##*.}" != "bz2" ]; then
+ mylink="${mylink}.gz"
+ fi
+
+ echo "fixing man page symlink: ${mylink##*/}"
+ ln -snf "${linkto}" "${mylink}"
+ if [ "${y}" != "${mylink}" ] ; then
+ echo "removing old symlink: ${y##*/}"
+ rm -f "${y}"
+ fi
+ else
+ if [ "${y##*.}" != "gz" ] && [ "${y##*.}" != "bz2" ] && [ ! -d "${y}" ]; then
+ echo "gzipping man page: ${y##*/}"
+ gzip -f -9 "${y}"
+ fi
+ fi
+ done
+done
diff --git a/bin/prepstrip b/bin/prepstrip
new file mode 100755
index 00000000..f5a51a37
--- /dev/null
+++ b/bin/prepstrip
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/prepstrip,v 1.23.2.3 2005/08/15 02:58:20 vapier Exp $
+
+if [ "${FEATURES//*nostrip*/true}" == "true" ] || [ "${RESTRICT//*nostrip*/true}" == "true" ] ; then
+ echo "nostrip"
+ STRIP="/bin/false"
+ PORTAGE_STRIP_FLAGS=""
+else
+ STRIP="${STRIP:-${CHOST}-strip}"
+ type -p ${STRIP} > /dev/null || STRIP=strip
+ PORTAGE_STRIP_FLAGS=${PORTAGE_STRIP_FLAGS:---strip-unneeded}
+fi
+
+banner=1
+retval=0
+
+for x in "$@" ; do
+ if [ -d "${x}" ]; then
+ # We only want files. So make a pass for each directory and call again.
+ find "${x}" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 -or -name '*.so' -or -name '*.so.*' \) -print0 |
+ $XARGS -0 -n500 prepstrip
+ else
+ if [ ${banner} -eq 1 ] ; then
+ echo "strip: ${STRIP} ${PORTAGE_STRIP_FLAGS}"
+ banner=0
+ fi
+
+ f=$(file "${x}") || continue
+ [ -z "${f}" ] && continue
+
+ if [ -z "${f/*current ar archive*/}" ]; then
+ echo " ${x:${#D}:${#x}}"
+ ${STRIP} -g "${x}"
+ fi
+ if [ -z "${f/*SB executable*/}" ]; then
+ echo " ${x:${#D}:${#x}}"
+ ${STRIP} "${x}"
+ fi
+ if [ -z "${f/*SB shared object*/}" ]; then
+ echo " ${x:${#D}:${#x}}"
+ ${STRIP} ${PORTAGE_STRIP_FLAGS} "${x}"
+ fi
+ fi
+done
+
+exit ${retval}
diff --git a/bin/quickpkg b/bin/quickpkg
new file mode 100755
index 00000000..f5baa4cb
--- /dev/null
+++ b/bin/quickpkg
@@ -0,0 +1,148 @@
+#!/bin/bash
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/quickpkg,v 1.13.2.6 2005/08/10 22:08:48 vapier Exp $
+
+# This script tries to quickly create a Gentoo binary package using the
+# VDB_PATH/category/pkg/* files
+#
+# Resulting tbz2 file will be created in ${PKGDIR} ...
+# default is /usr/portage/packages/All/
+
+if [ "`whoami`" != "root" ] ; then
+ echo "You must run this as root"
+ exit 1
+fi
+
+export PORTAGE_DB=$(portageq vdb_path)
+if [ -z "$1" ] || [ $1 == "-h" ] || [ $1 == "--help" ] ; then
+ echo "QUICKPKG ver 1.2"
+ echo "USAGE: quickpkg <list of pkgs>"
+ echo " a pkg can be of the form:"
+ echo " - ${PORTAGE_DB}/<CATEGORY>/<PKG-VERSION>/"
+ echo " - single depend-type atom ..."
+ echo " if portage can emerge it, quickpkg can make a package"
+ echo " for exact definitions of depend atoms, see ebuild(5)"
+ echo
+ echo "EXAMPLE:"
+ echo " quickpkg ${PORTAGE_DB}/net-www/apache-1.3.27-r1"
+ echo " package up apache, just version 1.3.27-r1"
+ echo " quickpkg apache"
+ echo " package up apache, all versions of apache installed"
+ echo " quickpkg =apache-1.3.27-r1"
+ echo " package up apache, just version 1.3.27-r1"
+ exit 1
+fi
+
+export PKGDIR=$(portageq envvar PKGDIR)
+export PORTAGE_TMPDIR=$(portageq envvar PORTAGE_TMPDIR)
+
+source /sbin/functions.sh
+
+# here we make a package given a little info
+# $1 = package-name w/version
+# $2 = category
+do_pkg() {
+ mkdir -p "${PORTAGE_TMPDIR}/portage-pkg" || exit 1
+ chmod 0750 "${PORTAGE_TMPDIR}/portage-pkg"
+ MYDIR="${PORTAGE_TMPDIR}/portage-pkg/$1"
+ SRCDIR="${PORTAGE_DB}/$2/$1"
+ LOG="${PORTAGE_TMPDIR}/portage-pkg/$1-quickpkglog"
+
+ ebegin "Building package for $1"
+ (
+ # clean up temp directory
+ rm -rf "${MYDIR}"
+
+ # get pkg info files
+ mkdir -p "${MYDIR}"/temp
+ cp "${SRCDIR}"/* "${MYDIR}"/temp/
+
+ # create filelist and a basic tbz2
+ gawk '{
+ if ($1 != "dir") {
+ if ($1 == "obj")
+ NF=NF-2
+ else if ($1 == "sym")
+ NF=NF-3
+ print
+ }
+ }' "${SRCDIR}"/CONTENTS | cut -f2- -d" " - > "${MYDIR}"/filelist
+ tar vjcf "${MYDIR}"/bin.tar.bz2 --files-from="${MYDIR}"/filelist --no-recursion
+
+ # join together the basic tbz2 and the pkg info files
+ xpak "${MYDIR}"/temp "${MYDIR}"/inf.xpak
+ tbz2tool join "${MYDIR}"/bin.tar.bz2 "${MYDIR}"/inf.xpak "${MYDIR}"/$1.tbz2
+
+ # move the final binary package to PKGDIR
+ [ -d "${PKGDIR}"/All ] || mkdir -p "${PKGDIR}"/All
+ [ -d "${PKGDIR}/$2" ] || mkdir -p "${PKGDIR}/$2"
+ mv "${MYDIR}"/$1.tbz2 "${PKGDIR}"/All
+ ( cd "${PKGDIR}/$2" && ln -s ../All/$1.tbz2 )
+
+ # cleanup again
+ rm -rf "${MYDIR}"
+ ) >& "${LOG}"
+
+ if [ -e "${PKGDIR}/All/$1.tbz2" ] ; then
+ rm -f "${LOG}"
+ PKGSTATS="${PKGSTATS}"$'\n'"$(einfo $1: $(du -h "${PKGDIR}/All/$1.tbz2" | gawk '{print $1}'))"
+ eend 0
+ else
+ cat ${LOG}
+ PKGSTATS="${PKGSTATS}"$'\n'"$(ewarn $1: not created)"
+ eend 1
+ fi
+}
+
+# here we parse the parameters given to use on the cmdline
+export PKGERROR=""
+export PKGSTATS=""
+for x in "$@" ; do
+
+ # they gave us full path
+ if [ -e "${x}"/CONTENTS ] ; then
+ x=$(readlink -f $x)
+ pkg=$(echo ${x} | cut -d/ -f6)
+ cat=$(echo ${x} | cut -d/ -f5)
+ do_pkg "${pkg}" "${cat}"
+
+ # lets figure out what they want
+ else
+ DIRLIST=$(portageq match / "${x}")
+ if [ -z "${DIRLIST}" ] ; then
+ eerror "Could not find anything to match '${x}'; skipping"
+ export PKGERROR="${PKGERROR} ${x}"
+ continue
+ fi
+
+ for d in ${DIRLIST} ; do
+ pkg=$(echo ${d} | cut -d/ -f2)
+ cat=$(echo ${d} | cut -d/ -f1)
+ if [ -f "${PORTAGE_DB}/${cat}/${pkg}/CONTENTS" ] ; then
+ do_pkg ${pkg} ${cat}
+ elif [ -d "${PORTAGE_DB}/${cat}/${pkg}" ] ; then
+ ewarn "Package '${cat}/${pkg}' was injected; skipping"
+ else
+ eerror "Unhandled case (${cat}/${pkg}) !"
+ eerror "Please file a bug at http://bugs.gentoo.org/"
+ exit 10
+ fi
+ done
+ fi
+
+done
+
+if [ -z "${PKGSTATS}" ] ; then
+ eerror "No packages found"
+ exit 1
+else
+ echo $'\n'"$(einfo Packages now in ${PKGDIR}:)${PKGSTATS}"
+fi
+if [ ! -z "${PKGERROR}" ] ; then
+ ewarn "The following packages could not be found:"
+ ewarn "${PKGERROR}"
+ exit 2
+fi
+
+exit 0
diff --git a/bin/regenworld b/bin/regenworld
new file mode 100755
index 00000000..2e7f7f84
--- /dev/null
+++ b/bin/regenworld
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/regenworld,v 1.10.2.1 2005/01/11 03:40:57 carpaski Exp $
+
+import sys
+sys.path.insert(0, "/usr/lib/portage/pym")
+
+import portage, string, re
+
+__candidatematcher__ = re.compile("^[0-9]+: \\*\\*\\* emerge ")
+__noncandidatematcher__ = re.compile(" sync( |$)| clean( |$)| search( |$)|--oneshot| unmerge( |$)")
+
+def issyspkg(pkgline):
+ return (pkgline[0] == "*")
+
+def iscandidate(logline):
+ return (__candidatematcher__.match(logline) \
+ and not __noncandidatematcher__.search(logline))
+
+def getpkginfo(logline):
+ logline = re.sub("^[0-9]+: \\*\\*\\* emerge ", "", logline)
+ logline = logline.strip()
+ logline = re.sub("(\\S+\\.(ebuild|tbz2))|(--\\S+)|inject ", "", logline)
+ return logline.strip()
+
+__uniqlist__ = []
+def isunwanted(pkgline):
+ if pkgline in ["world", "system", "depclean", "info", "regen", ""]:
+ return False
+ elif pkgline in __uniqlist__:
+ return False
+ elif not re.search("^[a-zA-Z<>=~]", pkgline):
+ return False
+ else:
+ __uniqlist__.append(pkgline)
+ return True
+
+# show a little description if we have arguments
+if len(sys.argv) >= 2 and sys.argv[1] in ["-h", "--help"]:
+ print "This script regenerates the portage world file by checking the portage"
+ print "logfile for all actions that you've done in the past. It ignores any"
+ print "arguments except --help. It is recommended that you make a backup of"
+ print "your existing world file (%s) before using this tool." % portage.WORLD_FILE
+ sys.exit(0)
+
+worldlist = portage.grabfile(portage.WORLD_FILE)
+syslist = portage.settings.packages
+syslist = filter(issyspkg, syslist)
+
+logfile = portage.grabfile("/var/log/emerge.log")
+biglist = filter(iscandidate, logfile)
+biglist = map(getpkginfo, biglist)
+tmplist = []
+for l in biglist:
+ tmplist += l.split()
+biglist = filter(isunwanted, tmplist)
+#for p in biglist:
+# print p
+#sys.exit(0)
+
+# resolving virtuals
+realsyslist = []
+for mykey in syslist:
+ # drop the asterix
+ mykey = mykey[1:]
+ #print "candidate:",mykey
+ mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
+ if mylist:
+ mykey=portage.cpv_getkey(mylist[0])
+ if mykey not in realsyslist:
+ realsyslist.append(mykey)
+
+for mykey in biglist:
+ #print "checking:",mykey
+ try:
+ mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
+ except KeyError:
+ if "--debug" in sys.argv:
+ print "* ignoring broken log entry for %s (likely injected)" % mykey
+ except ValueError, e:
+ print "* %s is an ambigous package name, candidates are:\n%s" % (mykey, e)
+ continue
+ if mylist:
+ #print "mylist:",mylist
+ myfavkey=portage.cpv_getkey(mylist[0])
+ if (myfavkey not in realsyslist) and (myfavkey not in worldlist):
+ print "add to world:",myfavkey
+ worldlist.append(myfavkey)
+
+myfile=open(portage.WORLD_FILE, "w")
+myfile.write(string.join(worldlist, '\n')+'\n')
+myfile.close()
diff --git a/bin/repoman b/bin/repoman
new file mode 100755
index 00000000..40607d7a
--- /dev/null
+++ b/bin/repoman
@@ -0,0 +1,1522 @@
+#!/usr/bin/python -O
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/repoman,v 1.98.2.23 2005/06/18 01:00:43 vapier Exp $
+
+# Next to do: dep syntax checking in mask files
+# Then, check to make sure deps are satisfiable (to avoid "can't find match for" problems)
+# that last one is tricky because multiple profiles need to be checked.
+
+import os,sys,shutil
+exename=os.path.basename(sys.argv[0])
+os.environ["PORTAGE_CALLER"]="repoman"
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+version="1.2"
+
+import string,signal,re,pickle,tempfile
+
+import portage
+import portage_checksum
+import portage_const
+import portage_dep
+import cvstree
+import time
+from output import *
+#bold, darkgreen, darkred, green, red, turquoise, yellow
+
+from commands import getstatusoutput
+from fileinput import input
+from grp import getgrnam
+from stat import *
+
+
+def err(txt):
+ print exename+": "+txt
+ sys.exit(1)
+
+def exithandler(signum=None,frame=None):
+ sys.stderr.write("\n"+exename+": Interrupted; exiting...\n")
+ sys.exit(1)
+ os.kill(0,signal.SIGKILL)
+signal.signal(signal.SIGINT,exithandler)
+
+REPOROOTS=["gentoo-x86"]
+modes=["scan","fix","full","help","commit","last","lfull"]
+shortmodes={"ci":"commit"}
+modeshelp={
+"scan" :"Scan current directory tree for QA issues (default)",
+"fix" :"Fix those issues that can be fixed (stray digests, missing digests)",
+"full" :"Scan current directory tree for QA issues (full listing)",
+"help" :"Show this screen",
+"commit":"Scan current directory tree for QA issues; if OK, commit via cvs",
+"last" :"Remember report from last run",
+"lfull" :"Remember report from last run (full listing)"
+}
+options=["--pretend","--help","--commitmsg","--commitmsgfile","--verbose","--xmlparse","--ignore-other-arches","--include-masked"]
+shortoptions={"-m":"--commitmsg","-M":"--commitmsgfile","-p":"--pretend","-v":"--verbose","-x":"--xmlparse","-I":"--ignore-other-arches"}
+optionshelp={
+"--pretend":"Don't actually perform commit or fix steps; just show what would be done (always enabled when not started in a CVS tree).",
+"--help" :"Show this screen",
+"--commitmsg" :"Adds a commit message via the command line.",
+"--commitmsgfile":"Adds a commit message from a file given on the command line.",
+"--ignore-other-arches": "Instructs repoman to ignore arches that are not relevent to the committing arch. REPORT/FIX issues you work around.",
+"--verbose":"Displays every package name while checking",
+"--xmlparse":"Forces the metadata.xml parse check to be carried out",
+"--include-masked":"Includes masked packages in scans at category or tree level"
+}
+
+qahelp={
+ "CVS/Entries.IO_error":"Attempting to commit, and an IO error was encountered access the Entries file",
+ "digest.partial":"Digest files do not contain all corresponding URI elements",
+ "digest.assumed":"Existing digest must be assumed correct (Package level only)",
+ "digest.unused":"Digest entry has no matching SRC_URI entry",
+ "digest.fail":"Digest does not match the specified local file",
+ "digest.stray":"Digest files that do not have a corresponding ebuild",
+ "digest.missing":"Digest files that are missing (ebuild exists, digest doesn't)",
+ "digest.disjointed":"Digests not added to cvs when the matching ebuild has been added",
+ "digest.notadded":"Digests that exist but have not been added to cvs",
+ "digest.unmatch":"Digests which are incomplete (please check if your USE/ARCH includes all files)",
+ "ebuild.invalidname":"Ebuild files with a non-parseable or syntactically incorrect name",
+ "ebuild.namenomatch":"Ebuild files that do not have the same name as their parent directory",
+ "changelog.missing":"Missing ChangeLog files",
+ "ebuild.disjointed":"Ebuilds not added to cvs when the matching digest has been added",
+ "ebuild.notadded":"Ebuilds that exist but have not been added to cvs",
+ "changelog.notadded":"ChangeLogs that exist but have not been added to cvs",
+ "filedir.missing":"Package lacks a files directory",
+ "file.executable":"Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do note need the executable bit",
+ "file.size":"Files in the files directory must be under 20k",
+ "KEYWORDS.missing":"Ebuilds that have a missing KEYWORDS variable",
+ "LICENSE.missing":"Ebuilds that have a missing LICENSE variable",
+ "DESCRIPTION.missing":"Ebuilds that have a missing DESCRIPTION variable",
+ "SLOT.missing":"Ebuilds that have a missing SLOT variable",
+ "HOMEPAGE.missing":"Ebuilds that have a missing HOMEPAGE variable",
+ "DEPEND.bad":"User-visible ebuilds with bad DEPEND settings (matched against *visible* ebuilds)",
+ "RDEPEND.bad":"User-visible ebuilds with bad RDEPEND settings (matched against *visible* ebuilds)",
+ "PDEPEND.bad":"User-visible ebuilds with bad PDEPEND settings (matched against *visible* ebuilds)",
+ "DEPEND.badmasked":"Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds)",
+ "RDEPEND.badmasked":"Masked ebuilds with RDEPEND settings (matched against *all* ebuilds)",
+ "PDEPEND.badmasked":"Masked ebuilds with PDEPEND settings (matched against *all* ebuilds)",
+ "DEPEND.badindev":"User-visible ebuilds with bad DEPEND settings (matched against *visible* ebuilds) in developing arch",
+ "RDEPEND.badindev":"User-visible ebuilds with bad RDEPEND settings (matched against *visible* ebuilds) in developing arch",
+ "PDEPEND.badindev":"User-visible ebuilds with bad PDEPEND settings (matched against *visible* ebuilds) in developing arch",
+ "DEPEND.badmaskedindev":"Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds) in developing arch",
+ "RDEPEND.badmaskedindev":"Masked ebuilds with RDEPEND settings (matched against *all* ebuilds) in developing arch",
+ "PDEPEND.badmaskedindev":"Masked ebuilds with PDEPEND settings (matched against *all* ebuilds) in developing arch",
+ "DEPEND.syntax":"Syntax error in DEPEND (usually an extra/missing space/parenthesis)",
+ "RDEPEND.syntax":"Syntax error in RDEPEND (usually an extra/missing space/parenthesis)",
+ "PDEPEND.syntax":"Syntax error in PDEPEND (usually an extra/missing space/parenthesis)",
+ "LICENSE.syntax":"Syntax error in LICENSE (usually an extra/missing space/parenthesis)",
+ "ebuild.syntax":"Error generating cache entry for ebuild; typically caused by ebuild syntax error",
+ "ebuild.output":"A simple sourcing of the ebuild produces output; this breaks ebuild policy.",
+ "ebuild.nesteddie":"Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild.",
+ "variable.readonly":"Assigning a readonly variable",
+ "IUSE.invalid":"This build has a variable in IUSE that is not in the use.desc or use.local.desc file",
+ "LICENSE.invalid":"This ebuild is listing a license that doesnt exist in portages license/ dir.",
+ "KEYWORDS.invalid":"This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found",
+ "ebuild.nostable":"There are no ebuilds that are marked as stable for your ARCH",
+ "ebuild.allmasked":"All ebuilds are masked for this package (Package level only)",
+ "ebuild.majorsyn":"This ebuild has a major syntax error that may cause the ebuild to fail partially or fully",
+ "ebuild.minorsyn":"This ebuild has a minor syntax error that contravenes gentoo coding style",
+ "ebuild.badheader":"This ebuild has a malformed header",
+ "metadata.missing":"Missing metadata.xml files",
+ "metadata.bad":"Bad metadata.xml files",
+ "virtual.versioned":"PROVIDE contains virtuals with versions",
+ "virtual.exists":"PROVIDE contains existing package names",
+ "virtual.unavailable":"PROVIDE contains a virtual which contains no profile default"
+}
+
+qacats = qahelp.keys()
+qacats.sort()
+
+qawarnings=[
+"changelog.missing",
+"changelog.notadded",
+"ebuild.notadded",
+"ebuild.nostable",
+"ebuild.allmasked",
+"ebuild.nesteddie",
+"digest.assumed",
+"digest.notadded",
+"digest.disjointed",
+"digest.missing",
+"digest.unused",
+"DEPEND.badmasked","RDEPEND.badmasked","PDEPEND.badmasked",
+"DEPEND.badindev","RDEPEND.badindev","PDEPEND.badindev",
+"DEPEND.badmaskedindev","RDEPEND.badmaskedindev","PDEPEND.badmaskedindev",
+"IUSE.invalid",
+"ebuild.minorsyn",
+"ebuild.badheader",
+"file.size",
+"metadata.missing",
+"metadata.bad",
+"virtual.versioned"
+]
+
+missingvars=["KEYWORDS","LICENSE","DESCRIPTION","HOMEPAGE","SLOT"]
+allvars=portage.auxdbkeys
+commitmessage=None
+commitmessagefile=None
+for x in missingvars:
+ x += ".missing"
+ if x not in qacats:
+ print "* missingvars values need to be added to qahelp ("+x+")"
+ qacats.append(x)
+ qawarnings.append(x)
+
+
+def err(txt):
+ print exename+": "+txt
+ sys.exit(1)
+
+ven_cat = r'[\w0-9-]+' # Category
+ven_nam = r'([+a-z0-9-]+(?:[+_a-z0-9-]*[+a-z0-9-]+)*)' # Name
+ven_ver = r'((?:\d+\.)*\d+[a-z]?)' # Version
+ven_suf = r'(_(alpha\d*|beta\d*|pre\d*|rc\d*|p\d+))?' # Suffix
+ven_rev = r'(-r\d+)?' # Revision
+
+ven_string=ven_cat+'/'+ven_nam+'-'+ven_ver+ven_suf+ven_rev
+valid_ebuild_name_re=re.compile(ven_string+'$', re.I)
+valid_ebuild_filename_re=re.compile(ven_string+'\.ebuild$', re.I)
+
+repoman_settings = portage.config(clone=portage.settings)
+
+def valid_ebuild_name(name):
+ """(name) --- Checks to ensure that the package name meets portage specs.
+ Return 1 if valid, 0 if not."""
+ # Handle either a path to the ebuild, or cat/pkg-ver string
+ if (len(name) > 7) and (name[-7:] == ".ebuild"):
+ if valid_ebuild_filename_re.match(name):
+ return 1
+ else:
+ if valid_ebuild_name_re.match(name):
+ return 1
+ return 0
+
+
+def help():
+ print
+ print green(exename+" "+version)
+ print " \"Quality is job zero.\""
+ print " Copyright 1999-2005 Gentoo Foundation"
+ print " Distributed under the terms of the GNU General Public License v2"
+ print
+ print bold(" Usage:"),turquoise(exename),"[",green("option"),"] [",green("mode"),"]"
+ print bold(" Modes:"),turquoise("scan (default)"),
+ for x in modes[1:]:
+ print "|",turquoise(x),
+ print "\n"
+ print " "+green(string.ljust("Option",20)+" Description")
+ for x in options:
+ print " "+string.ljust(x,20),optionshelp[x]
+ print
+ print " "+green(string.ljust("Mode",20)+" Description")
+ for x in modes:
+ print " "+string.ljust(x,20),modeshelp[x]
+ print
+ print " "+green(string.ljust("QA keyword",20)+" Description")
+ for x in qacats:
+ print " "+string.ljust(x,20),qahelp[x]
+ print
+ sys.exit(1)
+
+def last():
+ try:
+ #Retrieve and unpickle stats and fails from saved files
+ savedf=open('/var/cache/edb/repo.stats','r')
+ stats = pickle.load(savedf)
+ savedf.close()
+ savedf=open('/var/cache/edb/repo.fails','r')
+ fails = pickle.load(savedf)
+ savedf.close()
+ except SystemExit, e:
+ raise # Need to propogate this
+ except:
+ err("Error retrieving last repoman run data; exiting.")
+
+ #dofail will be set to 1 if we have failed in at least one non-warning category
+ dofail=0
+ #dowarn will be set to 1 if we tripped any warnings
+ dowarn=0
+ #dofull will be set if we should print a "repoman full" informational message
+ dofull=0
+
+ print
+ print green("RepoMan remembers...")
+ print
+ for x in qacats:
+ if stats[x]:
+ dowarn=1
+ if x not in qawarnings:
+ dofail=1
+ else:
+ if mymode!="lfull":
+ continue
+ print " "+string.ljust(x,20),
+ if stats[x]==0:
+ print green(`stats[x]`)
+ continue
+ elif x in qawarnings:
+ print yellow(`stats[x]`)
+ else:
+ print red(`stats[x]`)
+ if mymode!="lfull":
+ if stats[x]<12:
+ for y in fails[x]:
+ print " "+y
+ else:
+ dofull=1
+ else:
+ for y in fails[x]:
+ print " "+y
+ print
+ if dofull:
+ print bold("Note: type \"repoman lfull\" for a complete listing of repomans last run.")
+ print
+ if dowarn and not dofail:
+ print green("RepoMan sez:"),"\"You only gave me a partial QA payment last time?\nI took it, but I wasn't happy.\""
+ elif not dofail:
+ print green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\""
+ print
+ sys.exit(1)
+
+mymode=None
+myoptions=[]
+if len(sys.argv)>1:
+ x=1
+ while x < len(sys.argv):
+ if sys.argv[x] in shortmodes.keys():
+ sys.argv[x]=shortmodes[sys.argv[x]]
+ if sys.argv[x] in modes:
+ if mymode==None:
+ mymode=sys.argv[x]
+ else:
+ err("Please specify either \""+mymode+"\" or \""+sys.argv[x]+"\", but not both.")
+ elif sys.argv[x] in options+shortoptions.keys():
+ optionx=sys.argv[x]
+ if optionx in shortoptions.keys():
+ optionx = shortoptions[optionx]
+ if (optionx=="--commitmsg") and (len(sys.argv)>=(x+1)):
+ commitmessage=sys.argv[x+1]
+ x=x+1
+ elif (optionx=="--commitmsgfile") and (len(sys.argv)>=(x+1)):
+ commitmessagefile=sys.argv[x+1]
+ x=x+1
+ elif optionx not in myoptions:
+ myoptions.append(optionx)
+ else:
+ err("\""+sys.argv[x]+"\" is not a valid mode or option.")
+ x=x+1
+if mymode==None:
+ mymode="scan"
+if mymode=="help" or ("--help" in myoptions):
+ help()
+if mymode=="last" or (mymode=="lfull"):
+ last()
+if mymode=="commit" and "--include-masked" not in myoptions:
+ myoptions.append("--include-masked")
+
+isCvs=False
+myreporoot=None
+if os.path.isdir("CVS"):
+ repoman_settings["PORTDIR_OVERLAY"]=""
+ if "cvs" not in portage.features:
+ print
+ print
+ print red('!!! You do not have ')+bold('FEATURES="cvs" ')+red("enabled...")
+ print red("!!! ")+bold("Adding \"cvs\" to FEATURES")
+ print
+ os.environ["FEATURES"]=repoman_settings["FEATURES"]+" cvs"
+
+ try:
+ isCvs=True
+ myrepofile=open("CVS/Repository")
+ myreporoot=myrepofile.readline()[:-1]
+ myrepofile.close()
+ myrepofile=open("CVS/Root")
+ myreporootpath=string.split(myrepofile.readline()[:-1], ":")[-1]
+ myrepofile.close()
+ if myreporootpath == myreporoot[:len(myreporootpath)]:
+ # goofy os x cvs co.
+ myreporoot = myreporoot[len(myreporootpath):]
+ while myreporoot and myreporoot[0] == '/':
+ myreporoot = myreporoot[1:]
+ except SystemExit, e:
+ raise # Need to propogate this
+ except:
+ err("Error grabbing repository information; exiting.")
+ myreporootpath=os.path.normpath(myreporootpath)
+ if myreporootpath=="/space/cvsroot":
+ print
+ print
+ print red("You're using the wrong cvsroot. For Manifests to be correct, you must")
+ print red("use the same base cvsroot path that the servers use. Please try the")
+ print red("following script to remedy this:")
+ print
+ print "cd my_cvs_tree"
+ print
+ print "rm -Rf [a-z]*"
+ print "cvs up"
+ print
+ if portage.userland=="BSD" or portage.userland=="Darwin":
+ print "find ./ -type f -regex '.*/CVS/Root$' -print0 | xargs -0 sed \\"
+ else:
+ print "find ./ -type f -regex '.*/CVS/Root$' -print0 | xargs -0r sed \\"
+ fi
+ print " -i 's:/space/cvsroot$:/home/cvsroot:'"
+ print
+ print red("You must clear and re-update your tree as all header tags will cause")
+ print red("problems in manifests for all rsync and /home/cvsroot users.")
+ print
+ print "You should do this to any other gentoo trees your have as well,"
+ print "excluding the deletions. 'gentoo-src' should be /home/cvsroot."
+ print
+ sys.exit(123)
+
+if not "--pretend" in myoptions and not isCvs:
+ print
+ print darkgreen("Not in a CVS repository; enabling pretend mode.")
+ myoptions.append("--pretend");
+
+
+def have_profile_dir(path, maxdepth=3):
+ while path != "/" and maxdepth:
+ if os.path.exists(path + "/profiles/package.mask"):
+ return path
+ path = os.path.normpath(path + "/..")
+ maxdepth -= 1
+
+portdir=None
+portdir_overlay=None
+mydir=os.getcwd()
+if mydir[-1] != "/":
+ mydir += "/"
+
+for overlay in repoman_settings["PORTDIR_OVERLAY"].split():
+ if overlay[-1] != "/":
+ overlay += "/"
+ if mydir[:len(overlay)] == overlay:
+ portdir_overlay = overlay
+ subdir = mydir[len(overlay):]
+ if subdir and subdir[-1] != "/":
+ subdir += "/"
+ if have_profile_dir(mydir, subdir.count("/")):
+ portdir = portdir_overlay
+ break
+
+if not portdir_overlay:
+ if (repoman_settings["PORTDIR"]+"/")[:len(mydir)] == mydir:
+ portdir_overlay = repoman_settings["PORTDIR"]
+ else:
+ portdir_overlay = have_profile_dir(mydir)
+ portdir = portdir_overlay
+
+if not portdir_overlay:
+ print darkred("Unable to determine PORTDIR.")
+ sys.exit(1)
+
+if not portdir:
+ portdir = repoman_settings["PORTDIR"]
+
+if portdir[-1] == "/":
+ portdir = portdir[:-1]
+if portdir_overlay[-1] == "/":
+ portdir_overlay = portdir_overlay[:-1]
+
+os.environ["PORTDIR"] = portdir
+if portdir_overlay != portdir:
+ os.environ["PORTDIR_OVERLAY"] = portdir_overlay
+else:
+ os.environ["PORTDIR_OVERLAY"] = ""
+
+print "\nSetting paths:"
+print "PORTDIR = \""+os.environ["PORTDIR"]+"\""
+print "PORTDIR_OVERLAY = \""+os.environ["PORTDIR_OVERLAY"]+"\""
+
+
+reload(portage)
+repoman_settings = portage.config(clone=portage.settings)
+
+if not myreporoot:
+ myreporoot = os.path.basename(portdir_overlay)
+ myreporoot += mydir[len(portdir_overlay):-1]
+
+if isCvs:
+ reporoot=None
+ for x in REPOROOTS:
+ if myreporoot[0:len(x)]==x:
+ reporoot=myreporoot
+ if not reporoot:
+ err("Couldn't recognize repository type. Supported repositories:\n"+repr(REPOROOTS))
+reposplit=string.split(myreporoot,"/")
+repolevel=len(reposplit)
+
+# check if it's in $PORTDIR/$CATEGORY/$PN , otherwise bail if commiting.
+# Reason for this is if they're trying to commit in just $FILESDIR/*, the Manifest needs updating.
+# this check ensure that repoman knows where it is, and the manifest recommit is at least possible.
+if mymode == "commit" and repolevel not in [1,2,3]:
+ print red("***")+" Commit attempts *must* be from within a cvs co, category, or package directory."
+ print red("***")+" Attempting to commit from a packages files directory will be blocked for instance."
+ print red("***")+" This is intended behaviour, to ensure the manifest is recommited for a package."
+ print red("***")
+ err("Unable to identify level we're commiting from for %s" % string.join(reposplit,'/'))
+
+if repolevel == 3 and "--include-masked" not in myoptions:
+ myoptions.append("--include-masked")
+
+startdir=os.getcwd()
+
+for x in range(0,repolevel-1):
+ os.chdir("..")
+repodir=os.getcwd()
+os.chdir(startdir)
+
+def caterror(mycat):
+ err(mycat+" is not an official category. Skipping QA checks in this directory.\nPlease ensure that you add "+catdir+" to "+repodir+"/profiles/categories\nif it is a new category.")
+print
+if "--pretend" in myoptions:
+ print green("RepoMan does a once-over of the neighborhood...")
+else:
+ print green("RepoMan scours the neighborhood...")
+
+# retreive local USE list
+luselist={}
+try:
+ mylist=portage.grabfile(portdir+"/profiles/use.local.desc")
+ for mypos in range(0,len(mylist)):
+ mysplit=mylist[mypos].split()[0]
+ myuse=string.split(mysplit,":")
+ if len(myuse)==2:
+ if not luselist.has_key(myuse[0]):
+ luselist[myuse[0]] = []
+ luselist[myuse[0]].append(myuse[1])
+except SystemExit, e:
+ raise # Need to propogate this
+except:
+ err("Couldn't read from use.local.desc")
+
+# setup a uselist from portage
+uselist=[]
+try:
+ uselist=portage.grabfile(portdir+"/profiles/use.desc")
+ for l in range(0,len(uselist)):
+ uselist[l]=string.split(uselist[l])[0]
+except SystemExit, e:
+ raise # Need to propogate this
+except:
+ err("Couldn't read USE flags from use.desc")
+
+# retrieve a list of current licenses in portage
+liclist=portage.listdir(portdir+"/licenses")
+if not liclist:
+ err("Couldn't find licenses?")
+
+# retrieve list of offical keywords
+try:
+ kwlist=portage.grabfile(portdir+"/profiles/arch.list")
+except SystemExit, e:
+ raise # Need to propogate this
+except:
+ err("Couldn't read KEYWORDS from arch.list")
+if not kwlist:
+ kwlist=["alpha","arm","hppa","mips","ppc","sparc","x86"]
+
+scanlist=[]
+if repolevel==2:
+ #we are inside a category directory
+ catdir=reposplit[-1]
+ if catdir not in repoman_settings.categories:
+ caterror(catdir)
+ mydirlist=os.listdir(startdir)
+ for x in mydirlist:
+ if x=="CVS":
+ continue
+ if os.path.isdir(startdir+"/"+x):
+ scanlist.append(catdir+"/"+x)
+elif repolevel==1:
+ for x in repoman_settings.categories:
+ if not os.path.isdir(startdir+"/"+x):
+ continue
+ for y in os.listdir(startdir+"/"+x):
+ if y=="CVS":
+ continue
+ if os.path.isdir(startdir+"/"+x+"/"+y):
+ scanlist.append(x+"/"+y)
+elif repolevel==3:
+ catdir = reposplit[-2]
+ if catdir not in repoman_settings.categories:
+ caterror(catdir)
+ scanlist.append(catdir+"/"+reposplit[-1])
+
+profiles={}
+descfile=portdir+"/profiles/profiles.desc"
+if os.path.exists(descfile):
+ for x in portage.grabfile(descfile):
+ if x[0]=="#":
+ continue
+ arch=string.split(x)
+ if len(arch)!=3:
+ print "wrong format: \""+red(x)+"\" in "+descfile
+ continue
+ if not os.path.isdir(portdir+"/profiles/"+arch[1]):
+ print "Invalid "+arch[2]+" profile ("+arch[1]+") for arch "+arch[0]
+ continue
+ if profiles.has_key(arch[0]):
+ profiles[arch[0]]+= [[arch[1], arch[2]]]
+ else:
+ profiles[arch[0]] = [[arch[1], arch[2]]]
+
+ for x in portage.archlist:
+ if x[0] == "~":
+ continue
+ if not profiles.has_key(x):
+ print red("\""+x+"\" doesn't have a valid profile listed in profiles.desc.")
+ print red("You need to either \"cvs update\" your profiles dir or follow this")
+ print red("up with the "+x+" team.")
+ print
+else:
+ print red("profiles.desc does not exist: "+descfile)
+ print red("You need to do \"cvs update\" in profiles dir.")
+ print
+ sys.exit(1)
+
+
+stats={}
+fails={}
+#objsadded records all object being added to cvs
+objsadded=[]
+for x in qacats:
+ stats[x]=0
+ fails[x]=[]
+xmllint_capable = False
+if getstatusoutput('which xmllint')[0] != 0:
+ print red("!!! xmllint not found. Can't check metadata.xml.\n")
+ if "--xmlparse" in myoptions or repolevel==3:
+ print red("!!!")+" sorry, xmllint is needed. failing\n"
+ sys.exit(1)
+else:
+ #hardcoded paths/urls suck. :-/
+ must_fetch=1
+ backup_exists=0
+ try:
+ # if it's been over a week since fetching (or the system clock is fscked), grab an updated copy of metadata.dtd
+ # clock is fscked or it's been a week. time to grab a new one.
+ ct=os.stat(portage.CACHE_PATH + '/metadata.dtd')[ST_CTIME]
+ if abs(time.time() - ct) > (60*60*24*7):
+ # don't trap the exception, we're watching for errno 2 (file not found), anything else is a bug.
+ backup_exists=1
+ else:
+ must_fetch=0
+
+ except (OSError,IOError), e:
+ if e.errno != 2:
+ print red("!!!")+" caught exception '%s' for %s/metadata.dtd, bailing" % (str(e), portage.CACHE_PATH)
+ sys.exit(1)
+
+ if must_fetch:
+ print
+ print green("***")+" the local copy of metadata.dtd needs to be refetched, doing that now"
+ print
+ try:
+ if os.path.exists(repoman_settings["DISTDIR"]+'/metadata.dtd'):
+ os.remove(repoman_settings["DISTDIR"]+'/metadata.dtd')
+ val=portage.fetch(['http://www.gentoo.org/dtd/metadata.dtd'],repoman_settings,fetchonly=0, \
+ try_mirrors=0)
+ if val:
+ if backup_exists:
+ os.remove(portage.CACHE_PATH+'/metadata.dtd')
+ shutil.copy(repoman_settings["DISTDIR"]+'/metadata.dtd',portage.CACHE_PATH+'/metadata.dtd')
+ os.chown(portage.CACHE_PATH+'/metadata.dtd',os.getuid(),portage.portage_gid)
+ os.chmod(portage.CACHE_PATH+'/metadata.dtd',0664)
+
+
+ except SystemExit, e:
+ raise # Need to propogate this
+ except Exception,e:
+ print
+ print red("!!!")+" attempting to fetch 'http://www.gentoo.org/dtd/metadata.dtd', caught"
+ print red("!!!")+" exception '%s' though." % str(e)
+ val=0
+ if not val:
+ print red("!!!")+" fetching new metadata.dtd failed, aborting"
+ sys.exit(1)
+ #this can be problematic if xmllint changes their output
+ xmllint_capable=True
+
+
+arch_caches={}
+for x in scanlist:
+ #ebuilds and digests added to cvs respectively.
+ if "--verbose" in myoptions:
+ print "checking package " + x
+ eadded=[]
+ dadded=[]
+ cladded=0
+ catdir,pkgdir=x.split("/")
+ checkdir=repodir+"/"+x
+ checkdirlist=os.listdir(checkdir)
+ ebuildlist=[]
+ for y in checkdirlist:
+ if y[-7:]==".ebuild":
+ ebuildlist.append(y[:-7])
+ if y in ["Manifest","ChangeLog","metadata.xml"]:
+ if os.stat(checkdir+"/"+y)[0] & 0x0248:
+ stats["file.executable"] += 1
+ fails["file.executable"].append(checkdir+"/"+y)
+ digestlist=[]
+ if isCvs:
+ try:
+ mystat=os.stat(checkdir+"/files")[0]
+ if len(ebuildlist) and not S_ISDIR(mystat):
+ raise Exception
+ except SystemExit, e:
+ raise # Need to propogate this
+ except:
+ stats["filedir.missing"] += 1
+ fails["filedir.missing"].append(checkdir)
+ continue
+ try:
+ myf=open(checkdir+"/CVS/Entries","r")
+ myl=myf.readlines()
+ for l in myl:
+ if l[0]!="/":
+ continue
+ splitl=l[1:].split("/")
+ if not len(splitl):
+ continue
+ objsadded.append(splitl[0])
+ if splitl[0][-7:]==".ebuild":
+ eadded.append(splitl[0][:-7])
+ if splitl[0]=="ChangeLog":
+ cladded=1
+ except IOError:
+ if mymode=="commit":
+ stats["CVS/Entries.IO_error"] += 1
+ fails["CVS/Entries.IO_error"].append(checkdir+"/CVS/Entries")
+ continue
+
+ try:
+ myf=open(checkdir+"/files/CVS/Entries","r")
+ myl=myf.readlines()
+ for l in myl:
+ if l[0]!="/":
+ continue
+ splitl=l[1:].split("/")
+ if not len(splitl):
+ continue
+ objsadded.append(splitl[0])
+ if splitl[0][:7]=="digest-":
+ dadded.append(splitl[0][7:])
+ except IOError:
+ if mymode=="commit":
+ stats["CVS/Entries.IO_error"] += 1
+ fails["CVS/Entries.IO_error"].append(checkdir+"/files/CVS/Entries")
+ continue
+
+ if os.path.exists(checkdir+"/files"):
+ filesdirlist=os.listdir(checkdir+"/files")
+ for y in filesdirlist:
+ if y[:7]=="digest-":
+ if y[7:] not in dadded:
+ #digest not added to cvs
+ stats["digest.notadded"]=stats["digest.notadded"]+1
+ fails["digest.notadded"].append(x+"/files/"+y)
+ if y[7:] in eadded:
+ stats["digest.disjointed"]=stats["digest.disjointed"]+1
+ fails["digest.disjointed"].append(x+"/files/"+y)
+
+ if os.stat(checkdir+"/files/"+y)[0] & 0x0248:
+ stats["file.executable"] += 1
+ fails["file.executable"].append(x+"/files/"+y)
+
+ mydigests=portage.digestParseFile(checkdir+"/files/"+y)
+
+ mykey = catdir + "/" + y[7:]
+ if y[7:] not in ebuildlist:
+ #stray digest
+ if mymode=="fix":
+ if "--pretend" in myoptions:
+ print "(cd "+repodir+"/"+x+"/files; cvs rm -f "+y+")"
+ else:
+ os.system("(cd "+repodir+"/"+x+"/files; cvs rm -f "+y+")")
+ else:
+ stats["digest.stray"]=stats["digest.stray"]+1
+ fails["digest.stray"].append(x+"/files/"+y)
+ else:
+ # We have an ebuild
+ myuris,myfiles = portage.db["/"]["porttree"].dbapi.getfetchlist(mykey,all=True)
+ for entry in mydigests.keys():
+ if entry not in myfiles:
+ stats["digest.unused"] += 1
+ fails["digest.unused"].append(y+"::"+entry)
+ uri_dict = {}
+ for myu in myuris:
+ myubn = os.path.basename(myu)
+ if myubn not in uri_dict:
+ uri_dict[myubn] = [myu]
+ else:
+ uri_dict[myubn] += [myu]
+
+ for myf in uri_dict:
+ myff = repoman_settings["DISTDIR"] + "/" + myf
+ if not mydigests.has_key(myf):
+ uri_settings = portage.config(clone=repoman_settings)
+ if mymode == "fix":
+ if not portage.fetch(uri_dict[myf], uri_settings):
+ stats["digest.unmatch"] += 1
+ fails["digest.unmatch"].append(y+"::"+myf)
+ else:
+ eb_name,eb_location = portage.db["/"]["porttree"].dbapi.findname2(mykey)
+ portage.doebuild(eb_name, "digest", "/", uri_settings)
+ else:
+ stats["digest.partial"] += 1
+ fails["digest.partial"].append(y+"::"+myf)
+ else:
+ if os.path.exists(myff):
+ if not portage_checksum.verify_all(myff, mydigests[myf]):
+ stats["digest.fail"] += 1
+ fails["digest.fail"].append(y+"::"+myf)
+ elif repolevel == 3:
+ stats["digest.assumed"] += 1
+ fails["digest.assumed"].append(y+"::"+myf)
+
+ # recurse through files directory
+ # use filesdirlist as a stack, appending directories as needed so people can't hide > 20k files in a subdirectory.
+ while filesdirlist:
+ y = filesdirlist.pop(0)
+ try:
+ mystat = os.stat(checkdir+"/files/"+y)
+ except OSError, oe:
+ if oe.errno == 2:
+ # don't worry about it. it likely was removed via fix above.
+ continue
+ else:
+ raise oe
+ if S_ISDIR(mystat.st_mode):
+ for z in os.listdir(checkdir+"/files/"+y):
+ filesdirlist.append(y+"/"+z)
+ # current policy is no files over 20k, this is the check.
+ elif mystat.st_size > 20480:
+ stats["file.size"] += 1
+ fails["file.size"].append("("+ str(mystat.st_size/1024) + "K) "+x+"/files/"+y)
+
+ if "ChangeLog" not in checkdirlist:
+ stats["changelog.missing"]+=1
+ fails["changelog.missing"].append(x+"/ChangeLog")
+
+ #metadata.xml file check
+ if "metadata.xml" not in checkdirlist:
+ stats["metadata.missing"]+=1
+ fails["metadata.missing"].append(x+"/metadata.xml")
+ #metadata.xml parse check
+ else:
+ #Only carry out if in package directory or check forced
+ if xmllint_capable:
+ st=getstatusoutput("xmllint --nonet --noout --dtdvalid %s/metadata.dtd %s/metadata.xml" % (portage.CACHE_PATH, checkdir))
+ if st[0] != 0:
+ for z in st[1].split("\n"):
+ print red("!!! ")+z
+ stats["metadata.bad"]+=1
+ fails["metadata.bad"].append(x+"/metadata.xml")
+
+ allmasked = True
+
+ for y in ebuildlist:
+ if os.stat(checkdir+"/"+y+".ebuild")[0] & 0x0248:
+ stats["file.executable"] += 1
+ fails["file.executable"].append(x+"/"+y+".ebuild")
+ if y not in eadded:
+ #ebuild not added to cvs
+ stats["ebuild.notadded"]=stats["ebuild.notadded"]+1
+ fails["ebuild.notadded"].append(x+"/"+y+".ebuild")
+ if y in dadded:
+ stats["ebuild.disjointed"]=stats["ebuild.disjointed"]+1
+ fails["ebuild.disjointed"].append(x+"/"+y+".ebuild")
+ if not os.path.exists(checkdir+"/files/digest-"+y):
+ if mymode=="fix":
+ if "--pretend" in myoptions:
+ print "You will need to run:"
+ print " /usr/sbin/ebuild "+repodir+"/"+x+"/"+y+".ebuild digest"
+ else:
+ retval=os.system("/usr/sbin/ebuild "+repodir+"/"+x+"/"+y+".ebuild digest")
+ if retval:
+ print "!!! Exiting on ebuild digest (shell) error code:",retval
+ sys.exit(retval)
+ else:
+ stats["digest.missing"]=stats["digest.missing"]+1
+ fails["digest.missing"].append(x+"/files/digest-"+y)
+ myesplit=portage.pkgsplit(y)
+ if myesplit==None or not valid_ebuild_name(x.split("/")[0]+"/"+y):
+ stats["ebuild.invalidname"]=stats["ebuild.invalidname"]+1
+ fails["ebuild.invalidname"].append(x+"/"+y+".ebuild")
+ continue
+ elif myesplit[0]!=pkgdir:
+ print pkgdir,myesplit[0]
+ stats["ebuild.namenomatch"]=stats["ebuild.namenomatch"]+1
+ fails["ebuild.namenomatch"].append(x+"/"+y+".ebuild")
+ continue
+ try:
+ myaux=portage.db["/"]["porttree"].dbapi.aux_get(catdir+"/"+y,allvars,strict=1)
+ except KeyError:
+ stats["ebuild.syntax"]=stats["ebuild.syntax"]+1
+ fails["ebuild.syntax"].append(x+"/"+y+".ebuild")
+ continue
+ except IOError:
+ stats["ebuild.output"]=stats["ebuild.output"]+1
+ fails["ebuild.output"].append(x+"/"+y+".ebuild")
+ continue
+
+ mynewaux = {}
+ for idx in range(len(allvars)):
+ if idx < len(myaux):
+ mynewaux[allvars[idx]] = myaux[idx]
+ else:
+ mynewaux[allvars[idx]] = ""
+ myaux = mynewaux
+
+ # Test for negative logic and bad words in the RESTRICT var.
+ #for x in myaux[allvars.index("RESTRICT")].split():
+ # if x.startswith("no"):
+ # print "Bad RESTRICT value: %s" % x
+
+ myaux["PROVIDE"] = portage_dep.use_reduce(portage_dep.paren_reduce(myaux["PROVIDE"]), matchall=1)
+ myaux["PROVIDE"] = " ".join(portage.flatten(myaux["PROVIDE"]))
+ for myprovide in myaux["PROVIDE"].split():
+ prov_cp = portage.dep_getkey(myprovide)
+ if prov_cp != myprovide:
+ stats["virtual.versioned"]+=1
+ fails["virtual.versioned"].append(x+"/"+y+".ebuild: "+myprovide)
+ prov_pkg = portage.dep_getkey(portage.best(portage.db["/"]["porttree"].dbapi.xmatch("match-all", prov_cp)))
+ if prov_cp == prov_pkg:
+ stats["virtual.exists"]+=1
+ fails["virtual.exists"].append(x+"/"+y+".ebuild: "+prov_cp)
+
+ for pos in range(0,len(missingvars)):
+ if not myaux[missingvars[pos]]:
+ myqakey=missingvars[pos]+".missing"
+ stats[myqakey]=stats[myqakey]+1
+ fails[myqakey].append(x+"/"+y+".ebuild")
+
+ if "--ignore-other-arches" in myoptions:
+ arches=[[repoman_settings["ARCH"], repoman_settings["ARCH"], portage.groups]]
+ else:
+ arches=[]
+ for keyword in myaux["KEYWORDS"].split():
+ if (keyword[0]=="-"):
+ continue
+ elif (keyword[0]=="~"):
+ arches.append([keyword, keyword[1:], [keyword[1:], keyword]])
+ else:
+ arches.append([keyword, keyword, [keyword]])
+ allmasked = False
+
+ baddepsyntax = False
+ badlicsyntax = False
+ catpkg = catdir+"/"+y
+ for mytype in ["DEPEND","RDEPEND","PDEPEND","LICENSE"]:
+ mydepstr = myaux[mytype]
+ if (string.find(mydepstr, " ?") != -1):
+ stats[mytype+".syntax"] += 1
+ fails[mytype+".syntax"].append(catpkg+".ebuild "+mytype+": '?' preceded by space")
+ if mytype != "LICENSE":
+ baddepsyntax = True
+ else:
+ badlicsyntax = True
+ try:
+ # Missing closing parenthesis will result in a ValueError
+ mydeplist=portage_dep.paren_reduce(mydepstr)
+ # Missing opening parenthesis will result in a final "" element
+ if "" in mydeplist or "(" in mydeplist:
+ raise ValueError
+ except ValueError:
+ stats[mytype+".syntax"] += 1
+ fails[mytype+".syntax"].append(catpkg+".ebuild "+mytype+": Mismatched parenthesis")
+ if mytype != "LICENSE":
+ baddepsyntax = True
+ else:
+ badlicsyntax = True
+
+ for keyword,arch,groups in arches:
+ portage.groups=groups
+
+ if not profiles.has_key(arch):
+ # A missing profile will create an error further down
+ # during the KEYWORDS verification.
+ continue
+
+ for prof in profiles[arch]:
+
+ profdir = portdir+"/profiles/"+prof[0]
+
+ portage.profiledir=profdir
+
+ if arch_caches.has_key(prof[0]):
+ dep_settings, portage.portdb, portage.db["/"]["porttree"] = arch_caches[prof[0]]
+ else:
+ os.environ["ACCEPT_KEYWORDS"]="-~"+arch
+ dep_settings=portage.config(config_profile_path=profdir, config_incrementals=portage_const.INCREMENTALS)
+ portage.portdb=portage.portdbapi(portdir, dep_settings)
+ portage.db["/"]["porttree"]=portage.portagetree("/",dep_settings.getvirtuals("/"))
+ arch_caches[prof[0]]=[dep_settings, portage.portdb, portage.db["/"]["porttree"]]
+
+ for myprovide in myaux["PROVIDE"].split():
+ prov_cp = portage.dep_getkey(myprovide)
+ if prov_cp not in dep_settings.virtuals:
+ stats["virtual.unavailable"]+=1
+ fails["virtual.unavailable"].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+prov_cp)
+
+ if not baddepsyntax:
+ ismasked = (catdir+"/"+y not in portage.db["/"]["porttree"].dbapi.xmatch("list-visible",x))
+ if ismasked:
+ if "--include-masked" not in myoptions:
+ continue
+ #we are testing deps for a masked package; give it some lee-way
+ suffix="masked"
+ matchmode="match-all"
+ else:
+ suffix=""
+ matchmode="match-visible"
+
+ if prof[1] == "dev":
+ suffix=suffix+"indev"
+
+ for mytype,mypos in [["DEPEND",len(missingvars)],["RDEPEND",len(missingvars)+1],["PDEPEND",len(missingvars)+2]]:
+
+ mykey=mytype+".bad"+suffix
+ myvalue = myaux[mytype]
+ if not myvalue:
+ continue
+ try:
+ mydep=portage.dep_check(myvalue,portage.db["/"]["porttree"].dbapi,dep_settings,use="all",mode=matchmode)
+ except KeyError, e:
+ stats[mykey]=stats[mykey]+1
+ fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(e[0]))
+ continue
+
+ if mydep[0]==1:
+ if mydep[1]!=[]:
+ #we have some unsolvable deps
+ #remove ! deps, which always show up as unsatisfiable
+ d=0
+ while d<len(mydep[1]):
+ if mydep[1][d][0]=="!":
+ del mydep[1][d]
+ else:
+ d += 1
+ #if we emptied out our list, continue:
+ if not mydep[1]:
+ continue
+ stats[mykey]=stats[mykey]+1
+ fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(mydep[1]))
+ else:
+ stats[mykey]=stats[mykey]+1
+ fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(mydep[1]))
+
+ # this check needs work, it won't catch (\ndie)
+ if not os.system("egrep '^[^#]*\([^)]*\<die\>' "+checkdir+"/"+y+".ebuild >/dev/null 2>&1"):
+ stats["ebuild.nesteddie"]=stats["ebuild.nesteddie"]+1
+ fails["ebuild.nesteddie"].append(x+"/"+y+".ebuild")
+ # uselist checks - global
+ myuse = myaux["IUSE"].split()
+ for mypos in range(len(myuse)-1,-1,-1):
+ if myuse[mypos] and (myuse[mypos] in uselist):
+ del myuse[mypos]
+ # uselist checks - local
+ mykey = portage.dep_getkey(catpkg)
+ if luselist.has_key(mykey):
+ for mypos in range(len(myuse)-1,-1,-1):
+ if myuse[mypos] and (myuse[mypos] in luselist[mykey]):
+ del myuse[mypos]
+ for mypos in range(len(myuse)):
+ stats["IUSE.invalid"]=stats["IUSE.invalid"]+1
+ fails["IUSE.invalid"].append(x+"/"+y+".ebuild: %s" % myuse[mypos])
+
+ # license checks
+ if not badlicsyntax:
+ myuse = myaux["LICENSE"]
+ # Parse the LICENSE variable, remove USE conditions and
+ # flatten it.
+ myuse=portage_dep.use_reduce(portage_dep.paren_reduce(myuse), matchall=1)
+ myuse=portage.flatten(myuse)
+ # Check each entry to ensure that it exists in PORTDIR's
+ # license directory.
+ for mypos in range(0,len(myuse)):
+ # Need to check for "||" manually as no portage
+ # function will remove it without removing values.
+ if myuse[mypos] not in liclist and myuse[mypos] != "||":
+ stats["LICENSE.invalid"]=stats["LICENSE.invalid"]+1
+ fails["LICENSE.invalid"].append(x+"/"+y+".ebuild: %s" % myuse[mypos])
+
+ #keyword checks
+ myuse = myaux["KEYWORDS"].split()
+ for mykey in myuse:
+ myskey=mykey[:]
+ if myskey[0]=="-":
+ myskey=myskey[1:]
+ if myskey[0]=="~":
+ myskey=myskey[1:]
+ if mykey!="-*":
+ if myskey not in kwlist:
+ stats["KEYWORDS.invalid"] += 1
+ fails["KEYWORDS.invalid"].append(x+"/"+y+".ebuild: %s" % mykey)
+ elif not profiles.has_key(myskey):
+ stats["KEYWORDS.invalid"] += 1
+ fails["KEYWORDS.invalid"].append(x+"/"+y+".ebuild: %s (profile invalid)" % mykey)
+
+ #syntax checks
+ myear = time.gmtime(os.stat(checkdir+"/"+y+".ebuild")[ST_MTIME])[0]
+ gentoo_copyright = re.compile(r'^# Copyright ((1999|200\d)-)?' + str(myear) + r' Gentoo Foundation')
+ gentoo_license = re.compile(r'^# Distributed under the terms of the GNU General Public License v2$')
+ cvs_header = re.compile(r'^#\s*\$Header.*\$$')
+ ignore_line = re.compile(r'(^$)|(^(\t)*#)')
+ leading_spaces = re.compile(r'^[\S\t]')
+ trailing_whitespace = re.compile(r'.*([\S]$)')
+ readonly_assignment = re.compile(r'^\s*(export\s+)?(A|P|PV|PN|PR|PVR|PF|D|WORKDIR|FILESDIR|FEATURES|USE)=')
+ continuation_symbol = re.compile(r'(.*[ ]+[\\][ ].*)')
+ line_continuation_quoted = re.compile(r'(\"|\')(([\w ,:;#\[\]\.`=/|\$\^\*{}()\'-])|(\\.))*\1')
+ line_continuation = re.compile(r'([^#]*\S)(\s+|\t)\\$')
+ linenum=0
+ for line in input(checkdir+"/"+y+".ebuild"):
+ linenum += 1
+ # Gentoo copyright check
+ if linenum == 1:
+ match = gentoo_copyright.match(line)
+ if not match:
+ myerrormsg = "Copyright header Error. Possibly date related."
+ stats["ebuild.badheader"] +=1
+ fails["ebuild.badheader"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+ # Gentoo license check
+ elif linenum == 2:
+ match = gentoo_license.match(line)
+ if not match:
+ myerrormsg = "Gentoo License Error."
+ stats["ebuild.badheader"] +=1
+ fails["ebuild.badheader"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+ # CVS Header check
+ elif linenum == 3:
+ match = cvs_header.match(line)
+ if not match:
+ myerrormsg = "CVS Header Error."
+ stats["ebuild.badheader"] +=1
+ fails["ebuild.badheader"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+ else:
+ match = ignore_line.match(line)
+ if not match:
+ # Excluded Blank lines and full line comments. Good!
+ # Leading Spaces Check
+ match = leading_spaces.match(line)
+ if not match:
+ #Line has got leading spaces. Bad!
+ myerrormsg = "Leading Space Syntax Error. Line %d" % linenum
+ stats["ebuild.minorsyn"] +=1
+ fails["ebuild.minorsyn"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+ # Trailing whitespace check
+ match = trailing_whitespace.match(line)
+ if not match:
+ #Line has got trailing whitespace. Bad!
+ myerrormsg = "Trailing whitespace Syntax Error. Line %d" % linenum
+ stats["ebuild.minorsyn"] +=1
+ fails["ebuild.minorsyn"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+ # Readonly variable assignment check
+ match = readonly_assignment.match(line)
+ if match:
+ # invalid assignment, very bad!
+ myerrormsg = "Readonly variable assignment to %s on line %d" % (match.group(2), linenum)
+ stats["variable.readonly"] += 1
+ fails["variable.readonly"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+ # Line continuation check
+ match = continuation_symbol.match(line)
+ if match:
+ #Excluded lines not even containing a " \" match. Good!
+ line = re.sub(line_continuation_quoted,"\"\"",line)
+ #line has been edited to collapsed "" and '' quotes to "". Good!
+ match = continuation_symbol.match(line)
+ if match:
+ #Again exclude lines not even containing a " \" match. Good!
+ #This repetition is done for a slight performance increase
+ match = line_continuation.match(line)
+ if not match:
+ #Line has a line continuation error. Bad!
+ myerrormsg = "Line continuation (\"\\\") Syntax Error. Line %d" % linenum
+ stats["ebuild.majorsyn"] +=1
+ fails["ebuild.majorsyn"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+
+ # Check for 'all unstable' or 'all masked' -- ACCEPT_KEYWORDS is stripped
+ # XXX -- Needs to be implemented in dep code. Can't determine ~arch nicely.
+ #if not portage.portdb.xmatch("bestmatch-visible",x):
+ # stats["ebuild.nostable"]+=1
+ # fails["ebuild.nostable"].append(x)
+ if allmasked and repolevel == 3:
+ stats["ebuild.allmasked"]+=1
+ fails["ebuild.allmasked"].append(x)
+
+#Pickle and save results for instant reuse in last and lfull
+savef=open('/var/cache/edb/repo.stats','w')
+pickle.dump(stats,savef)
+savef.close()
+savef=open('/var/cache/edb/repo.fails','w')
+pickle.dump(fails,savef)
+savef.close()
+if not (os.stat('/var/cache/edb/repo.stats')[ST_GID] == getgrnam('portage')[2]):
+ os.chown('/var/cache/edb/repo.stats',os.geteuid(),getgrnam('portage')[2])
+ os.chmod('/var/cache/edb/repo.stats',0664)
+if not (os.stat('/var/cache/edb/repo.fails')[ST_GID] == getgrnam('portage')[2]):
+ os.chown('/var/cache/edb/repo.fails',os.geteuid(),getgrnam('portage')[2])
+ os.chmod('/var/cache/edb/repo.fails',0664)
+print
+#dofail will be set to 1 if we have failed in at least one non-warning category
+dofail=0
+#dowarn will be set to 1 if we tripped any warnings
+dowarn=0
+#dofull will be set if we should print a "repoman full" informational message
+dofull=0
+for x in qacats:
+ if not isCvs and (string.find(x, "notadded") != -1):
+ stats[x] = 0
+ if stats[x]:
+ dowarn=1
+ if x not in qawarnings:
+ dofail=1
+ else:
+ continue
+ print " "+string.ljust(x,30),
+ if stats[x]==0:
+ print green(`stats[x]`)
+ continue
+ elif x in qawarnings:
+ print yellow(`stats[x]`)
+ else:
+ print red(`stats[x]`)
+ if mymode!="full":
+ if stats[x]<12:
+ for y in fails[x]:
+ print " "+y
+ else:
+ dofull=1
+ else:
+ for y in fails[x]:
+ print " "+y
+print
+
+def grouplist(mylist,seperator="/"):
+ """(list,seperator="/") -- Takes a list of elements; groups them into
+ same initial element categories. Returns a dict of {base:[sublist]}
+ From: ["blah/foo","spork/spatula","blah/weee/splat"]
+ To: {"blah":["foo","weee/splat"], "spork":["spatula"]}"""
+ mygroups={}
+ for x in mylist:
+ xs=string.split(x,seperator)
+ if xs[0]==".":
+ xs=xs[1:]
+ if xs[0] not in mygroups.keys():
+ mygroups[xs[0]]=[string.join(xs[1:],seperator)]
+ else:
+ mygroups[xs[0]]+=[string.join(xs[1:],seperator)]
+ return mygroups
+
+if mymode!="commit":
+ if dofull:
+ print bold("Note: type \"repoman full\" for a complete listing.")
+ print
+ if dowarn and not dofail:
+ print green("RepoMan sez:"),"\"You're only giving me a partial QA payment?\nI'll take it this time, but I'm not happy.\""
+ elif not dofail:
+ print green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\""
+ print
+else:
+ if dofail:
+ print turquoise("Please fix these important QA issues first.")
+ print green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n"
+ sys.exit(1)
+
+ if "--pretend" in myoptions:
+ print green("RepoMan sez:"), "\"So, you want to play it safe. Good call.\"\n"
+
+ if fails["digest.missing"]:
+ print green("Creating missing digests...")
+ for x in fails["digest.missing"]:
+ xs=string.split(x,"/")
+ del xs[-2]
+ myeb=string.join(xs[:-1],"/")+"/"+xs[-1][7:]
+ if "--pretend" in myoptions:
+ print "(ebuild "+portdir+"/"+myeb+".ebuild digest)"
+ else:
+ retval=os.system("ebuild "+portdir+"/"+myeb+".ebuild digest")
+ if retval:
+ print "!!! Exiting on ebuild digest (shell) error code:",retval
+ sys.exit(retval)
+
+ mycvstree=cvstree.getentries("./",recursive=1)
+ if isCvs and not mycvstree:
+ print "!!! It seems we don't have a cvs tree?"
+ sys.exit(3)
+
+ myunadded=cvstree.findunadded(mycvstree,recursive=1,basedir="./")
+ myautoadd=[]
+ if myunadded:
+ for x in range(len(myunadded)-1,-1,-1):
+ xs=string.split(myunadded[x],"/")
+ if xs[-1]=="files":
+ print "!!! files dir is not added! Please correct this."
+ sys.exit(-1)
+ elif xs[-1]=="Manifest":
+ # It's a manifest... auto add
+ myautoadd+=[myunadded[x]]
+ del myunadded[x]
+ elif len(xs[-1])>=7:
+ if xs[-1][:7]=="digest-":
+ del xs[-2]
+ myeb=string.join(xs[:-1]+[xs[-1][7:]],"/")+".ebuild"
+ if os.path.exists(myeb):
+ # Ebuild exists for digest... So autoadd it.
+ myautoadd+=[myunadded[x]]
+ del myunadded[x]
+
+ if myautoadd:
+ print ">>> Auto-Adding missing digests..."
+ if "--pretend" in myoptions:
+ print "(/usr/bin/cvs add "+string.join(myautoadd)+")"
+ retval=0
+ else:
+ retval=os.system("/usr/bin/cvs add "+string.join(myautoadd))
+ if retval:
+ print "!!! Exiting on cvs (shell) error code:",retval
+ sys.exit(retval)
+
+ if myunadded:
+ print red("!!! The following files are in your cvs tree but are not added to the master")
+ print red("!!! tree. Please remove them from the cvs tree or add them to the master tree.")
+ for x in myunadded:
+ print " ",x
+ print
+ print
+ sys.exit(1)
+
+ mymissing=None
+ if mymissing:
+ print "The following files are obviously missing from your cvs tree"
+ print "and are being fetched so we can continue:"
+ for x in mymissing:
+ print " ",x
+ if "--pretend" in myoptions:
+ print "(/usr/bin/cvs -q up "+string.join(mymissing)+")"
+ retval=0
+ else:
+ retval=os.system("/usr/bin/cvs -q up "+string.join(mymissing))
+ if retval:
+ print "!!! Exiting on cvs (shell) error code:",retval
+ sys.exit(retval)
+ del mymissing
+
+ retval=["",""]
+ if isCvs:
+ print "Performing a "+green("cvs -n up")+" with a little magic grep to check for updates."
+ retval=getstatusoutput("/usr/bin/cvs -n up 2>&1 | egrep '^[^\?] .*' | egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'")
+
+ mylines=string.split(retval[1], "\n")
+ myupdates=[]
+ for x in mylines:
+ if not x:
+ continue
+ if x[0] not in "UPMAR": # Updates,Patches,Modified,Added,Removed
+ print red("!!! Please fix the following issues reported from cvs: ")+green("(U,P,M,A,R are ok)")
+ print red("!!! Note: This is a pretend/no-modify pass...")
+ print retval[1]
+ print
+ sys.exit(1)
+ elif x[0] in ["U","P"]:
+ myupdates+=[x[2:]]
+
+ if myupdates:
+ print green("Fetching trivial updates...")
+ if "--pretend" in myoptions:
+ print "(/usr/bin/cvs up "+string.join(myupdates)+")"
+ retval=0
+ else:
+ retval=os.system("/usr/bin/cvs up "+string.join(myupdates))
+ if retval!=0:
+ print "!!! cvs exited with an error. Terminating."
+ sys.exit(retval)
+
+ if isCvs:
+ mycvstree=cvstree.getentries("./",recursive=1)
+ mychanged=cvstree.findchanged(mycvstree,recursive=1,basedir="./")
+ mynew=cvstree.findnew(mycvstree,recursive=1,basedir="./")
+ myremoved=cvstree.findremoved(mycvstree,recursive=1,basedir="./")
+ if not (mychanged or mynew or myremoved):
+ print
+ print green("RepoMan sez:"), "\"Doing nothing is not always good for QA.\"\n"
+ print
+ print "(Didn't find any changed files...)"
+ print
+ sys.exit(0)
+
+ myupdates=mychanged+mynew
+ myheaders=[]
+ mydirty=[]
+ headerstring="'\$(Header|Id)"
+ headerstring+=".*\$'"
+ for myfile in myupdates:
+ myout=getstatusoutput("egrep -q "+headerstring+" "+myfile)
+ if myout[0]==0:
+ myheaders.append(myfile)
+
+ print "*",green(str(len(myupdates))),"files being committed...",green(str(len(myheaders))),"have headers that will change."
+ print "*","Files with headers will cause the manifests to be made and recommited."
+ print "myupdates:",myupdates
+ print "myheaders:",myheaders
+ print
+ unlinkfile=0
+ if not (commitmessage or commitmessagefile):
+ print "Please enter a CVS commit message at the prompt:"
+ while not commitmessage:
+ try:
+ commitmessage=raw_input(green("> "))
+ except KeyboardInterrupt:
+ exithandler()
+ try:
+ commitmessage+="\n(Portage version: "+str(portage.VERSION)+")"
+ except:
+ print "Failed to insert portage version in message!"
+ commitmessage+="\n(Portage version: Unknown)"
+ if not commitmessagefile:
+ unlinkfile=1
+ commitmessagefile=tempfile.mktemp(".repoman.msg")
+ if os.path.exists(commitmessagefile):
+ os.unlink(commitmessagefile)
+ mymsg=open(commitmessagefile,"w")
+ mymsg.write(commitmessage)
+ mymsg.close()
+
+ print
+ print green("Using commit message:")
+ print green("------------------------------------------------------------------------------")
+ print commitmessage
+ print green("------------------------------------------------------------------------------")
+ print
+
+ if "--pretend" in myoptions:
+ print "(/usr/bin/cvs -q commit -F "+commitmessagefile+")"
+ retval=0
+ else:
+ retval=os.system("/usr/bin/cvs -q commit -F "+commitmessagefile)
+ if retval:
+ print "!!! Exiting on cvs (shell) error code:",retval
+ sys.exit(retval)
+
+ # Setup the GPG commands
+ def gpgsign(filename):
+ gpgcmd = "gpg --sign --clearsign --yes "
+ gpgcmd+= "--default-key "+repoman_settings["PORTAGE_GPG_KEY"]
+ if repoman_settings.has_key("PORTAGE_GPG_DIR"):
+ gpgcmd += " --homedir "+repoman_settings["PORTAGE_GPG_DIR"]
+ rValue = os.system(gpgcmd+" "+filename)
+ if rValue == 0:
+ os.rename(filename+".asc", filename)
+ else:
+ print "!!! gpg exited with '" + str(rValue) + "' status"
+ return rValue
+
+ if myheaders or myupdates or myremoved or mynew:
+ myfiles=myheaders+myupdates+myremoved+mynew
+ for x in range(len(myfiles)-1, -1, -1):
+ if myfiles[x].count("/") < 4-repolevel:
+ del myfiles[x]
+ mydone=[]
+ if repolevel==3: # In a package dir
+ repoman_settings["O"]="./"
+ portage.digestgen([],repoman_settings,manifestonly=1)
+ elif repolevel==2: # In a category dir
+ for x in myfiles:
+ xs=string.split(x,"/")
+ if xs[0]==".":
+ xs=xs[1:]
+ if xs[0] in mydone:
+ continue
+ mydone.append(xs[0])
+ repoman_settings["O"]="./"+xs[0]
+ portage.digestgen([],repoman_settings,manifestonly=1)
+ elif repolevel==1: # repo-cvsroot
+ print green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n"
+ for x in myfiles:
+ xs=string.split(x,"/")
+ if xs[0]==".":
+ xs=xs[1:]
+ if string.join(xs[:2],"/") in mydone:
+ continue
+ mydone.append(string.join(xs[:2],"/"))
+ repoman_settings["O"]="./"+string.join(xs[:2],"/")
+ portage.digestgen([],repoman_settings,manifestonly=1)
+ else:
+ print red("I'm confused... I don't know where I am!")
+ sys.exit(1)
+
+ if "--pretend" in myoptions:
+ print "(/usr/bin/cvs -q commit -F "+commitmessagefile+")"
+ else:
+ mymsg=open(commitmessagefile,"w")
+ mymsg.write(commitmessage)
+ mymsg.write("\n (Unsigned Manifest commit)")
+ mymsg.close()
+ retval=os.system("/usr/bin/cvs -q commit -F "+commitmessagefile)
+ if retval:
+ print "!!! Exiting on cvs (shell) error code:",retval
+ sys.exit(retval)
+
+ if "sign" in portage.features:
+ mydone=[]
+ if repolevel==3: # In a package dir
+ repoman_settings["O"]="./"
+ while(gpgsign(repoman_settings["O"]+"/Manifest")):
+ portage.writemsg("!!! YOU MUST sign the Manifest.\n")
+ portage.writemsg("!!! You can also disable this for the time being by removing FEATURES='sign'")
+ time.sleep(3)
+ elif repolevel==2: # In a category dir
+ for x in myfiles:
+ xs=string.split(x,"/")
+ if xs[0]==".":
+ xs=xs[1:]
+ if xs[0] in mydone:
+ continue
+ mydone.append(xs[0])
+ repoman_settings["O"]="./"+xs[0]
+ while(gpgsign(repoman_settings["O"]+"/Manifest")):
+ portage.writemsg("!!! YOU MUST sign the Manifest.\n")
+ portage.writemsg("!!! You can also disable this for the time being by removing FEATURES='sign'")
+ time.sleep(3)
+ elif repolevel==1: # repo-cvsroot
+ print green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n"
+ for x in myfiles:
+ xs=string.split(x,"/")
+ if xs[0]==".":
+ xs=xs[1:]
+ if string.join(xs[:2],"/") in mydone:
+ continue
+ mydone.append(string.join(xs[:2],"/"))
+ repoman_settings["O"]="./"+string.join(xs[:2],"/")
+ while(gpgsign(repoman_settings["O"]+"/Manifest")):
+ portage.writemsg("!!! YOU MUST sign the Manifest.\n")
+ portage.writemsg("!!! You can also disable this for the time being by removing FEATURES='sign'")
+ time.sleep(3)
+
+ if "--pretend" in myoptions:
+ print "(/usr/bin/cvs -q commit -F "+commitmessagefile+")"
+ else:
+ mymsg=open(commitmessagefile,"w")
+ mymsg.write(commitmessage)
+ mymsg.write("\n (Signed Manifest commit)")
+ mymsg.close()
+ retval=os.system("/usr/bin/cvs -q commit -F "+commitmessagefile)
+ if retval:
+ print "!!! Exiting on cvs (shell) error code:",retval
+ sys.exit(retval)
+
+ if unlinkfile:
+ os.unlink(commitmessagefile)
+ print
+ if isCvs:
+ print "CVS commit complete."
+ else:
+ print "repoman was too scared by not seeing any familiar cvs file that he forgot to commit anything"
+ print green("RepoMan sez:"), "\"If everyone were like you, I'd be out of business!\"\n"
+sys.exit(0)
+
diff --git a/bin/xpak b/bin/xpak
new file mode 100755
index 00000000..03228c14
--- /dev/null
+++ b/bin/xpak
@@ -0,0 +1,14 @@
+#!/usr/bin/python -O
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/xpak,v 1.10 2004/10/04 13:56:50 vapier Exp $
+
+import sys
+if len(sys.argv)!=3:
+ print "xpak: expecting three arguments."
+ sys.exit(1)
+
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+
+import xpak
+xpak.xpak(sys.argv[1],sys.argv[2])
diff --git a/cnf/dispatch-conf.conf b/cnf/dispatch-conf.conf
new file mode 100644
index 00000000..11123b2a
--- /dev/null
+++ b/cnf/dispatch-conf.conf
@@ -0,0 +1,36 @@
+#
+# dispatch-conf.conf
+#
+
+# Directory to archive replaced configs
+archive-dir=/etc/config-archive
+
+# Use rcs for storing files in the archive directory?
+# (yes or no)
+use-rcs=no
+
+# Diff for display
+# %s old file
+# %s new file
+diff="diff -Nu %s %s | less --no-init --QUIT-AT-EOF"
+
+# Diff for interactive merges.
+# %s output file
+# %s old file
+# %s new file
+merge="sdiff --suppress-common-lines --output=%s %s %s"
+
+# Automerge files comprising only CVS interpolations (e.g. Header or Id)
+# (yes or no)
+replace-cvs=yes
+
+# Automerge files comprising only whitespace and/or comments
+# (yes or no)
+replace-wscomments=no
+
+# Automerge files that the user hasn't modified
+# (yes or no)
+replace-unmodified=no
+
+# Per-session log file of changes made to configuration files
+#log-file=/var/log/dispatch-conf.log
diff --git a/cnf/etc-update.conf b/cnf/etc-update.conf
new file mode 100644
index 00000000..ac132de0
--- /dev/null
+++ b/cnf/etc-update.conf
@@ -0,0 +1,71 @@
+# edit the lines below to your liking
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/etc-update.conf,v 1.5.2.1 2004/10/22 16:53:30 carpaski Exp $
+
+# mode - 0 for text, 1 for menu (support incomplete)
+# note that you need dev-util/dialog installed
+mode="0"
+
+# Whether trivial/comment changes should be automerged
+eu_automerge="yes"
+
+# arguments used whenever rm is called
+rm_opts="-i"
+
+# arguments used whenever mv is called
+mv_opts="-i"
+
+# arguments used whenever cp is called
+cp_opts="-i"
+
+# pager for use with diff commands (see NOTE_2)
+pager="less"
+#pager=""
+
+# vim-users: you CAN use vimdiff for diff_command. (see NOTE_1)
+diff_command="diff -uN %file1 %file2"
+using_editor=0
+#diff_command="vim -d %file1 %file2"
+#using_editor=1
+
+
+# vim-users: don't use vimdiff for merging (see NOTE_1)
+merge_command="sdiff -s -o %merged %orig %new"
+
+# EXPLANATION
+#
+# pager:
+#
+# Examples of pager usage:
+# pager="" # don't use a pager
+# pager="less -E" # less
+# pager="more" # more
+#
+#
+# diff_command:
+#
+# Arguments:
+# %file1 [REQUIRED]
+# %file2 [REQUIRED]
+#
+# Examples of diff_command:
+# diff_command="diff -uN %file1 %file2" # diff
+# diff_command="vim -d %file1 %file2" # vimdiff
+#
+#
+# merge_command:
+#
+# Arguments:
+# %orig [REQUIRED]
+# %new [REQUIRED]
+# %merged [REQUIRED]
+#
+# Examples of merge_command:
+# merge_command="sdiff -s -o %merged %old %new" # sdiff
+#
+
+# NOTE_1: Editors such as vim/vimdiff are not usable for the merge_command
+# because it is not known what filenames the produced files have (the user can
+# choose while using those programs)
+
+# NOTE_2: Make sure pager is set to "" when using an editor as diff_command!
+
diff --git a/cnf/make.conf b/cnf/make.conf
new file mode 100644
index 00000000..cded7506
--- /dev/null
+++ b/cnf/make.conf
@@ -0,0 +1,319 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf,v 1.84.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
+# Change this line as appropriate (i686, i586, i486 or i386).
+# All modern systems (even Athlons) should use "i686-pc-linux-gnu".
+# All K6's are i586.
+CHOST="i686-pc-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
+# breaking compatibility with other CPUs.
+#
+# -march=<cpu-type> means to take full advantage of the ABI and instructions
+# for the particular CPU; this will break compatibility with older CPUs (for
+# example, -march=athlon-xp code will not run on a regular Athlon, and
+# -march=i686 code will not run on a Pentium Classic.
+#
+# CPU types supported in gcc-3.2 and higher: athlon-xp, athlon-mp,
+# athlon-tbird, athlon, k6, k6-2, k6-3, i386, i486, i586 (Pentium), i686
+# (PentiumPro), pentium, pentium-mmx, pentiumpro, pentium2 (Celeron),
+# pentium3, and pentium4.
+#
+# Note that Gentoo Linux 1.4 and higher include at least gcc-3.2.
+#
+# CPU types supported in gcc-2.95*: k6, i386, i486, i586 (Pentium), i686
+# (Pentium Pro), pentium, pentiumpro Gentoo Linux 1.2 and below use gcc-2.95*
+#
+# CRITICAL WARNINGS: ****************************************************** #
+# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
+# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
+# ************************************************************************* #
+#
+# Decent examples:
+#
+#CFLAGS="-mcpu=athlon-xp -O3 -pipe"
+#CFLAGS="-march=pentium3 -O3 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.alpha b/cnf/make.conf.alpha
new file mode 100644
index 00000000..e98eec7f
--- /dev/null
+++ b/cnf/make.conf.alpha
@@ -0,0 +1,305 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.alpha,v 1.40.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
+# The generic HOST setting on alpha is alpha-unknown-linux-gnu. If your machine
+# is an ev6 or ev67 based system you might want to use
+# either alphaev6-unknown-linux-gnu or alphaev67-unknown-linux-gnu accordingly.
+#
+#CHOST="alphaev67-unknown-linux-gnu"
+CHOST="alpha-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> means optimize code for the particular type of CPU. In
+# difference to x86 for example -mcpu does break compatibility
+# to older cpu types in case of ev6 or higher.
+# On Alpha there is no -march= option in gcc-3.
+#
+# CPU types supported in gcc-3.2 or higher: ev4, ev45, ev5, ev56, ev6, ev67
+#
+# Decent examples:
+#
+#CFLAGS="-mcpu=ev67 -O3 -pipe "
+CFLAGS="-mcpu=ev5 -O3 -pipe "
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~alpha"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.amd64 b/cnf/make.conf.amd64
new file mode 100644
index 00000000..4de87760
--- /dev/null
+++ b/cnf/make.conf.amd64
@@ -0,0 +1,316 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.amd64,v 1.5.2.4 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+CHOST="x86_64-pc-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
+# breaking compatibility with other CPUs. GCC 3.4 has deprecated support for
+# -mcpu, so use -mtune instead if using this compiler.
+#
+# -march=<cpu-type> means to take full advantage of the ABI and instructions
+# for the particular CPU; this will break compatibility with older CPUs (for
+# example, -march=athlon-xp code will not run on a regular Athlon, and
+# -march=i686 code will not run on a Pentium Classic.)
+#
+# CPU types supported in gcc-3.2 and higher: athlon-xp, athlon-mp,
+# athlon-tbird, athlon, k6, k6-2, k6-3, i386, i486, i586 (Pentium), i686
+# (PentiumPro), pentium, pentium-mmx, pentiumpro, pentium2 (Celeron),
+# pentium3, and pentium4.
+#
+# Note that Gentoo Linux 1.4 and higher include at least gcc-3.2.
+#
+# amd64 CPU types supported in gcc-3.4: athlon64, opteron, k8
+#
+# CRITICAL WARNINGS: ****************************************************** #
+# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
+# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
+# GCC 3.3 doesnt support an amd64 specific -march setting, use 3.4. #
+# ************************************************************************* #
+#
+# Decent examples:
+#
+#CFLAGS="-mtune=k8 -O2 -pipe"
+#CFLAGS="-march=athlon64 -O2 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~amd64"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.arm b/cnf/make.conf.arm
new file mode 100644
index 00000000..167e6c60
--- /dev/null
+++ b/cnf/make.conf.arm
@@ -0,0 +1,313 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.arm,v 1.31.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
+# It's very important you select the right CHOST from the start. A wrong
+# CHOST could easily lead to weird errors either in compiling or running.
+#
+# Netwinder (or any StrongArm110): armv4l-unknown-linux-gnu
+# nslu2: armvbe-unknown-linux-gnu
+# Generic ARM: arm-unknown-linux-gnu
+#
+CHOST="armv4l-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
+# breaking compatibility with other CPUs.
+#
+# -march=<cpu-type> means to take full advantage of the ABI and instructions
+# for the particular CPU; this will break compatibility with older CPUs (for
+# example, -march=xscale code will not run on a StrongARM 11x0, and
+# -march=strongarm110 code will not run on a regular StrongARM).
+#
+# Don't use -O3. Even -O2 may be risky in some cases.
+#
+# For a full listing of supported CPU models, please refer to the GCC website:
+# http://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/ARM-Options.html
+#
+# Netwinder:
+#CFLAGS="-mcpu=strongarm110 -O2 -pipe"
+# NSLU2:
+#CFLAGS="-mcpu=armeb -O2 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.hppa b/cnf/make.conf.hppa
new file mode 100644
index 00000000..04fb9896
--- /dev/null
+++ b/cnf/make.conf.hppa
@@ -0,0 +1,322 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.hppa,v 1.37.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
+# The generic CHOST value for hppa is hppa-unknown-linux-gnu.
+# But you might want to use hppa1.1-unknown-linux-gnu or hppa2.0-unknown-linux-gnu
+# according to your station.
+#
+CHOST="hppa-unknown-linux-gnu"
+#CHOST="hppa1.1-unknown-linux-gnu"
+#CHOST="hppa2.0-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -march=<cpu-type> means to take full advantage of the ABI and instructions
+# for the particular CPU; this will break compatibility with older CPUs (for
+# example, -march=2.0 code will not run on a regular hppa1.1 station)
+#
+# -mschedule=cpu-type create schedule code according to the constraints for the machine
+# cpu-type. The choices for cpu-type are 700 7100, 7100LC, 7200, and 8000.
+# Use 'cat /proc/cpuinfo' to know the right schedule for your hppa.
+# Note that you must use 7100LC for 7300LC.
+#
+# Architectures types supported in gcc-3.2 and higher: 1.0, 1.1 and 2.0
+# Note that 64bit userspace is not yet implemented.
+#
+# Decent examples:
+#
+
+# Use this one if you have a hppa1.1
+#CFLAGS="-march=1.1 -O2 -pipe -mschedule=7100LC"
+
+# Or this one if you have a hppa2.0
+# Note that -march=2.0 was unstable on some stations.
+# -march=1.0 will create problems too.
+#CFLAGS="-O2 -pipe -mschedule=8000"
+
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Btw it's recommended to use this setting for stability.
+# There are still many bugs with higher level of optimisation.
+#CXXFLAGS="-O1 -pipe"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'hppa' architecture
+# would add '~hppa' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.ia64 b/cnf/make.conf.ia64
new file mode 100644
index 00000000..556261f2
--- /dev/null
+++ b/cnf/make.conf.ia64
@@ -0,0 +1,284 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.ia64,v 1.1.2.4 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# All Itanium systems should use this host setting:
+
+CHOST="ia64-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+#CFLAGS="-O2 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.mac b/cnf/make.conf.mac
new file mode 100644
index 00000000..f1883ec9
--- /dev/null
+++ b/cnf/make.conf.mac
@@ -0,0 +1,6 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.mac,v 1.2 2004/09/30 06:34:27 vapier Exp $
+# Contains local system settings for Portage system
+
+#Nothing needed here
diff --git a/cnf/make.conf.mips b/cnf/make.conf.mips
new file mode 100644
index 00000000..82141b5b
--- /dev/null
+++ b/cnf/make.conf.mips
@@ -0,0 +1,302 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.mips,v 1.38.2.4 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# All MIPS systems should use this host setting:
+
+CHOST="mips-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> for MIPS systems selects the type of processor you want
+# to optimize your code for. Code generated under those options will run best
+# on that processor, and may not run at all on others.
+#
+# GCC 3.2 supports many mips processor types including: r2000, r3000, r3900, r4000,
+# r4100, r4300, r4400, r4600, r4650, r5000, r6000, r8000 , orion
+#
+#CFLAGS="-O2 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~mips"
+
+
+
+
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.ppc b/cnf/make.conf.ppc
new file mode 100644
index 00000000..2ddea6e5
--- /dev/null
+++ b/cnf/make.conf.ppc
@@ -0,0 +1,335 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.ppc,v 1.57.2.4 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# All PowerPC systems should use this host setting:
+
+CHOST="powerpc-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> for PowerPC systems selects the type of processor you want
+# to optimize your code for. Code generated under those options will run best
+# on that processor, and may not run at all on others.
+#
+# GCC 3.2 supports many powerpc processor types including: rios, rios1, rsc,
+# rios2, rs64a, 601, 602, 603, 603e, 604, 604e, 620, 630, 740, 7400, 7450, 750,
+# power, power2, powerpc, 403, 505, 801, 821, 823, and 860 and common.
+#
+# Recommended settings for GCC 3.2 only (Gentoo 1.4 or newer) :
+#
+# -maltivec enables optional (still limited) altivec support and should be used
+# only for G4 processors, on GCC 3.2 or newer. It also requires that you have
+# the alitvec option compiled into your kernel to take full advantage of this
+# feature. Note: you should also include -mabi=altivec flag if using this option.
+#
+# Long term testing has shown that -O3 opts can be unreliable on G4's but work
+# on G3 series processors or earlier. Use on a G4 at your own risk =)
+#
+# Due to some failures with the cpu string of 7450, the dev team recommends
+# using -mcpu=7400 for all G4 series processors until GCC 3.2 is more mature
+#
+#CFLAGS="-O2 -pipe -mcpu=7400 -maltivec -mabi=altivec"
+#
+#
+# All non G4 PPC boxen should choose this next option. It will work fine for
+# all G3 and pre machines. (note it will not hurt pre G3 machines either to
+# use this mcpu option as it is the default for gcc 3.2.x anyway)
+#
+#CFLAGS="-O3 -pipe -mcpu=750"
+
+# Recommended settings for GCC 2.95.3 only (Gentoo 1.2 or older):
+#
+# PowerPC 750 > up: this works on G3's and G4s, gcc 2.95.3 doesn't make the
+# distinction between G3 and G4, so this is fine for all NewWorld machines, if
+# you use yaboot to boot you should select this option
+#
+#CFLAGS="-O2 -pipe -mcpu=750 -mpowerpc-gfxopt -mmultiple -mstring"
+#
+# This will run on all other processors, by building more generic code This is
+# safe for all PPC machines running gcc 2.95.3, and works for all OldWorld
+# machines - if you use BootX to boot you should select this option
+#CFLAGS="-O2 -pipe -mmultiple -mstring"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+# Note: this really shouldn't be enabled until _AFTER_ you bootstrap and emerge
+# system. If you want the testing things update after these steps are completed.
+#
+#ACCEPT_KEYWORDS="~ppc"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.ppc64 b/cnf/make.conf.ppc64
new file mode 100644
index 00000000..ad7f6a5b
--- /dev/null
+++ b/cnf/make.conf.ppc64
@@ -0,0 +1,320 @@
+# Copyright 1999-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.ppc64,v 1.1.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# All PowerPC64 systems should use this host setting:
+
+CHOST="powerpc64-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mtarget=<cpu-type> for PowerPC64 systems instructs the gcc compiler that
+# it can use instruction scheduling specific for that type of processor
+# specified
+#
+# -mcpu=<cpu-type> for PowerPC64 systems selects the type of processor you want
+# to optimize your code for. Code generated under those options will run best
+# on that processor.
+#
+# -mcpu=<cpu-type> and -mtarget=<cpu-type> should both be specified
+#
+# GCC 3.x supports many ppc64 processor types including: power3, power4,
+# 970 (aka G5), and power5.
+#
+# RS64 processors should specify power3.
+#
+# Additional options of interest:
+#
+# -maltivec enables optional altivec support and should be used
+# only for 970 processors. It also requires that you have
+# the alitvec option compiled into your kernel to take full advantage of this
+# feature. Note: you should also include -mabi=altivec flag if using this option.
+#
+# -O3 for the most part seems ok but should be used with caution as
+# for instance app-editors/vim has problems if it is used. -O2 is a
+# good selection.
+#
+#Example CFLAGS setting
+#CFLAGS="-O2 -pipe -mcpu=970 -mtarget=970 -maltivec -mabi=altivec"
+#
+#or
+#
+#CFLAGS="-O2 -pipe -mcpu=power3 -mtarget=power3"
+#
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'ppc64' architecture
+# would add '~ppc64' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc64', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+# Note: this really shouldn't be enabled until _AFTER_ you bootstrap and emerge
+# system. If you want the testing things update after these steps are completed.
+#
+#ACCEPT_KEYWORDS="ppc64"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.s390 b/cnf/make.conf.s390
new file mode 100644
index 00000000..b2056dd5
--- /dev/null
+++ b/cnf/make.conf.s390
@@ -0,0 +1,284 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.s390,v 1.3.2.4 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# All s390 systems should use this host setting:
+
+CHOST="s390-ibm-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+#CFLAGS="-O2 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.sparc b/cnf/make.conf.sparc
new file mode 100644
index 00000000..57749688
--- /dev/null
+++ b/cnf/make.conf.sparc
@@ -0,0 +1,320 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.sparc,v 1.42.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+# This should be left to the default value of sparc-unknown-linux-gnu unless
+# you are absolutely certain of the consequences. In addition to potentially
+# destroying your system, you will recieve no support and your bugs will be
+# marked INVALID if you change this.
+#
+# CHOST="sparc-unknown-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# Sparc specific cpu optimizatiobn flags can be found here:
+# http://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/SPARC-Options.html#SPARC%20Options
+#
+# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
+# breaking compatibility with other CPUs.
+#
+# -mtune=<cpu-type> set the instruction scheduling parameters for machine, but
+# do not set the instruction set or register set.
+#
+# Here is a list of each supported architecture and their supported
+# implementations:
+#
+# gcc-3.2 and higher:
+# v7: cypress
+# v8: supersparc, hypersparc
+# sparclite: f930, f934, sparclite86x
+# sparclet: tsc701
+# v9: ultrasparc
+#
+# Additionally in gcc-3.3 and higher:
+# v9: ultrasparc3
+#
+# Decent examples:
+#
+#CFLAGS="-mcpu=supersparc -O3 -pipe"
+#CFLAGS="-mcpu=ultrasparc -O3 -pipe"
+#CFLAGS="-mcpu=v8 -mtune=v9 -O2 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~sparc"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.x86 b/cnf/make.conf.x86
new file mode 100644
index 00000000..2e2a7018
--- /dev/null
+++ b/cnf/make.conf.x86
@@ -0,0 +1,319 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.x86,v 1.5.2.5 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
+# Change this line as appropriate (i686, i586, i486 or i386).
+# All modern systems (even Athlons) should use "i686-pc-linux-gnu".
+# All K6's are i586.
+CHOST="i686-pc-linux-gnu"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
+# breaking compatibility with other CPUs.
+#
+# -march=<cpu-type> means to take full advantage of the ABI and instructions
+# for the particular CPU; this will break compatibility with older CPUs (for
+# example, -march=athlon-xp code will not run on a regular Athlon, and
+# -march=i686 code will not run on a Pentium Classic.
+#
+# CPU types supported in gcc-3.2 and higher: athlon-xp, athlon-mp,
+# athlon-tbird, athlon, k6, k6-2, k6-3, i386, i486, i586 (Pentium), i686
+# (PentiumPro), pentium, pentium-mmx, pentiumpro, pentium2 (Celeron),
+# pentium3, and pentium4.
+#
+# Note that Gentoo Linux 1.4 and higher include at least gcc-3.2.
+#
+# CPU types supported in gcc-2.95*: k6, i386, i486, i586 (Pentium), i686
+# (Pentium Pro), pentium, pentiumpro Gentoo Linux 1.2 and below use gcc-2.95*
+#
+# CRITICAL WARNINGS: ****************************************************** #
+# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
+# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
+# ************************************************************************* #
+#
+# Decent examples:
+#
+#CFLAGS="-mcpu=athlon-xp -O3 -pipe"
+#CFLAGS="-march=pentium3 -O3 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+# If specified, portage will use this directory whenever possible
+# for all rapid operations such as lockfiles and transient data.
+# It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+# set this to anything that does not give a significant performance
+# enhancement and proper FS compliance for locks and read/write.
+# /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+# setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.conf.x86-fbsd b/cnf/make.conf.x86-fbsd
new file mode 100644
index 00000000..e78b3a32
--- /dev/null
+++ b/cnf/make.conf.x86-fbsd
@@ -0,0 +1,310 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.conf.x86-fbsd,v 1.1.2.2 2005/04/13 15:28:38 jstubbs Exp $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them: --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host Setting
+# ============
+#
+# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
+# Change this line as appropriate (i686, i586, i486 or i386).
+# All modern systems (even Athlons) should use "i686-pc-linux-gnu".
+# All K6's are i586.
+CHOST="i686-unknown-freebsd5.3"
+
+# Host and optimization settings
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# -mtune=<cpu-type> means optimize code for the particular type of CPU without
+# breaking compatibility with other CPUs.
+#
+# -march=<cpu-type> means to take full advantage of the ABI and instructions
+# for the particular CPU; this will break compatibility with older CPUs (for
+# example, -march=athlon-xp code will not run on a regular Athlon, and
+# -march=i686 code will not run on a Pentium Classic.
+#
+# CPU types supported in gcc-3.2 and higher: athlon-xp, athlon-mp,
+# athlon-tbird, athlon, k6, k6-2, k6-3, i386, i486, i586 (Pentium), i686
+# (PentiumPro), pentium, pentium-mmx, pentiumpro, pentium2 (Celeron),
+# pentium3, and pentium4.
+#
+# Note that Gentoo Linux 1.4 and higher include at least gcc-3.2.
+#
+# CPU types supported in gcc-2.95*: k6, i386, i486, i586 (Pentium), i686
+# (Pentium Pro), pentium, pentiumpro Gentoo Linux 1.2 and below use gcc-2.95*
+#
+# CRITICAL WARNINGS: ****************************************************** #
+# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
+# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
+# ************************************************************************* #
+#
+# Decent examples:
+#
+#CFLAGS="-mtune=athlon-xp -O3 -pipe"
+#CFLAGS="-march=pentium3 -O3 -pipe"
+
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+# temporary storage of data. This can get VERY large depending upon
+# the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+# for all profile information as well as all ebuilds. If you change
+# this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+# emerges. The source code is maintained here unless you delete
+# it. The entire repository of tarballs for gentoo is 9G. This is
+# considerably more than any user will ever download. 2-3G is
+# a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+# with '--buildpkg' or '-b' while emerging a package. This can get
+# upto several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+# creates from each individual merge. They are stored as NNNN-$PF.log
+# in the directory specified. This is disabled until you enable it by
+# providing a directory. Permissions will be modified as needed IF the
+# directory exists, otherwise logging will be disabled. NNNN is the
+# increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+# concern that they will be deleted by rsync updates. Default is not
+# defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+# rotation. This allows you to select servers that are geographically
+# close to you, yet still distribute the load over a number of servers.
+# Please do not single out specific rsync mirrors. Doing so places undue
+# stress on particular mirrors. Instead you may use one of the following
+# continent specific rotations:
+#
+# Default: "rsync://rsync.gentoo.org/gentoo-portage"
+# North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+# South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+# Europe: "rsync://rsync.europe.gentoo.org/gentoo-portage"
+# Asia: "rsync://rsync.asia.gentoo.org/gentoo-portage"
+# Australia: "rsync://rsync.au.gentoo.org/gentoo-portage"
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+# a current portage tree before it exits with an error. This allows
+# for a more successful retrieval without user intervention most times.
+#RSYNC_RETRIES="3"
+#
+# RSYNC_TIMEOUT sets the length of time rsync will wait before it times out
+# on a connection. Most users will benefit from this setting as it will
+# reduce the amount of 'dead air' they experience when they run across
+# the occasional, unreachable mirror. Dialup users might want to set this
+# value up around the 300 second mark.
+#RSYNC_TIMEOUT=180
+
+# Advanced Features
+# =================
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+# program is compiled. Presently the only use is for specifying
+# the number of parallel makes (-j) to perform. The suggested number
+# for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+# Note: This is an increment. Running emerge in a niced environment will
+# reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+# packages from the system after every successful merge. This is the
+# same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+# This does not affect the unpacked source. See 'noclean' below.
+#AUTOCLEAN="yes"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+# these settings are for developer use, but some are available to non-
+# developers as well.
+#
+# 'autoaddcvs' causes portage to automatically try to add files to cvs
+# that will have to be added later. Done at generation times
+# and only has an effect when 'cvs' is also set.
+# 'buildpkg' causes binary packages to be created of all packages that
+# are being merged.
+# 'ccache' enables ccache support via CC.
+# 'collision-protect'
+# prevents packages from overwriting files that are owned by
+# another package or by no package at all.
+# 'cvs' causes portage to enable all cvs features (commits, adds),
+# and to apply all USE flags in SRC_URI for digests -- for
+# developers only.
+# 'digest' causes digests to be generated for all packages being merged.
+# 'distcc' enables distcc support via CC.
+# 'distlocks' enables distfiles locking using fcntl or hardlinks. This
+# is enabled by default. Tools exist to help clean the locks
+# after crashes: /usr/lib/portage/bin/clean_locks.
+# 'fixpackages' allows portage to fix binary packages that are stored in
+# PKGDIR. This can consume a lot of time. 'fixpackages' is
+# also a script that can be run at any given time to force
+# the same actions.
+# 'gpg' enables basic verification of Manifest files using gpg.
+# This features is UNDER DEVELOPMENT and reacts to features
+# of strict and severe. Heavy use of gpg sigs is coming.
+# 'keeptemp' prevents the clean phase from deleting the temp files ($T)
+# from a merge.
+# 'keepwork' prevents the clean phase from deleting the WORKDIR.
+# 'maketest' causes ebuilds to perform testing phases if they are capable
+# of it. Some packages support this automaticaly via makefiles.
+# 'noauto' causes ebuild to perform only the action requested and
+# not any other required actions like clean or unpack -- for
+# debugging purposes only.
+# 'noclean' prevents portage from removing the source and temporary files
+# after a merge -- for debugging purposes only.
+# 'nostrip' prevents the stripping of binaries.
+# 'notitles' disables xterm titlebar updates (which contain status info).
+# 'sandbox' enables sandboxing when running emerge and ebuild. Doesn't
+# work on *BSD-based systems.
+# 'strict' causes portage to react strongly to conditions that are
+# potentially dangerous, like missing/incorrect Manifest files.
+# 'userpriv' allows portage to drop root privileges while it is compiling,
+# as a security measure. As a side effect this can remove
+# sandbox access violations for users.
+# 'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork autoaddcvs"
+#FEATURES="sandbox ccache distcc distlocks autoaddcvs"
+#
+# CCACHE_SIZE sets the space use limitations for ccache. The default size is
+# 2G, and will be set if not defined otherwise and ccache is in features.
+# Portage will set the default ccache dir if it is not present in the
+# user's environment, for userpriv it sets: ${PORTAGE_TMPDIR}/ccache
+# (/var/tmp/ccache), and for regular use the default is /root/.ccache.
+# Sizes are specified with 'G' 'M' or 'K'.
+# '2G' for 2 gigabytes, '2048M' for 2048 megabytes (same as 2G).
+#CCACHE_SIZE="512M"
+#
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+#
+# RSYNC_EXCLUDEFROM is a file that portage will pass to rsync when it updates
+# the portage tree. Specific chunks of the tree may be excluded from
+# consideration. This may cause dependency failures if you are not careful.
+# The file format is one pattern per line, blanks and ';' or '#' lines are
+# comments. See 'man rsync' for more details on the exclude-from format.
+#RSYNC_EXCLUDEFROM=/etc/portage/rsync_excludes
diff --git a/cnf/make.globals b/cnf/make.globals
new file mode 100644
index 00000000..d7d93a8e
--- /dev/null
+++ b/cnf/make.globals
@@ -0,0 +1,67 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/cnf/make.globals,v 1.56.2.5 2005/05/05 03:59:59 jstubbs Exp $
+# System-wide defaults for the Portage system
+
+# *****************************
+# ** DO NOT EDIT THIS FILE **
+# ***************************************************
+# **** CHANGES TO make.conf *OVERRIDE* THIS FILE ****
+# ***************************************************
+# ** Incremental Variables Accumulate Across Files **
+# ** USE, CONFIG_*, and FEATURES are incremental **
+# ***************************************************
+
+
+# Default rsync mirror
+SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+
+# Default distfiles mirrors
+GENTOO_MIRRORS="http://distfiles.gentoo.org http://distro.ibiblio.org/pub/Linux/distributions/gentoo"
+
+# Repository Paths
+PORTDIR=/usr/portage
+DISTDIR=/usr/portage/distfiles
+PKGDIR=/usr/portage/packages
+RPMDIR=/usr/portage/rpm
+
+# Temporary build directory
+PORTAGE_TMPDIR=/var/tmp
+
+# Fetching command (5 tries, passive ftp for firewall compatibility)
+FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp -P \${DISTDIR} \${URI}"
+RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp -P \${DISTDIR} \${URI}"
+
+# Default user options
+FEATURES="sandbox distlocks"
+
+# Default chunksize for binhost comms
+PORTAGE_BINHOST_CHUNKSIZE="3000"
+
+# By default wait 5 secs before cleaning a package
+CLEAN_DELAY="5"
+
+# By default wait 10 secs on an important warning
+EMERGE_WARNING_DELAY="10"
+
+# Automatically clean installed packages after they are updated.
+# This option will be removed and forced to yes.
+AUTOCLEAN="yes"
+
+# Number of times 'emerge --sync' will run before giving up.
+RSYNC_RETRIES="3"
+
+# Number of seconds rsync will wait before timing out.
+RSYNC_TIMEOUT="180"
+
+# Minimal CONFIG_PROTECT
+CONFIG_PROTECT="/etc"
+
+# *****************************
+# ** DO NOT EDIT THIS FILE **
+# ***************************************************
+# **** CHANGES TO make.conf *OVERRIDE* THIS FILE ****
+# ***************************************************
+# ** Incremental Variables Accumulate Across Files **
+# ** USE, CONFIG_*, and FEATURES are incremental **
+# ***************************************************
diff --git a/make-man-tarball.sh b/make-man-tarball.sh
new file mode 100755
index 00000000..0f1f3ed4
--- /dev/null
+++ b/make-man-tarball.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+if [ -z "$1" ] ; then
+ echo "Usage: $0 <version>"
+ exit 1
+fi
+
+find man -name '*.eclass.5' > man-page-list
+tar -jcf portage-manpages-${1}.tar.bz2 --files-from man-page-list
+echo "Packed away $(wc -l man-page-list | cut -f1 -d' ') manpages"
+rm -f man-page-list
+
+ls -l portage-manpages-${1}.tar.bz2
diff --git a/man/alternatives.eclass.5 b/man/alternatives.eclass.5
new file mode 100644
index 00000000..0e536b3b
--- /dev/null
+++ b/man/alternatives.eclass.5
@@ -0,0 +1,59 @@
+.TH ALTERNATIVES.ECLASS 5 "Nov 2004" "Portage 2.0.51" portage
+.SH NAME
+alternatives \- interface for SLOT'ed packages requiring a symbolic link to the
+latest version
+.SH DESCRIPTION
+The \fBalternatives\fR eclass provides an interface for SLOT'ed packages that
+require a symbolic link that points to the latest version installed. Due to the
+varying order in which SLOT'ed versions may be installed, the symbolic link is
+not always guaranteed to point to the latest version. The \fBalternatives\fR
+eclass attempts to solve this problem.
+.br
+
+There are currently two methods in which this eclass may be used. The first
+method involves variable invocation (via \fBSOURCE\fR and \fBALTERNATIVES\fR),
+while the second method involves function invocation (via \fBalternatives_makesym\fR
+or \fBalternatives_auto_makesym\fR). These will be described below, however,
+please keep in mind that the two methods are not meant to be used in conjunction.
+.SH VARIABLES
+.TP
+.B SOURCE = \fI"/usr/bin/python"\fR
+Defines the name of the symbolic link that will be created to point to the
+latest installed version.
+.TP
+.B ALTERNATIVES = \fI"/usr/bin/python2.3 /usr/bin/python2.2"\fR
+Defines a whitespace-delimited list of alternatives. The first one found to
+exist will become the target of the created symbolic link.
+.SH FUNCTIONS
+.TP
+.B alternatives_makesym \fI< symlink > < alt1 alt2 ... >\fR
+Creates the specified symbolic link to point to the first specified alternative
+found to exist. This function is normally invoked from \fBpkg_postinst\fR and
+\fBpkg_postrm\fR.
+.TP
+.B alternatives_auto_makesym \fI< symlink > < alt_glob >\fR
+A "smart" version of \fBalternatives_makesym\fR that attempts to automatically
+deduce which version to link to, based on the specified alternatives glob
+pattern (eg. "python[0-9].[0-9]"). Like \fBalternatives_makesym\fR, this
+function is normally invoked from \fBpkg_postinst\fR and \fBpkg_postrm\fR.
+.TP
+\fBNOTE\fR: the following default pkg functions are only meant for use with the
+variable invocation method.
+.TP
+.B alternatives_pkg_postinst
+Default pkg_postinst that calls \fBalternatives_makesym\fR if both the
+\fBSOURCE\fR and \fBALTERNATIVES\fR variables are set.
+.TP
+.B alternatives_pkg_postrm
+Default pkg_postrm that calls \fBalternatives_makesym\fR if both the \fBSOURCE\fR
+and \fBALTERNATIVES\fR variables are set.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/alternatives.eclass
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/alternatives.eclass.5,v 1.1.2.1 2005/08/20 05:05:31 vapier Exp $
diff --git a/man/check-kernel.eclass.5 b/man/check-kernel.eclass.5
new file mode 100644
index 00000000..8402b0b2
--- /dev/null
+++ b/man/check-kernel.eclass.5
@@ -0,0 +1,53 @@
+.TH "CHECK-KERNEL.ECLASS" "5" "Aug 2004" "Portage 2.0.51" "portage"
+.SH "NAME"
+check-kernel.eclass \- check kernel sources
+.SH "DESCRIPTION"
+The \fBcheck-kernel\fR eclass provides an easy interface for detecting kernel
+sources and retrieving various information.
+.SH "VARIABLES"
+The following variables are exported by the \fBcheck-kernel\fR eclass:
+.TP
+.BR KV_full
+Full kernel version (eg. 2.4.27-gentoo-r1)
+.TP
+.BR KV_major
+Major kernel version (eg. 2)
+.TP
+.BR KV_minor
+Minor kernel version (eg. 4)
+.TP
+.BR KV_micro
+Micro kernel version (eg. 27)
+.SH "FUNCTIONS"
+.TP
+.BR check_version_h
+Checks to make sure the /usr/src/linux symlink is correctly setup. If it is not,
+this function will print a huge error message and halt the emerge process.
+.TP
+.BR get_KV_info
+Parses the kernel's version.h to fill in the \fB${KV_full}\fR, \fB${KV_major}\fR,
+\fB${KV_minor}\fR, and \fB${KV_micro}\fR variables.
+.TP
+\fINOTE:\fR The following functions all return shell true/false.
+.TP
+.BR is_2_4_kernel
+Checks for kernel version 2.4.
+.TP
+.BR is_2_5_kernel
+Checks for kernel version 2.5.
+.TP
+.BR is_2_6_kernel
+Checks for kernel version 2.6.
+.TP
+.BR kernel_supports_modules
+Check to see if the kernel supports modules (CONFIG_MODULES).
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/check-kernel.eclass
+.SH "AUTHORS"
+Aaron Walker <ka0ttic@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/check-kernel.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/check-reqs.eclass.5 b/man/check-reqs.eclass.5
new file mode 100644
index 00000000..3c3afcc9
--- /dev/null
+++ b/man/check-reqs.eclass.5
@@ -0,0 +1,55 @@
+.TH CHECK-REQS.ECLASS 5 "Dec 2004" "Portage 2.0.51" "portage"
+.SH NAME
+check-reqs.eclass \- functions for checking proper build requirements
+.SH DESCRIPTION
+The \fBcheck-reqs\fR eclass provides a uniform interface for handling ebuilds
+which require an abnormally high amount of system resources. The variable(s)
+and function(s) mentioned here should usually be set/called from \fBpkg_setup\fR.
+.br
+
+\fBNOTE\fR: Minimum criteria for use of this eclass is a build that requires
+>256MB of RAM and/or >1GB of temporary or install space.
+.SH VARIABLES
+\fBNOTE\fR: all numerical values are evaluated as megabytes (MB).
+.TP
+.B CHECKREQS_ACTION = \fI"(warn|error|ignore)"\fR
+Defines action to take if current system resources do not satisfy requirements.
+\fBNOTE\fR: this variable is for end user only. Ebuilds must *not* override or
+set a default for this variable.
+.TP
+.B CHECKREQS_MEMORY = \fI"256"\fR
+Defines amount of memory required. Note that the \fBcheck-reqs\fR eclass does
+not take swap space into account when checking current memory resources.
+.TP
+.B CHECKREQS_DISK_BUILD = \fI"1024"\fR
+Defines amount of temporary build space required.
+.TP
+.B CHECKREQS_DISK_USR = \fI"1024"\fR
+Defines amount of /usr space required.
+.TP
+.B CHECKREQS_DISK_VAR = \fI"1024"\fR
+Defines amount of /var space required.
+.SH FUNCTIONS
+\fBNOTE\fR: all numerical values are evaluated as megabytes (MB). Any values
+should merely be rough estimates, and a high degree of precision should not
+be implied -- for example, "2048" (or "2000") are more appropriate than "2137".
+.TP
+.B check_reqs
+Performs resource checks based on above defined variables. If the checks fail,
+the action specified by \fBCHECKREQS_ACTION\fR will be executed. If for some
+reason the \fBcheck-reqs\fR eclass is unable to determine current resources,
+then no action will be performed. This function should be called from within
+\fBpkg_setup\fR.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/check-reqs.eclass
+.SH AUTHORS
+.nf
+Aaron Walker <ka0ttic@gentoo.org>
+Ciaran McCreesh <ciaranm@gentoo.org>
+.fi
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/check-reqs.eclass.5,v 1.1.2.3 2005/05/10 11:30:32 swegener Exp $
diff --git a/man/cvs.eclass.5 b/man/cvs.eclass.5
new file mode 100644
index 00000000..b4fdcf2a
--- /dev/null
+++ b/man/cvs.eclass.5
@@ -0,0 +1,80 @@
+.TH CVS.ECLASS 5 "Nov 2004" "Portage 2.0.51" portage
+.SH NAME
+cvs.eclass \- provides generic cvs fetching functions
+.SH DESCRIPTION
+The \fBcvs\fR eclass contains a suite of functions that are used to
+create 'live' cvs ebuilds. These ebuilds are called 'live' because
+they will checkout a cvs repository at the time of emerge and compile
+the source from the checkout. This eclass usually generates pretty
+unstable ebuilds ... but you can't get anymore bleeding edge than
+a live cvs checkout :).
+
+Common usage of this eclass involves setting \fBECVS_SERVER\fR and
+\fBECVS_MODULE\fR to grab the relevant cvs sources, and then letting
+the eclass define \fBsrc_unpack\fR for you.
+.SH VARIABLES
+.TP
+.B "ECVS_CVS_COMMAND" = \fI"cvs -q -f -z4"\fR
+The command to run in order to checkout the module from the cvs
+repository. You should not need to change this.
+.TP
+.B "ECVS_UP_OPTS" = \fI"-dP"\fR
+Options to pass to \fBECVS_CVS_COMMAND\fR when running an update.
+You should not have to modify this.
+.TP
+.B "ECVS_CO_OPTS" = \fI""\fR
+Options to pass to \fBECVS_CVS_COMMAND\fR when running a checkout.
+You should not have to modify this.
+.TP
+.B "ECVS_TOP_DIR" = \fI"${DISTDIR}/cvs-src"\fR
+Where the cvs modules will be stored and then accessed. You
+should not have to modify this.
+.TP
+.B "ECVS_SERVER" = \fI"offline"\fR
+Set this to the server that you will be checking the sources out of.
+If you set this to 'offline' then the eclass will assume the module
+is already checked out and in \fBECVS_TOP_DIR\fR. You almost always
+will set this variable.
+.TP
+.B "ECVS_AUTH" = \fI"pserver"\fR
+The authentication method to use to checkout the sources. Please
+note that the only method currently supported is 'pserver'. You
+should not need to modify this variable.
+.TP
+.B "ECVS_USER" = \fI"anonymous"\fR
+The user to log into the server with.
+.TP
+.B "ECVS_PASS" = \fI""\fR
+The password to log into the server with.
+.TP
+.B "ECVS_MODULE" = \fI""\fR
+The module to checkout from the cvs server. Please note that you
+*must* set this variable.
+.TP
+.B "ECVS_BRANCH" = \fI"HEAD"\fR
+The branch to checkout the sources from. The common targets are
+HEAD (current 'stable' cvs code) and SPLIT (current 'unstable' cvs
+code).
+.SH FUNCTIONS
+.TP
+.B cvs_fetch
+This function will setup \fBECVS_TOP_DIR\fR and any other pre-checkout
+steps that may need to be taken. Then it will login into the server
+and finally checkout the sources from cvs. You usually do not call
+this function yourself, but rather let it be handled by \fBcvs_src_unpack\fR.
+.TP
+.B cvs_src_unpack
+This function will determine where the cvs files need to be saved and
+then where they need to be placed after the checkout. The final result
+is that you will have a copy of \fBECVS_MODULE\fR in \fB${WORKDIR}\fR. Thus
+you will usually set \fB${S}\fR to be \fB${WORKDIR}/${ECVS_MODULE}\fR.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/cvs.eclass
+.SH AUTHORS
+Mike Frysinger <vapier@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/cvs.eclass.5,v 1.4.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/dispatch-conf.1 b/man/dispatch-conf.1
new file mode 100644
index 00000000..c28f516a
--- /dev/null
+++ b/man/dispatch-conf.1
@@ -0,0 +1,93 @@
+.TH "DISPATCH-CONF" "1" "May 2004" "Portage 2.0.51" "Portage"
+.SH NAME
+dispatch-conf \- Sanely update configuration files after emerging new packages
+.SH SYNOPSIS
+.B dispatch-conf
+.SH DESCRIPTION
+.I dispatch-conf
+is designed to be run after merging new packages in order to see if
+there are updates to the configuration files. If a new
+configuration file will overwrite an old one,
+.I dispatch-conf
+will prompt the user for a decision about how to resolve the
+discrepancy.
+Advantages of
+.I dispatch-conf
+include easy rollback (changes to config files are stored either using
+patches or rcs) and the ability to automatically update config files
+that the user has never modified or
+that differ from the current version only in CVS cruft or white space.
+
+.I dispatch-conf
+will check all directories in the \fICONFIG_PROTECT\fR variable. All
+config files found in \fICONFIG_PROTECT_MASK\fR will automatically be
+updated for you by \fIdispatch-conf\fR. See \fBmake.conf\fR(5) for more
+information.
+.SH OPTIONS
+.TP
+None.
+.SH USAGE
+.I dispatch-conf
+must be run as root, since the config files to be replaced are generally
+owned by root. Before running
+.I dispatch-conf
+for the first time the settings in
+.B /etc/dispatch-conf.conf
+should be edited and the archive directory specified in
+\fI/etc/dispatch-conf.conf\fR will need to be created. All changes to
+config files will be saved in the archive directory either as patches
+or using rcs, making restoration to an earlier version rather simple.
+
+When dispatch-conf finds a config file that has a new update the user
+is provided
+with a menu of options for how to handle the update:
+.TP
+.B u
+Update (replace) the current config file with the new config file and continue.
+.TP
+.B z
+Zap (delete) the new config file and continue.
+.TP
+.B n
+Skip to the next config file, leaving both the original config file and any
+\fICONFIG_PROTECT\fRed files.
+.TP
+.B e
+Edit the new config file, using the editor defined in \fI$EDITOR\fR.
+.TP
+.B m
+Interactively merge the current and new config files.
+.TP
+.B l
+Look at the differences between the pre-merged and merged config files.
+.TP
+.B t
+Toggle between the merged and pre-merged config files (in terms of which
+should be installed using the
+.Qt u
+command).
+.TP
+.B h
+Display a help screen.
+.TP
+.B q
+Quit
+.I dispatch-conf.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR make.conf (5), etc-update (1)
+.SH "FILES"
+.TP
+.B /etc/dispatch-conf.conf
+Configuration settings for \fIdispatch-conf\fR are stored here.
+.SH AUTHORS
+Jeremy Wohl
+.br
+Karl Trygve Kalleberg <karltk@gentoo.org>
+.br
+Mike Frysinger <vapier@gentoo.org>
+.br
+Grant Goodyear <g2boojum@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/dispatch-conf.1,v 1.3.2.1 2004/11/02 23:59:57 vapier Exp $
diff --git a/man/distutils.eclass.5 b/man/distutils.eclass.5
new file mode 100644
index 00000000..10244ddf
--- /dev/null
+++ b/man/distutils.eclass.5
@@ -0,0 +1,39 @@
+.TH "DISTUTILS.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+distutils.eclass \- allow easier installation of distutils-based python modules
+.SH "DESCRIPTION"
+The \fBdistutils\fR eclass is designed to allow easier installation of
+distutils-based python modules and their incorporation into the Gentoo
+Linux system. The eclass defines \fBsrc_compile\fR and \fBsrc_install\fR
+for you. You should be able to make a quick ebuild without setting up
+any extra variables or functions.
+.SH "VARIABLES"
+.TP
+.B PYTHON_SLOT_VERSION = \fI"[0|2.1]"\fR
+This allows you to depend on python-2.1. This is usually only
+needed by a -py21- ebuild. Otherwise you should not have to set this.
+.TP
+.B DOCS = \fI"<files to give to dodoc>"\fR
+This will cause \fBsrc_install\fR to install a few extra documentation
+files than normal.
+.SH "FUNCTIONS"
+.TP
+.B distutils_python_version
+This will setup the variables \fBPYVER_MAJOR\fR, \fBPYVER_MINOR\fR,
+and \fBPYVER\fR with the corresponding values of the python version.
+.TP
+.B distutils_python_tkinter
+If the package requires tkinter support, then calling this function
+will cause the ebuild to fail if tkinter support does not exist. An
+informative message will be displayed telling the user they need to
+recompile python with tkinter support for the ebuild to emerge.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/distutils.eclass
+.SH "AUTHORS"
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/distutils.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/ebook.eclass.5 b/man/ebook.eclass.5
new file mode 100644
index 00000000..eab78696
--- /dev/null
+++ b/man/ebook.eclass.5
@@ -0,0 +1,75 @@
+.TH "EBOOK.ECLASS" "5" "Aug 2004" "Portage 2.0.51" "portage"
+.SH "NAME"
+ebook.eclass \- easy installation of ebooks
+.SH "DESCRIPTION"
+The \fBebook\fR eclass makes writing ebuilds for ebooks a trivial task.
+.SH "VARIABLES"
+\fINOTE\fR: the following variables should be set \fBBEFORE\fR inheriting the
+\fBebook\fR eclass:
+.TP
+.BR "DESCRIPTION"
+Package description. Defaults to "\fB${P}\fR ebook based on ebook eclass".
+.TP
+.BR "RDEPEND"
+Run-time dependencies. Defaults to ">=dev-util/devhelp-0.6".
+.TP
+.BR "EBOOKNAME"
+The name of the ebook. This variable \fImust\fR be set.
+.TP
+.BR "EBOOKVERSION"
+The version of the ebook. This variable \fImust\fR be set, even if there is
+no version. See the \fB${NOVERSION}\fR variable below for more information.
+.TP
+.BR "SRC"
+The name of the file to download, minus the file extension. This variable
+defaults to \fB${EBOOKNAME}\fR-\fB${EBOOKVERSION}\fR.
+.TP
+.BR "SRC_URI"
+The ebook URI to download. Defaults to "http://lidn.sourceforge.net/books_download/\fB${SRC}\fR.\fB${EBOOKEXT}\fR".
+.TP
+.BR "EBOOKEXT"
+The file name extension of \fB${SRC}\fR. Defaults to tar.gz.
+.TP
+.BR "EBOOKDESTDIR"
+The directory inside \fB${DEVHELPROOT}\fR/books/\fB${EBOOKDIR}\fR in which the
+ebook will be installed. This variable defaults to \fB${EBOOKNAME}\fR-\fB${EBOOKVERSION}\fR
+or \fB${EBOOKNAME}\fR if the \fB${NOVERSION}\fR variable is set.
+.TP
+.BR "EBOOKFROMDIR"
+The directory in which the ebook's HTML files are located after unpacking
+\fB${SRC_URI}\fR. This directory is relative to \fB${WORKDIR}\fR. This
+variable defaults to \fB${EBOOKNAME}\fR-\fB${EBOOKVERSION}\fR or \fB${EBOOKNAME}\fR
+if the \fB${NOVERSION}\fR variable is set.
+.TP
+.BR "BOOKDEVHELPFILE"
+The file name that the ebook's book.devhelp will be installed as. This variable
+defaults to \fB${EBOOKNAME}\fR-\fB${EBOOKVERSION}\fR.devhelp or \fB${EBOOKNAME}\fR.devhelp
+if the \fB${NOVERSION}\fR variable is set.
+.TP
+.BR "BOOKDESTDIR"
+The directory in which the ebook's HTML will be installed into. Defaults to
+\fB${EBOOKNAME}\fR-\fB${EBOOKVERSION}\fR or \fB${EBOOKNAME}\fR is the \fB${NOVERSION}\fR
+variable is set.
+.TP
+.BR "NOVERSION"
+If this variable is not empty, all instances of \fB${EBOOKVERSION}\fR will be
+removed from all variables.
+.TP
+.BR "DEVHELPROOT"
+The location of devhelp's data directory. Defaults to usr/share/devhelp.
+.SH "FUNCTIONS"
+\fINOTE\fR: the following functions will be used as the defaults should they
+be omitted from the ebuild.
+.TP
+.BR "ebook_src_install"
+Installs \fB${BOOKDEVHELPFILE}\fR and all HTML files into \fB${DEVHELPROOT}\fR/books/\fB${EBOOKDESTDIR}\fR.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/ebook.eclass
+.SH "AUTHORS"
+Aaron Walker <ka0ttic@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/ebook.eclass.5,v 1.2.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/ebuild.1 b/man/ebuild.1
new file mode 100644
index 00000000..af5f493f
--- /dev/null
+++ b/man/ebuild.1
@@ -0,0 +1,184 @@
+.TH "EBUILD" "1" "Nov 2002" "Portage 2.0.51" "Portage"
+.SH "NAME"
+ebuild \- manual page for the ebuild program, a low level interface to
+the Portage system.
+.SH "SYNOPSIS"
+.B ebuild
+.I file command [command]\fR...
+.SH "DESCRIPTION"
+The ebuild program is a direct interface to the Portage system. It
+allows for direct action upon an ebuild with specific subcommands or
+groups of commands to perform in a specific ebuild's context and
+functions. Accepting an ebuild script and one or more commands
+as arguments, the ebuild program parses the ebuild script and
+execute the specified commands. Commands exist to fetch sources,
+unpack sources, compile sources, install object files into a temporary
+directory "image", merge the image to the local filesystem, create a
+bzipped tarball package out of the image, and more.
+.SH "FILE"
+This must be a valid ebuild script. For further information read
+\fBebuild\fR(5).
+.SH "COMMANDS"
+.TP
+.BR help
+Show a condensed form of the man page along with a lot of package
+specific information.
+.TP
+.BR setup
+Run all package specific setup actions and exotic system checks.
+.TP
+.BR clean
+Cleans the temporary build directory that Portage has created for
+this particular ebuild file. The temporary build directory normally
+contains the extracted source files as well as a possible
+"install image" (all the files that will be merged to the local
+filesystem or stored in a package). The location of the build
+directory is set by the BUILD_PREFIX variable. For information
+on what this variable is, run \fIemerge [\-v] info\fR, or to override
+this variable, see \fBmake.conf\fR(5).
+
+Note: Portage cleans up almost everything after a package has been
+successfully merged unless FEATURES contains 'noclean'. Adding noclean
+to FEATURES will cause a lot of files to remain and will consume large
+amounts of space, very quickly. It is not recommended to leave this on
+unless you have use for the sources post\-merge. Optionally one may,
+manual clean \fIrm \-rf /var/tmp/portage\fR will take care of all
+of these files.
+.TP
+.BR fetch
+Checks to see if all the sources specified in SRC_URI are available in
+DISTDIR (see \fBmake.conf\fR(5) for more information) and have a valid
+md5 checksum. If the sources aren't available, an attempt is made to
+download them from the locations specified in SRC_URI. If multiple
+download locations are listed for a particular file, Portage pings
+each location to see which location is closer. (May not be true
+presently.) The Gentoo Linux mirrors defined by GENTOO_MIRRORS is
+always considered first. If for some reason the current or
+just\-downloaded sources' md5 digests don't match those recorded
+in files/digest\-[package]\-[version\-rev], a warning is printed
+and ebuild exits with an error code of 1.
+.TP
+.BR digest
+Creates a digest file for the package in
+/usr/portage/[category]/[package]/files/. This digest file lists the
+md5sum's of all the files found in the SRC_URI. If the fetched source
+of the package is corrupt/bogus in some way, the md5sum will catch this.
+.TP
+.BR unpack
+Extracts the sources to a subdirectory in the \fIbuild directory\fR
+(BUILD_PREFIX) by running the \fIsrc_unpack()\fR function in the ebuild
+file. If no src_unpack() function has been specified, a default
+src_unpack() function is used that extracts all the files specified in
+SRC_URI. The sources are normally extracted to
+${BUILD_PREFIX}/[package]\-[version\-rev]/work. This particular directory
+can be referenced by using the ${WORKDIR} variable.
+
+If you're creating an ebuild, you'll want to make sure that the S
+(source directory) variable defined at at the top of your ebuild script
+points to the directory that contains your extracted sources. This
+directory is defined by default to be ${WORKDIR}/${P}, so it is not
+often required. The src_unpack() function is also responsible for
+making the appropriate patches to the sources so that they're ready
+for compilation.
+.TP
+.BR compile
+Compiles the extracted sources by running the the \fIsrc_compile()\fR
+function specified in the ebuild file. When src_compile() starts, the
+current working directory will be set to ${S}. When src_compile()
+completes, the sources should be fully compiled.
+.TP
+.BR test
+Run package specific test cases to verify that everything was built
+properly.
+.TP
+.BR preinst
+Run package specific actions that need to be done before the package
+is installed into the live filesystem.
+.TP
+.BR install
+Installs the package to the temporary \fIinstall directory\fR by running
+the \fIsrc_install()\fR function. When completed, the
+\fIinstall directory\fR (${BUILD_PREFIX}/[package]\-[version\-rev]/image)
+will contain all the files that should either be merged to the local
+file system or included in a binary package.
+.TP
+.BR postinst
+Run package specific actions that need to be done after the package
+is installed into the live filesystem. Usually helpful messages are
+shown here.
+.TP
+.BR qmerge
+This function installs all the files in the \fIinstall directory\fR
+to the live filesystem. The process works as follows: first, the
+\fIpkg_preinst()\fR function (if specified) is run. Then, the files
+are merged into the live filesystem, and the installed files' md5
+digests are recorded in
+\fI/var/db/pkg/${CATEOGRY}/${PN}\-[version\-rev]/CONTENTS\fR. After
+all the files have been merged, the \fIpkg_postinst()\fR function
+(if specified) is executed.
+.TP
+.BR merge
+Normally, to merge an ebuild, you need to \fIfetch\fR, \fIunpack\fR,
+\fIcompile\fR, \fIinstall\fR and \fIqmerge\fR. If you're simply
+interested in merging the ebuild, you can use this command, which
+will perform all these steps for you, stopping along the way if a
+particular step doesn't complete successfully.
+.TP
+.BR unmerge
+This function first executes the \fIpkg_prerm\fR function (if specified).
+Then it removes all files from the live filesystem that have a valid md5
+checksum and mtime in the package contents file. Any empty directories
+are recursively removed. Finally, it runs \fIpkg_postrm\fR function (if
+specified). It is safe to merge a new version of a package first and
+then unmerge the old one. In fact, this is the recommended package
+upgrade method.
+.TP
+.BR prerm
+Run package specific actions that need to be executed before the package is
+removed from the filesystem. See also \fIunmerge\fR.
+.TP
+.BR postrm
+Run package specific actions that need to be executed after the package is
+removed from the filesystem. See also \fIunmerge\fR.
+.TP
+.BR config
+Run package specific actions needed to be executed after the emerge
+process has completed. This usually entails configuration file
+setup or other similar setups that the user may wish to run.
+.TP
+.BR package
+This command is a lot like the \fImerge\fR command, except that after
+fetching, unpacking, compiling and installing, a .tbz2 binary package
+tarball is created and stored in ${PKGDIR}/All (${PKGDIR} defaults to
+/usr/portage/packages). A symbolic link is created in
+${PKGDIR}/${CATEGORY} that points to the package in ${PKGDIR}/All.
+.TP
+.BR rpm
+Builds a RedHat RPM package from the files in the temporary
+\fIinstall directory\fR. At the moment, the ebuild's dependency
+information is not incorporated into the RPM.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR ebuild (5),
+.BR make.conf (5)
+.TP
+The \fI/usr/sbin/ebuild.sh\fR script.
+.TP
+The helper apps in \fI/usr/lib/portage/bin\fR.
+.SH "FILES"
+.TP
+\fB/etc/make.conf\fR
+Contains variables for the build\-process and overwrites those
+in make.globals.
+.SH "AUTHORS"
+Achim Gottinger <achim@gentoo.org>
+.br
+Daniel Robbins <drobbins@gentoo.org>
+.br
+Nicholas Jones <carpaski@gentoo.org>
+.br
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/ebuild.1,v 1.16 2004/09/17 00:17:10 vapier Exp $"
diff --git a/man/ebuild.5 b/man/ebuild.5
new file mode 100644
index 00000000..349a2b81
--- /dev/null
+++ b/man/ebuild.5
@@ -0,0 +1,837 @@
+.TH "EBUILD" "5" "Feb 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+ebuild \- the internal format, variables, and functions in an ebuild script
+.SH "DESCRIPTION"
+The
+.BR ebuild (1)
+program accepts a single ebuild script as an argument. This script
+contains variables and commands that specify how to download, unpack,
+patch, compile, install and merge a particular software package from
+its original sources. In addition to all of this, the ebuild script
+can also contain pre/post install/remove commands, as required.
+.SH "EXAMPLES"
+Here's a simple example ebuild:
+
+.DS
+.nf
+# Copyright 1999\-2005 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header:
+
+inherit some_eclass another_eclass
+
+DESCRIPTION="Super\-useful stream editor (sed)"
+HOMEPAGE="http://www.gnu.org/software/sed/sed.html"
+SRC_URI="ftp://alpha.gnu.org/pub/gnu/sed/${P}.tar.gz"
+
+LICENSE="GPL\-2"
+SLOT="0"
+KEYWORDS="~x86"
+IUSE=""
+
+DEPEND="virtual/libc"
+RDEPEND="virtual/libc"
+
+src_compile() {
+ econf || die "could not configure"
+ emake || die "emake failed"
+}
+
+src_install() {
+ into /usr
+ doinfo doc/sed.info
+ doman doc/sed.1
+ into /
+ dobin sed/sed || die "dobin sed failed"
+ dodir /usr/bin
+ dosym /bin/sed /usr/bin/sed
+ dodoc NEWS README* THANKS TODO AUTHORS BUGS ANNOUNCE
+}
+.fi
+.SH "VARIABLES"
+.TP
+.B MISC USAGE NOTES
+- PORTAGE* and PORTDIR* variables may be found in \fBmake.conf\fR(5).
+.br
+- When assigning values to variables in ebuilds, you \fBcannot have a space\fR
+between the variable name and the equal sign.
+.TP
+.B P
+This variable contains the package name without the ebuild revision.
+This variable must NEVER be modified.
+.br
+\fBxfree-4.2.1-r2.ebuild\fR --> \fB$P\fR=='\fIxfree-4.2.1\fR'
+.TP
+.B PN
+Contains the name of the script without the version number.
+.br
+\fBxfree-4.2.1-r2.ebuild\fR --> \fB$PN\fR=='\fIxfree\fR'
+.TP
+.B PV
+Contains the version number without the revision.
+.br
+\fBxfree-4.2.1-r2.ebuild\fR --> \fB$PV\fR=='\fI4.2.1\fR'
+.TP
+.B PR
+Contains the revision number or 'r0' if no revision number exists.
+.br
+\fBxfree-4.2.1-r2.ebuild\fR --> \fB$PR\fR=='\fIr2\fR'
+.TP
+.B PVR
+Contains the version number with the revision.
+.br
+\fBxfree-4.2.1-r2.ebuild\fR --> \fB$PVR\fR=='\fI4.2.1-r2\fR'
+.TP
+.B PF
+Contains the full package name \fI[PN]\-[PVR]\fR
+.br
+\fBxfree-4.2.1-r2.ebuild\fR --> \fB$PF\fR=='\fIxfree-4.2.1-r2\fR'
+.TP
+.B A
+Contains all source files required for the package. This variable must
+not be defined. It is autogenerated from the \fISRC_URI\fR variables.
+.TP
+\fBWORKDIR\fR = \fI"${PORTAGE_TMPDIR}/portage/${PF}/work"\fR
+Contains the path to the package build root. Do not modify this variable.
+.TP
+\fBFILESDIR\fR = \fI"${PORTDIR}/${CATEGORY}/${PN}/files"\fR
+Contains the path to the 'files' sub folder in the package specific
+location in the portage tree. Do not modify this variable.
+.TP
+\fBS\fR = \fI"${WORKDIR}/${P}"\fR
+Contains the path to the temporary \fIbuild directory\fR. This variable
+is used by the functions \fIsrc_compile\fR and \fIsrc_install\fR. Both
+are executed with \fIS\fR as the current directory. This variable may
+be modified to match the extraction directory of a tarball for the package.
+.TP
+\fBT\fR = \fI"${PORTAGE_TMPDIR}/portage/${PF}/temp"\fR
+Contains the path to a \fItemporary directory\fR. You may use this for
+whatever you like.
+.TP
+\fBD\fR = \fI"${PORTAGE_TMPDIR}/portage/${PF}/image"\fR
+Contains the path to the temporary \fIinstall directory\fR. Every write
+operation that does not involve the helper tools and functions (found below)
+should be prefixed with ${D}. Do not modify this variable. This will not be
+available inside of the pkg_* functions, see \fIIMAGE\fR below.
+.TP
+\fBIMAGE\fR = \fI"${PORTAGE_TMPDIR}/portage/${PF}/image"\fR
+Contains the path to the temporary \fIimage directory\fR. When inside of the
+\fIpkg_*\fR functions, you should access the \fIIMAGE\fR directory instead of
+the \fID\fR directory. Do not modify this variable.
+.TP
+\fBDESCRIPTION\fR = \fI"A happy little package"\fR
+Should contain a short description of the package.
+.TP
+\fBSRC_URI\fR = \fI"http://happy.com/little/${P}.tar.gz"\fR
+Contains a list of URI's for the required source files. It can contain
+multiple URI's for a single source file. The fastest location is chosen
+if the file was not found at \fIGENTOO_MIRROR\fB\fR.
+.TP
+\fBHOMEPAGE\fR = \fI"http://happy.com/"\fR
+Should contain a list of URL's for the sources main sites and other further
+package dependent information.
+.TP
+\fBKEYWORDS\fR = \fI[-~][x86,ppc,sparc,mips,alpha,arm,hppa]\fR
+Should contain appropriate list of arches that the ebuild is know to
+work/not work. By default if you do not know if an ebuild runs under
+a particular arch simply omit that KEYWORD. If the ebuild will not
+work on that arch include it as \-ppc for example. If the ebuild is
+being submitted for inclusion, it must have ~arch set for architectures
+where it has been PROVEN TO WORK. (Packages KEYWORDed this way may be
+unmasked for testing by setting ACCEPT_KEYWORDS="~arch" on the command
+line, or in \fBmake.conf\fR(5)) For an authoritative list please review
+/usr/portage/profiles/arch.list.
+.TP
+\fBSLOT\fR
+This sets the SLOT for packages that may need to co\-exist. By default
+you should set \fBSLOT\fR="0" unless you know what you are doing and need
+to do otherwise. This value should \fINEVER\fR be left undefined.
+.TP
+\fBLICENSE\fR
+This should be a space delimited list of licenses that the package falls
+under. This \fB_must_\fR be set to a matching license in
+/usr/portage/licenses/. If the license does not exist in portage yet you
+must add it first.
+.TP
+\fBIUSE\fR
+This should be a list of any and all USE flags that are leveraged within
+your build script. The only USE flags that should not be listed here are
+arch related flags (see \fBKEYWORDS\fR).
+.TP
+\fBDEPEND\fR
+This should contain a list of all packages that are required for the
+program to compile.
+.RS
+.TP
+.B DEPEND Atoms
+A depend atom is simply a dependency that is used by portage when calculating
+relationships between packages. Please note that if the atom has not already
+been emerged, then the latest version available is matched.
+.RS
+.TP
+.B Atom Bases
+The base atom is just a full category/packagename. Hence, these are base atoms:
+
+.nf
+.I sys-apps/sed
+.I sys-libs/zlib
+.I net-misc/dhcp
+.fi
+.TP
+.B Atom Versions
+It is nice to be more specific and say that only certain versions of atoms are
+acceptable. Note that versions must be combined with a prefix (see below). Hence
+you may add a version number as a postfix to the base:
+
+.nf
+sys-apps/sed\fI-4.0.5\fR
+sys-libs/zlib\fI-1.1.4-r1\fR
+net-misc/dhcp\fI-3.0_p2\fR
+.fi
+
+Versions are normally made up of two or three numbers separated by periods, such
+as 1.2 or 4.5.2. This string may be followed by a character such as 1.2a or 4.5.2z.
+Note that this letter is \fBnot\fR meant to indicate alpha, beta, etc... status.
+For that, use the optional suffix; either _alpha, _beta, _pre (pre-release), _rc
+(release candidate), or _p (patch). This means for the 3rd pre-release of a package,
+you would use something like 1.2_pre3.
+.TP
+.B Atom Prefix Operators [> >= = <= <]
+Sometimes you want to be able to depend on general versions rather than specifying
+exact versions all the time. Hence we provide standard boolean operators:
+
+.nf
+\fI>\fRmedia-libs/libgd-1.6
+\fI>=\fRmedia-libs/libgd-1.6
+\fI=\fRmedia-libs/libgd-1.6
+\fI<=\fRmedia-libs/libgd-1.6
+\fI<\fRmedia-libs/libgd-1.6
+.fi
+.TP
+.B Extended Atom Prefixes [!~] and Postfixes [*]
+Now to get even fancier, we provide the ability to define blocking packages and
+version range matching. Also note that these extended prefixes/postfixes may
+be combined in any way with the atom classes defined above. Here are some common
+examples you may find in the portage tree:
+
+.nf
+\fI!\fRapp-text/dos2unix
+=dev-libs/glib-2\fI*\fR
+\fI!\fR=net-fs/samba-2\fI*\fR
+\fI~\fRnet-libs/libnet-1.0.2a
+.fi
+
+\fI!\fR means block packages from being installed at the same time.
+.br
+\fI*\fR means match any version of the package so long as the specified base
+is matched. So with a version of '2*', we can match '2.1', '2.2', '2.2.1',
+etc... and not match version '1.0', '3.0', '4.1', etc...
+.br
+\fI~\fR means match any revision of the base version specified. So in the
+above example, we would match versions '1.0.2a', '1.0.2a-r1', '1.0.2a-r2',
+etc...
+.RE
+.TP
+.B Dynamic DEPENDs
+Sometimes programs may depend on different things depending on the USE
+variable. Portage offers a few options to handle this. Note that when
+using the following syntaxes, each case is considered as 1 Atom in the
+scope it appears. That means that each Atom both conditionally include
+multiple Atoms and be nested to an infinite depth.
+.RS
+.TP
+.B usevar? ( DEPEND Atom )
+To include the jpeg library when the user has jpeg in \fBUSE\fR, simply use the
+following syntax:
+.br
+.B jpeg? ( media-libs/jpeg)
+.TP
+.B !usevar? ( Atom )
+If you want to include a package only if the user does not have a certain option
+in their \fBUSE\fR variable, then use the following syntax:
+.br
+.B !nophysfs? ( dev-games/physfs )
+.br
+This is often useful for those times when you want to want to add optional support
+for a feature and have it enabled by default.
+.TP
+.B usevar? ( Atom if true ) !usevar? ( Atom if false )
+For functionality like the tertiary operator found in C you must use
+two statements, one normal and one inverted. If a package uses
+GTK2 or GTK1, but not both, then you can handle that like this:
+.br
+.B gtk2? ( =x11-libs/gtk+-2* ) !gtk2? ( =x11-libs/gtk+-1* )
+.br
+That way the default is the superior GTK2 library.
+.TP
+.B || ( Atom Atom ... )
+When a package can work with a few different packages but a virtual is not
+appropriate, this syntax can easily be used.
+.nf
+.B || (
+.B app-games/unreal-tournament
+.B app-games/unreal-tournament-goty
+.B )
+.fi
+Here we see that unreal-tournament has a normal version and it has a goty version.
+Since they provide the same base set of files, another package can use either.
+Adding a virtual is inappropriate due to the small scope of it.
+.br
+Another good example is when a package can be built with multiple video
+interfaces, but it can only ever have just one.
+.nf
+.B || (
+.B sdl? ( media-libs/libsdl )
+.B svga? ( media-libs/svgalib )
+.B opengl? ( virtual/opengl )
+.B ggi? ( media-libs/libggi )
+.B virtual/x11
+.B )
+.fi
+Here only one of the packages will be chosen, and the order of preference is
+determined by the order in which they appear. So sdl has the best chance of being
+chosen, followed by svga, then opengl, then ggi, with a default of X if the user
+does not specify any of the previous choices.
+.RE
+
+.RE
+.TP
+\fBRDEPEND\fR
+This should contain a list of all packages that are required for this
+program to run (aka runtime depend). If this is not set, then it
+defaults to the value of \fBDEPEND\fR.
+.br
+You may use the same syntax to vary dependencies as seen above in \fBDEPEND\fR.
+.TP
+\fBPDEPEND\fR
+This should contain a list of all packages that will have to be installed after
+the program has been merged.
+.br
+You may use the same syntax to vary dependencies as seen above in \fBDEPEND\fR.
+.TP
+\fBRESTRICT\fR = \fI[fetch,mirror,nostrip,userpriv]\fR
+This should be a space delimited list of portage features to restrict.
+.PD 0
+.RS
+.TP
+.I fetch
+like \fInomirror\fR but the files will not be fetched via \fBSRC_URI\fR either.
+.TP
+.I mirror
+files in \fBSRC_URI\fR will not be downloaded from the \fBGENTOO_MIRRORS\fR.
+.TP
+.I primaryuri
+fetch from URL's in \fBSRC_URI\fR before \fBGENTOO_MIRRORS\fR.
+.TP
+.I nostrip
+final binaries/libraries will not be stripped of debug symbols.
+.TP
+.I userpriv
+Disables userpriv for specific packages.
+.RE
+.PD 1
+.TP
+\fBPROVIDE\fR = \fI"virtual/TARGET"\fR
+This variable should only be used when a package provides a virtual target.
+For example, blackdown-jdk and sun-jdk provide \fIvirtual/jdk\fR. This
+allows for packages to depend on \fIvirtual/jdk\fR rather than on blackdown
+or sun specifically.
+.SH "PORTAGE DECLARATIONS"
+.TP
+.B inherit
+Inherit is portage's maintainance of extra classes of functions that
+are external to ebuilds and provided as inheritable capabilities and
+data. They define functions and set data types as drop-in replacements,
+expanded, and simplified routines for extremely common tasks to streamline
+the build process. Inherit may only be called once in an ebuild and it may
+\fBnever be wrapped within any conditionals\fR of any kind. Specification of
+the eclasses contains only their name and not the \fI.eclass\fR extention.
+.SH "FUNCTIONS"
+.TP
+.B pkg_nofetch
+If you turn on \fIfetch\fR in \fBRESTRICT\fR, then this function will be
+run when the files in \fBSRC_URI\fR cannot be found. Useful for
+displaying information to the user on *how* to obtain said files. All
+you have to do is output a message and let the function return. Do not
+end the function with a call to \fBdie\fR.
+.TP
+.B pkg_setup
+This function can be used if the package needs specific setup actions or
+checks to be preformed before anything else.
+.br
+Initial working directory of ${PORTAGE_TMPDIR}.
+.TP
+.B src_unpack
+This function is used to unpack all the sources in \fIA\fR to \fIWORKDIR\fR.
+If not defined in the \fIebuild script\fR it calls \fIunpack ${A}\fR. Any
+patches and other pre configure/compile modifications should be done here.
+.br
+Initial working directory of $WORKDIR.
+.TP
+.B src_compile
+All necessary steps for configuration and compilation should be done in here.
+.br
+Initial working directory of $S.
+.TP
+.B src_test
+Run all package specific test cases. The default is to run 'make check'
+followed 'make test'.
+.br
+Initial working directory of $S.
+.TP
+.B src_install
+Should contain everything required to install the package in the temporary
+\fIinstall directory\fR.
+.br
+Initial working directory of $S.
+.TP
+.B pkg_preinst pkg_postinst
+All modifications required on the live\-filesystem before and after the
+package is merged should be placed here. Also commentary for the user
+should be listed here as it will be displayed last.
+.br
+Initial working directory of $PWD.
+.TP
+.B pkg_prerm pkg_postrm
+Like the pkg_*inst functions but for unmerge.
+.br
+Initial working directory of $PWD.
+.TP
+.B pkg_config
+This function should contain optional basic configuration steps.
+.br
+Initial working directory of $PWD.
+.SH "HELPER FUNCTIONS: GENERAL"
+.TP
+\fBdie\fR \fI[reason]\fR
+Causes the current emerge process to be aborted. The final display will
+include \fIreason\fR.
+.TP
+\fBuse\fR \fI<USE item>\fR
+If \fIUSE item\fR is in the \fBUSE\fR variable, \fIUSE item\fR will be
+echoed and the function will return 0. If \fIUSE item\fR is not in the
+\fBUSE\fR variable, the function will return 1. \fBuseq\fR is a non-echoing
+version of \fBuse\fR.
+.RS
+.TP
+.I Example:
+.nf
+if useq gnome ; then
+ guiconf="--enable-gui=gnome --with-x"
+elif useq gtk ; then
+ guiconf="--enable-gui=gtk --with-x"
+elif useq X ; then
+ guiconf="--enable-gui=athena --with-x"
+else
+ # No gui version will be built
+ guiconf=""
+fi
+.fi
+.RE
+.TP
+\fBuse_with\fR \fI<USE item>\fR \fI[configure option]\fR
+Useful for creating custom options to pass to a configure script. If
+\fIUSE item\fR is in the \fBUSE\fR variable, then the string
+\fI--with-[configure option]\fR will be echoed. If \fIUSE item\fR is
+not in the \fBUSE\fR variable, then the string
+\fI--without-[configure option]\fR will be echoed. If
+\fIconfigure option\fR is not specified, then \fIUSE item\fR will be
+used in its place.
+.RS
+.TP
+.I Example:
+.nf
+USE="jpeg"
+myconf="$(use_with jpeg libjpeg)"
+(myconf now has the value "--with-libjpeg")
+
+USE=""
+myconf="$(use_with jpeg libjpeg)"
+(myconf now has the value "--without-libjpeg")
+
+USE="opengl"
+myconf="$(use_with opengl")
+(myconf now has the value "--with-opengl")
+.fi
+.RE
+.TP
+\fBuse_enable\fR \fI<USE item>\fR \fI[configure option]\fR
+Useful for creating custom options to pass to a configure script. If
+\fIUSE item\fR is in the \fBUSE\fR variable, then the string
+\fI--enable-[configure option]\fR will be echoed. If \fIUSE item\fR is
+not in the \fBUSE\fR variable, then the string
+\fI--disable-[configure option]\fR will be echoed. If \fIconfigure option\fR
+is not specified, then \fIUSE item\fR will be used in its place.
+.br
+See \fBuse_with\fR for an example.
+.TP
+\fBhas\fR \fI<item>\fR \fI<item list>\fR
+If \fIitem\fR is in \fIitem list\fR, then \fIitem\fR is echoed and \fBhas\fR
+returns 0. Otherwise, nothing is echoed and 1 is returned. As indicated with
+use, there is a non-echoing version \fBhasq\fR. Please use \fBhasq\fR in all
+places where output is to be disregarded. Never use the output for calculation.
+.br
+The \fIitem list\fR is delimited by the \fIIFS\fR variable. This variable
+has a default value of ' ', or a space. It is a \fBbash\fR(1) setting.
+.TP
+\fBhas_version\fR \fI<category/package-version>\fR
+Check to see if \fIcategory/package-version\fR is installed on the system.
+The parameter accepts all values that are acceptable in the \fBDEPEND\fR
+variable. The function returns 0 if \fIcategory/package-version\fR is
+installed, 1 otherwise.
+.TP
+\fBbest_version\fR \fI<package name>\fR
+This function will look up \fIpackage name\fR in the database of currently
+installed programs and echo the "best version" of the package that is
+currently installed. The function returns 0 if there is a package that
+matches \fIpackage name\fR. Otherwise, the function will return 1.
+.RS
+.TP
+.I Example:
+VERINS="$(best_version net-ftp/glftpd)"
+.br
+(VERINS now has the value "net-ftp/glftpd-1.27" if glftpd-1.27 is installed)
+.RE
+.SH "HELPER FUNCTIONS: OUTPUT"
+.TP
+\fBeinfo\fR \fI"informative message"\fR
+If you need to display an message that you wish the user to read and take
+notice of, then use \fBeinfo\fR. It works just like \fBecho\fR(1), but
+adds a little more to the output so as to catch the user's eye.
+.TP
+\fBewarn\fR \fI"warning message"\fR
+Same as \fBeinfo\fR, but should be used when showing a warning to the user.
+.TP
+\fBeerror\fR \fI"error message"\fR
+Same as \fBeinfo\fR, but should be used when showing an error to the user.
+.SH "HELPER FUNCTIONS: UNPACK"
+.TP
+\fBunpack\fR \fI<source>\fR \fI[list of more sources]\fR
+This function uncompresses and/or untars a list of sources into the current
+directory. The function will append \fIsource\fR to the \fBDISTDIR\fR variable.
+.SH "HELPER FUNCTIONS: COMPILE"
+.TP
+\fBeconf\fR \fI[configure options]\fR
+This is used as a replacement for configure. Performs:
+.nf
+configure \\
+ --prefix=/usr \\
+ --host=${CHOST} \\
+ --mandir=/usr/share/man \\
+ --infodir=/usr/share/info \\
+ --datadir=/usr/share \\
+ --sysconfdir=/etc \\
+ --localstatedir=/var/lib \\
+ \fI${EXTRA_ECONF}\fR \\
+ \fIconfigure options\fR
+.fi
+Note that the \fIEXTRA_ECONF\fR is for users only, not for ebuild
+writers. If you wish to pass more options to configure, just pass the
+extra arguements to \fBeconf\fR.
+.TP
+\fBemake\fR \fI[make options]\fR
+This is used as a replacement for make. Performs 'make ${MAKEOPTS}
+\fImake options\fR' (as set in /etc/make.globals), default is MAKEOPTS="\-j2".
+
+\fB***warning***\fR
+.br
+if you are going to use \fBemake\fR, make sure your build is happy with
+parallel makes (make \-j2). It should be tested thoroughly as parallel
+makes are notorious for failing _sometimes_ but not always.
+.SH "HELPER FUNCTIONS: INSTALL"
+.TP
+\fBeinstall\fR \fI[make options]\fR
+This is used as a replacement for make install. Performs:
+.nf
+make \\
+ prefix=${D}/usr \\
+ datadir=${D}/usr/share \\
+ infodir=${D}/usr/share/info \\
+ localstatedir=${D}/var/lib \\
+ mandir=${D}/usr/share/man \\
+ sysconfdir=${D}/etc \\
+ \fI${EXTRA_EINSTALL}\fR \\
+ \fImake options\fR \\
+ install
+.fi
+Please do \fBnot\fR use this in place of 'make install DESTDIR=${D}'.
+That is the preferred way of installing make-based packages. Also, do
+not utilize the \fIEXTRA_EINSTALL\fR variable since it is for users.
+
+.PD 0
+.TP
+.B prepall
+.TP
+.B prepalldocs
+.TP
+.B prepallinfo
+.TP
+.B prepallman
+.TP
+.B prepallstrip
+.PD 1
+Useful for when a package installs into \fB${D}\fR via scripts
+(i.e. makefiles). If you want to be sure that libraries are executable,
+aclocal files are installed into the right place, doc/info/man files are
+all compressed, and that executables are all stripped of debugging symbols,
+then use these suite of functions.
+.RS
+.PD 0
+.TP
+.B prepall:
+Runs \fBprepallman\fR, \fBprepallinfo\fR, \fBprepallstrip\fR, sets
+libraries +x, and then checks aclocal directories. Please note this
+does \fI*not*\fR run \fBprepalldocs\fR.
+.TP
+.B prepalldocs:
+Compresses all doc files in ${D}/usr/share/doc.
+.TP
+.B prepallinfo:
+Compresses all info files in ${D}/usr/share/info.
+.TP
+.B prepallman:
+Compresses all man files in ${D}/usr/share/man.
+.TP
+.B prepallstrip:
+Strips all executable files of debugging symboles. This includes libraries.
+.RE
+
+.TP
+\fBprepinfo\fR \fI[dir]\fR
+.TP
+\fBpreplib\fR \fI[dir]\fR
+.TP
+\fBpreplib.so\fR \fI[dir]\fR
+.TP
+\fBprepman\fR \fI[dir]\fR
+.TP
+\fBprepstrip\fR \fI[dir]\fR
+.PD 1
+Similiar to the \fBprepall\fR functions, these are subtle in their differences.
+.RS
+.PD 0
+.TP
+.B prepinfo:
+If a \fIdir\fR is not specified, then \fBprepinfo\fR will assume the dir
+\fIusr\fR. \fBprepinfo\fR will then compress all the files in
+${D}/\fIdir\fR/info.
+.TP
+.B preplib:
+If a \fIdir\fR is not specified, then \fBpreplib\fR will assume the dir
+\fIusr\fR. \fBpreplib\fR will then run 'ldconfig -n -N' on ${D}/\fIdir\fR/lib.
+.TP
+.B preplib.so:
+All the files with '.so' in their name and are found in ${D}/\fIdir\fR will
+be stripped of their debug symbols. You may specify multiple directories.
+.TP
+.B prepman:
+If a \fIdir\fR is not specified, then \fBprepman\fR will assume the dir
+\fIusr\fR. \fBprepman\fR will then compress all the files in
+${D}/\fIdir\fR/man/*/.
+.TP
+.B prepstrip:
+All the files found in ${D}/\fIdir\fR will be stripped. You may specify
+multiple directories.
+.RE
+.PD 1
+.TP
+\fBdopython\fR \fI<commands>\fR
+Performs \fIcommands\fR with python and returns the result.
+.TP
+\fBdosed\fR \fI"s:orig:change:g" <filename>\fR
+Performs sed (including cp/mv \fIfilename\fR) on \fIfilename\fR.
+.br
+.BR 'dosed\ "s:/usr/local:/usr:g"\ /usr/bin/some-script'
+runs sed on ${D}/usr/bin/some-script
+.TP
+\fBdodir\fR \fI<path>\fR
+Creates a directory inside of ${D}.
+.br
+.BR 'dodir\ /usr/lib/apache'
+creates ${D}/usr/lib/apache. Note that the do* functions will run
+\fBdodir\fR for you.
+.TP
+\fBdiropts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in
+\fBdodir\fR. The default is \fI-m0755\fR.
+.TP
+\fBinto\fR \fI<path>\fR
+Sets the root (\fIDESTTREE\fR) for other functions like \fBdobin\fR,
+\fBdosbin\fR, \fBdoman\fR, \fBdoinfo\fR, \fBdolib\fR.
+.br
+The default root is /usr.
+.TP
+\fBkeepdir\fR \fI<path>\fR
+Tells portage to leave a directory behind even if it is empty. Functions
+the same as \fBdodir\fR.
+.TP
+\fBdobin\fR \fI<binary> [list of more binaries]\fR
+Installs a \fIbinary\fR or a list of binaries into \fIDESTTREE\fR/bin.
+Creates all necessary dirs.
+.TP
+\fBdosbin\fR \fI<binary> [list of more binaries]\fR
+Installs a \fIbinary\fR or a list of binaries into \fIDESTTREE\fR/sbin.
+Creates all necessary dirs.
+.TP
+\fBdoinitd\fR \fI<init.d script> [list of more init.d scripts]\fR
+Install Gentoo \fIinit.d scripts\fR. They will be installed into the
+correct location for Gentoo init.d scripts (/etc/init.d/). Creates all
+necessary dirs.
+.TP
+\fBdoconfd\fR \fI<conf.d file> [list of more conf.d file]\fR
+Install Gentoo \fIconf.d files\fR. They will be installed into the
+correct location for Gentoo conf.d files (/etc/conf.d/). Creates all
+necessary dirs.
+.TP
+\fBdoenvd\fR \fI<env.d entry> [list of more env.d entries]\fR
+Install Gentoo \fIenv.d entries\fR. They will be installed into the
+correct location for Gentoo env.d entries (/etc/env.d/). Creates all
+necessary dirs.
+
+.PD 0
+.TP
+\fBdolib\fR \fI<library>\fR \fI[list of more libraries]\fR
+.TP
+\fBdolib.a\fR \fI<library>\fR \fI[list of more libraries]\fR
+.TP
+\fBdolib.so\fR \fI<library>\fR \fI[list of more libraries]\fR
+.PD 1
+Installs a library or a list of libraries into \fIDESTTREE\fR/lib.
+Creates all necessary dirs.
+.TP
+\fBlibopts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in
+the \fBdolib\fR functions. The default is \fI-m0644\fR.
+.TP
+\fBdoman\fR \fI[\-i18n=<locale>]\fR \fI<man-page> [list of more man\-pages]\fR
+Installs manual\-pages into /usr/share/man/man[0\-9n] depending on the
+manual file ending. The files are gzipped if they are not already. You can
+specify locale-specific manpages with the \fI\-i18n\fR option. Then the
+man-page will be installed into /usr/share/man/\fI<locale>\fR/man[0\-9n].
+Creates all necessary dirs.
+
+.PD 0
+.TP
+\fBdohard\fR \fI<filename> <linkname>\fR
+.TP
+\fBdosym\fR \fI<filename> <linkname>\fR
+.PD 1
+Performs the ln command as either a hard link or symlink.
+.TP
+\fBdohtml\fR \fI [\-a filetypes] [\-r] [\-x list\-of\-dirs\-to\-ignore] [list\-of\-files\-and\-dirs]\fR
+Installs the files in the list of files (space\-separated list) into
+/usr/share/doc/${PF}/html provided the file ends in .html, .png, .js, .jpg,
+or .css. Setting \fI\-a\fR limits what types of files will be included,
+\fI\-A\fR appends to the default list, setting \fI\-x\fR sets which dirs to
+exclude (CVS excluded by default), \fI\-r\fR sets recursive.
+.TP
+\fBdoinfo\fR \fI<info-file> [list of more info\-files]\fR
+Installs info\-pages into \fIDESTDIR\fR/info. Files are automatically
+gzipped. Creates all necessary dirs.
+.TP
+\fBdojar\fR \fI<jar file> [list of more jar files]\fR
+Installs jar files into /usr/share/${PN}/lib and adds them to
+/usr/share/${PN}/classpath.env.
+.TP
+\fBdomo\fR \fI<locale-file> [list of more locale\-files] \fR
+Installs locale\-files into \fIDESTDIR\fR/usr/share/locale/[LANG]
+depending on local\-file's ending. Creates all necessary dirs.
+
+.PD 0
+.TP
+\fBfowners\fR \fI<permissions> <file> [files]\fR
+.TP
+\fBfperms\fR \fI<permissions> <file> [files]\fR
+.PD 1
+Performs chown (\fBfowners\fR) or chmod (\fBfperms\fR), applying
+\fIpermissions\fR to \fIfiles\fR.
+.TP
+\fBinsinto\fR \fI[path]\fR
+Sets the root (\fIINSDESTTREE\fR) for the \fBdoins\fR function.
+.br
+The default root is /.
+.TP
+\fBinsopts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in
+\fBdoins\fR. The default is \fI\-m0644\fR.
+.TP
+\fBdoins\fR \fI<file> [list of more files]\fR
+Installs files into \fIINSDESTTREE\fR. This function uses \fBinstall\fR(1).
+Creates all necessary dirs.
+.TP
+\fBexeinto\fR \fI[path]\fR
+Sets the root (\fIEXEDESTTREE\fR) for the \fBdoexe\fR function.
+.br
+The default root is /.
+.TP
+\fBexeopts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in \fBdoexe\fR.
+The default is \fI\-m0755\fR.
+.TP
+\fBdoexe\fR \fI<executable> [list of more executables]\fR
+Installs a executable or a list of executable into \fIEXEDESTTREE\fR.
+This function uses \fBinstall\fR(1). Creates all necessary dirs.
+.TP
+\fBdocinto\fR \fI[path]\fR
+Sets the relative subdir (\fIDOCDESTTREE\fR) used by \fBdodoc\fR.
+.TP
+\fBdodoc\fR \fI<document> [list of more documents]\fR
+Installs a document or a list of document into /usr/share/doc/${PF}/\fIDOCDESTTREE\fR.
+Files are automatically gzipped. Creates all necessary dirs.
+
+.PD 0
+.TP
+\fBnewbin\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewsbin\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewinitd\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewconfd\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewenvd\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewlib\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewlib.so\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewlib.a\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewman\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewinfo\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewins\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewexe\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewdoc\fR \fI<old file> <new filename>\fR
+.PD 1
+All these functions act like the do* functions, but they only work with one
+file and the file is installed as \fI[new filename]\fR.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (1),
+.BR make.conf (5)
+.TP
+The \fI/usr/sbin/ebuild.sh\fR script.
+.TP
+The helper apps in \fI/usr/lib/portage/bin\fR.
+.SH "FILES"
+.TP
+\fB/etc/make.conf\fR
+Contains variables for the build\-process and overwrites those in make.defaults.
+.TP
+\fB/etc/make.globals\fR
+Contains the default variables for the build\-process, you should edit
+\fI/etc/make.conf\fR instead.
+.SH "AUTHORS"
+.nf
+Achim Gottinger <achim@gentoo.org>
+Mark Guertin <gerk@gentoo.org>
+Nicholas Jones <carpaski@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+.fi
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/ebuild.5,v 1.73.2.8 2005/05/22 09:56:55 vapier Exp $
diff --git a/man/emerge.1 b/man/emerge.1
new file mode 100644
index 00000000..56f8a402
--- /dev/null
+++ b/man/emerge.1
@@ -0,0 +1,555 @@
+.TH "EMERGE" "1" "Jun 2003" "Portage 2.0.51" "Portage"
+.SH "NAME"
+emerge \- Command\-line interface to the Portage system
+.SH "SYNOPSIS"
+.TP
+.BR emerge
+[\fIoptions\fR] [\fIaction\fR] [\fIebuild\fR | \fItbz2file\fR | \fIclass\fR | \fIdependency\fR] ...
+.TP
+.BR emerge
+\fB\-\-sync\fR | \fB\-\-info\fR | \fB\-\-version\fR
+.TP
+.BR emerge
+\fB\-\-search\fR \fIsomestring\fR
+.TP
+.BR emerge
+\fB\-\-help\fR [\fBsystem\fR | \fBconfig\fR | \fBsync\fR]
+.SH "DESCRIPTION"
+\fBemerge\fR is the definitive command\-line interface to the Portage
+system. It is primarily used for installing packages, and \fBemerge\fR
+can automatically handle any dependencies that the desired package has.
+\fBemerge\fR can also update the \fBportage tree\fR, making new and
+updated packages available. \fBemerge\fR gracefully handles updating
+installed packages to newer releases as well. It handles both source
+and binary packages, and it can be used to create binary packages for
+distribution.
+.SH "EBUILDS, TBZ2S, CLASSES AND DEPENDENCIES"
+\fBemerge\fR primarily installs packages. You can specify
+packages to install in one of four main ways: an \fIebuild\fR,
+a \fItbz2file\fR, a \fIclass\fR, or a \fIdependency\fR.
+.LP
+.TP
+.BR ebuild
+An \fIebuild\fR must be, at a minimum, a valid Portage
+package directory name without a version or category, such as
+\fBportage\fR or \fBpython\fR.
+Both categories and version numbers may be used in addition, such
+as \fBsys\-apps/portage\fR or \fB=python\-2.2.1\-r2\fR.
+\fBemerge\fR
+ignores a trailing slash so that filename completion can be used.
+The \fIebuild\fR may also be an actual filename, such as
+\fB/usr/portage/app\-admin/python/python\-2.2.1\-r2.ebuild\fR.
+WARNING: The implementation of \fBemerge /path/to/ebuild\fR is broken and so this syntax shouldn't be used.
+.TP
+.BR tbz2file
+A \fItbz2file\fR must be a valid .tbz2 created with \fBebuild
+<package>\-<version>.ebuild package\fR or \fBemerge \-\-buildpkg
+[category/]<package>\fR or \fBquickpkg /var/db/pkg/<category>/<package>\fR.
+.TP
+.BR class
+Package classes are a convenient shorthand for large groups of
+packages. Two classes are currently supported: \fBsystem\fR
+and \fBworld\fR. \fBsystem\fR refers to a set of packages
+deemed necessary for your system to run properly. \fBworld\fR
+contains all of the packages in \fBsystem\fR, along with any
+other packages listed in \fB/var/lib/portage/world\fR. [See
+\fBFILES\fR below for more information.] Note that these
+commands are generally used in conjunction with \fB\-\-update\fR.
+.TP
+.BR dependency
+A \fIdependency\fR describes bounds on a package that you wish to install.
+\fISee portage(5) for the details on these 'atoms'.\fR For example,
+\fB>=dev\-lang/python\-2.2.1\-r2\fR matches the latest available version of
+Python greater than or equal to 2.2.1\-r2. Similarly,
+\fB<dev\-lang/python\-2.0\fR matches the latest available version of Python
+before 2.0. Note that in many shells you will need to escape characters such
+as '<' and '='; use single\- or double\-quotes around the \fIdependency\fR
+to get around escaping problems.
+.SH "ACTIONS"
+.TP
+.BR "No action"
+If no action is specified, the action is to merge in the specified
+packages, satisfying any dependencies that they may have. The
+arguments can be \fIebuilds\fR, \fItbz2s\fR, \fIclasses\fR, or
+\fIdependencies\fR. \fBNote that you need to use the \-\-usepkg
+option if you want to install a tbz2\fR. The packages are added
+to the \fBworld\fR file at the end, so that they are considered for
+later updating.
+.TP
+.BR "\-\-clean " (\fB\-c\fR)
+Cleans the system by removing packages that will not affect the
+functionality of the system. The arguments can be \fIebuilds\fR,
+\fIclasses\fR, or \fIdependencies\fR. For example, \fBemerge
+clean binutils\fR cleans out old versions of binutils;
+\fBemerge \-\-clean net\-www/mozilla\-0.9.9\-r2\fR cleans out that
+specific version of Mozilla. This is generally safe to use.
+\fBNote that\fR \-\-clean \fBdoes not remove unslotted packages.\fR
+.TP
+.BR \-\-depclean
+Determines all packages installed on the system that have no
+explicit reason for being there. \fBemerge\fR generates a list
+of packages which it expects to be installed by checking the
+\fBsystem\fR package list and the \fBworld\fR file. It then
+compares that list to the list of packages which are actually
+installed; the differences are listed as unnecessary packages
+and then unmerged after a short timeout. \fBWARNING: Removing some
+packages may cause packages which link to the removed package
+to stop working and complain about missing libraries.\fR
+Re\-emerge the complaining package to fix this issue.
+\fBNote that changes in USE flags can drastically affect the
+output of \-\-depclean.\fR
+.TP
+.BR \-\-info
+This is a list of information to include in bug reports which aids the
+developers with fixing any problems you may report. \fBPlease include this
+information when submitting a bug report.\fR Expanded output can be obtained
+with the \fI\-\-verbose\fR option.
+.TP
+.BR \-\-metadata
+Causes portage to process all the metacache files as is normally done on the
+tail end of an rsync update using \fBemerge \-\-sync\fR. The processing
+creates the cache database that portage uses for pre\-parsed lookups of
+package data.
+.TP
+.BR \-\-nocolor
+Make sure none of the output from portage contains color.
+.TP
+.BR "\-\-prune " (\fB\-P\fR)
+\fBWARNING: This action can remove important packages!\fR Tries to remove
+all but the last version installed. Since the command currently does not
+handle multiple versions of the same package properly, beware! This does not
+check dependencies, so it may also remove packages necessary for the proper
+operation of your system. \fBUse\fR \-\-clean \fBinstead unless you really
+know what you're doing\fR. Its arguments can be \fIebuilds\fR,
+\fIclasses\fR, or \fIdependencies\fR \-\- see \fB\-\-clean\fR above for
+examples. You have been warned!
+.TP
+.BR \-\-regen
+Causes portage to check and update the dependency cache of all ebuilds in the
+portage tree. The cache is used to speed up searches and the building of
+dependency trees. This command is not recommended for rsync users as rsync
+updates the cache using server\-side caches. If you do not know the
+differences between a 'rsync user' and some other user, then you are a 'rsync
+user' :). Rsync users should simply run \fBemerge \-\-sync\fR to regenerate
+the cache. After a portage update, rsync users may find it convenient to run
+\fBemerge \-\-metadata\fR to rebuild the cache as portage does at the end of
+a sync operation.
+.TP
+.BR "\-\-search " (\fB\-s\fR)
+Searches for matches of the supplied string in the portage tree.
+The \-\-search string is a regular expression. For example, \fBemerge
+\-\-search "^kde"\fR searches for any package that starts with "kde";
+\fBemerge \-\-search "gcc$"\fR searches for any package that ends with
+"gcc"; \fBemerge \-\-search "office"\fR searches for any package that
+contains the word "office". If you want to search the package
+descriptions as well, use the \fB\-\-searchdesc\fR option.
+.TP
+.BR \-\-sync
+Initiates a portage tree update with one of the rsync.gentoo.org
+mirrors. \fBNote that any changes you have made to the portage
+tree will be erased\fR. Except for special circumstances,
+this uses \fBrsync\fR to do the update. See \fBmake.conf\fR(5)'s
+description of PORTDIR_OVERLAY for a method to avoid deletions.
+.TP
+.BR "\-\-unmerge " (\fB\-C\fR)
+\fBWARNING: This action can remove important packages!\fR Removes
+all matching packages. This does no checking of dependencies, so
+it may remove packages necessary for the proper operation of your
+system. Its arguments can be \fIebuilds\fR, \fIclasses\fR, or
+\fIdependencies\fR \-\- see \fB\-\-clean\fR above for examples.
+.SH "OPTIONS"
+.TP
+.BR "\-\-ask " (\fB\-a\fR)
+Before performing the merge, display what ebuilds and tbz2s will be
+installed, in the same format as when using \fB\-\-pretend\fR; then ask
+whether to continue with the merge or abort. Using \fB\-\-ask\fR is more
+efficient than using \fB\-\-pretend\fR and then executing the same command
+without \fB\-\-pretend\fR, as dependencies will only need to be calculated
+once.
+.TP
+.BR "\-\-buildpkg " (\fB\-b\fR)
+Tells emerge to build binary packages for all ebuilds processed in
+addition to actually merging the packages. Useful for maintainers
+or if you administrate multiple Gentoo Linux systems (build once,
+emerge tbz2s everywhere). The package will be created in the
+\fI${PKGDIR}/All\fR directory. An alternative for already\-merged
+packages is to use \fBquickpkg\fR which creates a tbz2 from the
+live filesystem.
+.TP
+.BR "\-\-buildpkgonly " (\fB\-B\fR)
+Creates binary packages for all ebuilds processed without actually
+merging the packages. This comes with the caveat that all build-time
+dependencies must already be emerged on the system.
+.TP
+.BR "\-\-changelog " (\fB\-l\fR)
+Use this in conjunction with the \fB\-\-pretend\fR action. This will
+show the ChangeLog entries for all the packages that will be upgraded.
+.TP
+.BR "\-\-columns"
+Used alongside \fB\-\-pretend\fR to cause the package name, new version,
+and old version to be displayed in an aligned format for easy cut\-n\-paste.
+.TP
+.BR "\-\-debug " (\fB\-d\fR)
+Tells emerge to run the emerge command in \fB\-\-debug\fR mode. In this
+mode the bash build environment will run with the \-x option,
+causing it to output verbose debugging information to stdout.
+\fB\-\-debug\fR is great for finding bash syntax errors.
+.TP
+.BR "\-\-deep " (\fB\-D\fR)
+When used in conjunction with \fB\-\-update\fR, this flag forces
+\fBemerge\fR to consider the entire dependency tree of packages,
+instead of checking only the immediate dependencies of the packages.
+As an example, this catches updates in libraries that are not directly
+listed in the dependencies of a package.
+.TP
+.BR "\-\-emptytree " (\fB\-e\fR)
+Virtually tweaks the tree of installed packages to contain nothing. This is
+great to use together with \fI\-\-pretend\fR. This makes it possible for
+developers to get a complete overview of the entire dependency tree of a
+certain package.
+.TP
+.BR "\-\-fetchonly " (\fB\-f\fR)
+Instead of doing any package building, just perform fetches for all
+packages (the main package as well as all dependencies).
+.TP
+.BR "\-\-fetch\-all\-uri " (\fB\-F\fR)
+Instead of doing any package building, just perform fetches for all
+packages (the main package as well as all dependencies), grabbing all potential
+files.
+.TP
+.BR "\-\-getbinpkg " (\fB\-g\fR)
+Using the server and location defined in \fIPORTAGE_BINHOST\fR (see
+\fBmake.conf\fR(5)), portage will download the information from each binary
+package found and it will use that information to help build the dependency
+list. This option implies \fB\-k\fR. (Use \fB\-gK\fR for binary\-only merging.)
+.TP
+.BR "\-\-getbinpkgonly " (\fB\-G\fR)
+This option is identical to \fB\-g\fR, as above, except it will not use ANY
+information from the local machine. All binaries will be downloaded from the
+remote server without consulting packages existing in the local packages
+directory.
+.TP
+.BR "\-\-help " (\fB\-h\fR)
+Displays help information for emerge. Adding one of the additional
+arguments listed above will give you more specific help information
+on that subject. The internal \fBemerge\fR help documentation is
+updated more frequently than this man page; check it out if you
+are having problems that this man page does not help resolve.
+.TP
+.BR "\-\-newuse " (\fB\-N\fR)
+Tells emerge to include installed packages where USE flags have changed since
+compilation. An asterisk marks when a USE flag has changed since the package
+was compiled.
+.TP
+.BR "\-\-noconfmem"
+Causes portage to disregard merge records indicating that a config file
+inside of a \fBCONFIG_PROTECT\fR directory has been merged already. Portage
+will normally merge those files only once to prevent the user from
+dealing with the same config multiple times. This flag will cause the
+file to always be merged.
+.TP
+.BR "\-\-nodeps " (\fB\-O\fR)
+Merges specified packages without merging any dependencies. Note that
+the build may fail if the dependencies aren't satisfied.
+.TP
+.BR "\-\-noreplace " (\fB\-n\fR)
+Skips the packages specified on the command\-line that have already
+been installed. Without this option, any packages, ebuilds, or deps
+you specify on the command\-line *will* cause Portage to remerge
+the package, even if it is already installed. Note that Portage will
+not remerge dependencies by default.
+.TP
+.BR "\-\-nospinner"
+Disables the spinner for the session. The spinner is active when the
+terminal device is determined to be a TTY. This flag disables it regardless.
+.TP
+.BR "\-\-oneshot " (\fB\-1\fR)
+Emerge as normal, but do not add the packages to the world profile
+for later updating.
+.TP
+.BR "\-\-onlydeps " (\fB\-o\fR)
+Only merge (or pretend to merge) the dependencies of the packages
+specified, not the packages themselves.
+.TP
+.BR "\-\-pretend " (\fB\-p\fR)
+Instead of actually performing the merge, simply display what *would*
+have been installed if \fB\-\-pretend\fR weren't used. Using \fB\-\-pretend\fR
+is strongly recommended before installing an unfamiliar package. In
+the printout,
+.br
+
+.br
+\fIN\fR = new, (not yet installed)
+.br
+\fIS\fR = new, slot installation (side-by-side versions)
+.br
+\fIU\fR = updating, (changing versions)
+.br
+\fID\fR = downgrade, (Best version seems lower)
+.br
+\fIR\fR = replacing, (Remerging same version))
+.br
+\fIF\fR = fetch restricted, (Manual download)
+.br
+\fIf\fR = fetch restricted, (Already downloaded)
+.br
+\fIB\fR = blocked by an already installed package
+.TP
+.BR "\-\-quiet " (\fB\-q\fR)
+Results may vary, but the general outcome is a reduced or condensed
+output from portage's displays.
+.TP
+.BR "\-\-resume"
+Resumes the last merge operation. Please note that this operation
+will only return an error on failure. If there is nothing for portage
+to do, then portage will exit with a message and a success condition.
+.TP
+.BR "\-\-searchdesc " (\fB\-S\fR)
+Matches the search string against the description field as well as
+the package name. \fBTake caution\fR as the descriptions are also
+matched as regular expressions.
+.TP
+.BR "\-\-skipfirst"
+This action is only valid when used with \fB\-\-resume\fR. It removes the
+first package in the resume list so that a merge may continue in the presence
+of an uncorrectable or inconsequential error. This should only be used in
+cases where skipping the package will not result in failed dependencies.
+.TP
+.BR "\-\-tree " (\fB\-t\fR)
+Shows the dependency tree for the given target by indenting dependencies.
+This is only really useful in combination with \fB\-\-emptytree\fR or
+\fB\-\-update\fR and \fB\-\-deep\fR.
+.TP
+.BR "\-\-update " (\fB\-u\fR)
+Updates packages to the best version available, which may not always be the
+highest version number due to masking for testing and development. This will
+also update direct dependencies which may not be what you want. In general,
+use this option only in combination with the world or system target.
+.TP
+.BR "\-\-upgradeonly " (\fB\-U\fR)
+Updates packages, but excludes updates that would result in a lower version
+of the package being installed. \fBSLOT\fRs are considered at a basic level.
+.br
+This option is deprecated and should not be used anymore. Please use the
+/etc/portage/package.* files from now on.
+.TP
+.BR "\-\-usepkg " (\fB\-k\fR)
+Tells emerge to use binary packages (from $PKGDIR) if they are available, thus possibly avoiding some
+time\-consuming compiles. This option is useful for CD installs; you can export PKGDIR=/mnt/cdrom/packages
+and then use this option to have emerge "pull" binary packages from the CD in order to satisfy dependencies.
+.TP
+.BR "\-\-usepkgonly " (\fB\-K\fR)
+Tells emerge to only use binary packages (from $PKGDIR). All the binary
+packages must be available at the time of dependency calculation or emerge
+will simply abort. Portage does not use $PORTDIR when calculating dependency
+information so all masking information is ignored.
+.TP
+.BR "\-\-verbose " (\fB\-v\fR)
+Tell emerge to run in verbose mode. Currently this flag causes emerge to print out GNU info errors, if any, and to show the USE flags that will be used for each package when pretending.
+.TP
+.BR "\-\-version " (\fB\-V\fR)
+Displays the version number of \fBemerge\fR. It cannot be used in
+conjunction with other options.
+.SH "OUTPUT"
+When utilizing \fBemerge\fR with the \fB\-\-pretend\fR and \fB\-\-verbose\fR
+flags, the output may be a little hard to understand at first. This section
+explains the abbreviations.
+.TP
+.B [blocks B ] app\-text/dos2unix (from pkg app\-text/hd2u\-0.8.0)
+Dos2unix is Blocking hd2u from being emerged. Blockers are defined when
+two packages will clobber each others files, or otherwise cause some form
+of breakage in your system. However, blockers usually do not need to be
+simultaneously emerged because they usually provide the same functionality.
+.TP
+.B [ebuild N ] app\-games/qstat\-25c
+Qstat is New to your system, and will be emerged for the first time.
+.TP
+.B [ebuild NS ] dev-libs/glib-2.4.7
+You already have a version of glib installed, but a 'new' version in
+a different SLOT is available.
+.TP
+.B [ebuild R ] sys\-apps/sed\-4.0.5
+Sed 4.0.5 has already been emerged, but if you run the command, then
+portage will Re\-emerge the specified package (sed in this case).
+.TP
+.B [ebuild F ] media\-video/realplayer\-8\-r6
+The realplayer package requires that you Fetch the sources manually.
+When you attempt to emerge the package, if the sources are not found,
+then portage will halt and you will be provided with instructions on how
+to download the required files.
+.TP
+.B [ebuild f ] media\-video/realplayer\-8\-r6
+The realplayer package's files are already downloaded.
+.TP
+.B [ebuild U ] net\-fs/samba\-2.2.8_pre1 [2.2.7a]
+Samba 2.2.7a has already been emerged and can be Updated to version
+2.2.8_pre1.
+.TP
+.B [ebuild UD] media\-libs/libgd\-1.8.4 [2.0.11]
+Libgd 2.0.11 is already emerged, but if you run the command, then
+portage will Downgrade to version 1.8.4 for you.
+.br
+This may occur if a newer version of a package has been masked because it is
+broken or it creates a security risk on your system and a fix has not been
+released yet.
+.br
+Another reason this may occur is if a package you are trying to emerge requires
+an older version of a package in order to emerge successfully. In this case,
+libgd 2.x is incompatible with libgd 1.x. This means that packages that were
+created with libgd 1.x will not compile with 2.x and must downgrade libgd first
+before they can emerge.
+.TP
+.B [ebuild U\-] x11\-base/xfree\-4.3.0 [4.2.99.902]
+The \- represents lack of \fBSLOT\fR information about Xfree. This will occur
+when the previous version emerged was injected (see \fBinject\fR for more info)
+or very outdated (so old that \fBSLOT\fR did not exist). Either way, a newer version
+of Xfree is availabe for your updating delight.
+.TP
+.B [ebuild U ] sys\-devel/distcc\-2.16 [2.13\-r1] \-gtk +ipv6* (\-selinux)
+The \-gtk reflects the status of \fBUSE\fR variables when emerging distcc.
+Here we see that distcc can use the \fBUSE\fR variable gtk, but that your
+current settings have gtk disabled. This means optional support for gtk will
+not be enabled in distcc when you emerge it. An asterisk shows that the
+\fBUSE\fR flags have changed since the package was last installed. In this
+case, ipv6 is enabled but was previously disabled. A \fBUSE\fR flag in
+pparenthesis, like (\-selinux), is always disabled and shows that the flag is
+not available for the current system profile.
+.br
+\fB*Note:\fR The \fBUSE\fR status is only displayed when you use the
+\fB\-\-pretend\fR and \fB\-\-verbose\fR options.
+.SH "NOTES"
+You should almost always precede any package install or update attempt with a
+\fB\-\-pretend\fR install or update. This lets you see how much will be
+done, and shows you any blocking packages that you will have to rectify.
+This goes doubly so for the \fBsystem\fR and \fBworld\fR classes, which can
+update a large number of packages if the portage tree has been particularly
+active.
+.LP
+You also want to typically use \fB\-\-update\fR, which ignores packages that
+are already fully updated but upgrades those that are not.
+.LP
+When you install a package with uninstalled dependencies and do
+not explicitly state those dependencies in the list of parameters,
+they will not be added to the world file. If you want them to be
+detected for world updates, make sure to explicitly list them as
+parameters to \fBemerge\fR.
+.LP
+\fBUSE variables\fR may be specified on the command line to
+override those specified in the default locations, letting you
+avoid using some dependencies you may not want to have. \fBUSE
+flags specified on the command line are NOT remembered\fR. For
+example, \fBUSE="\-X \-gnome" emerge mc\fR will emerge mc with
+those USE settings. If you want those USE settings to be more
+permanent, you can put them in /etc/portage/package.use instead.
+.LP
+If \fBemerge \-\-update system\fR or \fBemerge \-\-update world\fR
+fails with an error message, it may be that an ebuild uses some
+newer feature not present in this version of \fBemerge\fR. You
+can use \fBemerge \-\-update portage\fR to upgrade to the lastest
+version, which should support any necessary new features.
+.SH "MASKED PACKAGES"
+\fINOTE: Please use caution when using development packages. Problems
+and bugs resulting from misusing masked packages drains Gentoo
+developer time. Please be sure you are capable of handling any problems
+that may ensue.\fR
+.LP
+Masks in \fBportage\fR provide three primary functions: they allow a
+testing period where the packages can be used in live machines; they
+prevent the use of a package when it will fail; and they mask existing
+packages that are broken or could pose a security risk. Masking can be
+done by two methods: \fBpackage.mask\fR and \fBKEYWORDS\fR. Read below
+to find out how to unmask in either case. Also note that if you give
+\fBemerge\fR an ebuild, then all forms of masking will be ignored and
+\fBemerge\fR will attempt to emerge the package.
+.TP
+.BR package.mask
+The \fBpackage.mask\fR file primarily blocks the use of packages that cause
+problems or are known to have issues on different systems. It resides in
+\fI/usr/portage/profiles\fR.
+.TP
+.BR KEYWORDS
+The \fBKEYWORDS\fR variable in an \fBebuild\fR file is also used for masking
+a package still in testing. There are architecture\-specific keywords for
+each package that let \fBportage\fR know which systems are compatible with
+the package. Packages which compile on an architecture, but have not been
+proven to be "stable", are masked with a tilde (\fB~\fR) in front of the
+architecture name. \fBemerge\fR examines the \fBACCEPT_KEYWORDS\fR environment
+variable to allow or disallow the emerging of a package masked by \fBKEYWORDS\fR.
+To inform \fBemerge\fR that it should build these 'testing' versions
+of packages, you should update your \fI/etc/portage/package.keywords\fR file
+to list the packages you want the 'testing' version. See \fBportage\fR(5) for
+more information.
+.SH "REPORTING BUGS"
+Please report any bugs you encounter through our website:
+.LP
+\fBhttp://bugs.gentoo.org/\fR
+.LP
+Please include the output of \fBemerge \-\-info\fR when you submit your
+bug report.
+.SH "SEE ALSO"
+.BR "emerge \-\-help",
+.BR ebuild (1),
+.BR ebuild (5),
+.BR make.conf (5),
+.BR portage (5)
+.LP
+A number of helper applications reside in \fI/usr/lib/portage/bin\fR.
+.LP
+The \fBapp\-portage/gentoolkit\fR package contains useful scripts such as
+\fBequery\fR (a package query tool).
+.SH "FILES"
+.TP
+\fB/var/lib/portage/world\fR
+Contains a list of all user\-specified packages. You can safely edit
+this file, adding packages that you want to be considered in \fBworld\fR
+class updates and removing those that you do not want to be considered.
+.TP
+\fB/etc/make.conf\fR
+Contains variables for the build process, overriding those in
+\fBmake.globals\fR. \fBYou should edit this file instead of the ones
+listed below\fR.
+.TP
+.B /etc/dispatch\-conf.conf
+Contains settings to handle automatic updates/backups of configuration
+files.
+.TP
+\fB/etc/make.profile/make.defaults\fR
+Contains profile\-specific variables for the build process. \fBDo not
+edit this file\fR.
+.TP
+\fB/etc/make.profile/use.defaults\fR
+Contains a list of packages which, if installed, cause the respective USE
+flag to be enabled by default. \fBDo not edit this file\fR.
+.TP
+\fB/usr/portage/profiles/use.desc\fR
+Contains the master list of USE flags with descriptions of their
+functions. \fBDo not edit this file\fR.
+.TP
+\fB/etc/make.profile/virtuals\fR
+Contains a list of default packages used to resolve virtual dependencies.
+\fBDo not edit this file\fR.
+.TP
+\fB/etc/make.profile/packages\fR
+Contains a list of packages used for the base system. The \fBsystem\fR
+and \fBworld\fR classes consult this file. \fBDo not edit this file\fR.
+.TP
+\fB/etc/make.globals\fR
+Contains the default variables for the build process. \fBDo not edit
+this file\fR.
+.SH "AUTHORS"
+Daniel Robbins <drobbins@gentoo.org>
+.br
+Geert Bevin <gbevin@gentoo.org>
+.br
+Achim Gottinger <achim@gentoo.org>
+.br
+Nicholas Jones <carpaski@gentoo.org>
+.br
+Phil Bordelon <phil@thenexusproject.org>
+.br
+Mike Frysinger <vapier@gentoo.org>
+.br
+Marius Mauch <genone@gentoo.org>
+.br
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/emerge.1,v 1.70.2.15 2005/08/20 03:56:50 vapier Exp $
diff --git a/man/env-update.1 b/man/env-update.1
new file mode 100644
index 00000000..9588f84c
--- /dev/null
+++ b/man/env-update.1
@@ -0,0 +1,28 @@
+.TH "ENV-UPDATE" "1" "Feb 2003" "Portage 2.0.51" "Portage"
+.SH NAME
+env-update \- updates environment settings automatically
+.SH SYNOPSIS
+.B env-update
+.SH DESCRIPTION
+.B env-update
+reads the files in \fI/etc/env.d\fR and automatically generates
+\fI/etc/profile.env\fR and \fI/etc/ld.so.conf\fR. Then \fBldconfig\fR(8)
+is run to update \fI/etc/ld.so.cache\fR. \fBenv-update\fR is run by
+\fBemerge\fR(1) automatically after each package merge. Also, if you
+make changes to \fI/etc/env.d\fR, you should run \fIenv-update\fR
+yourself for changes to take effect immediately. Note that this would
+only affect new processes. In order for the changes to affect your
+active shell, you will probably have to run \fIsource /etc/profile\fR
+first.
+.SH OPTIONS
+.TP
+None.
+.SH AUTHORS
+Daniel Robbins <drobbins@gentoo.org>
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR ldconfig (8)
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/env-update.1,v 1.6 2004/09/17 00:17:10 vapier Exp $
diff --git a/man/etc-update.1 b/man/etc-update.1
new file mode 100644
index 00000000..f2bb827c
--- /dev/null
+++ b/man/etc-update.1
@@ -0,0 +1,40 @@
+.TH "ETC-UPDATE" "1" "Feb 2003" "Portage 2.0.51" "Portage"
+.SH NAME
+etc-update \- handle configuration file updates
+.SH SYNOPSIS
+.B etc-update
+.SH DESCRIPTION
+.I etc-update
+is supposed to be run after merging a new package to see if
+there are updates to the configuration files. If a new
+configuration file will override an old one,
+.I etc-update
+will prompt the user for a decision.
+.PP
+.I etc-update
+will check all directories in the \fICONFIG_PROTECT\fR variable. All
+config files found in \fICONFIG_PROTECT_MASK\fR will automatically be
+updated for you by \fIetc-update\fR. See \fBmake.conf\fR(5) for more
+information.
+.SH OPTIONS
+.TP
+None.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR make.conf (5)
+.SH "FILES"
+.TP
+.B /etc/etc-update.conf
+Configuration settings for \fIetc-update\fR are stored here.
+.TP
+.B /etc/dispatch-conf.conf
+Settings for dispatching configuration files right before they're merged.
+.SH AUTHORS
+Jochem Kossen and Leo Lipelis
+.br
+Karl Trygve Kalleberg <karltk@gentoo.org>
+.br
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/etc-update.1,v 1.9 2004/09/17 00:17:10 vapier Exp $
diff --git a/man/eutils.eclass.5 b/man/eutils.eclass.5
new file mode 100644
index 00000000..a1a7d63f
--- /dev/null
+++ b/man/eutils.eclass.5
@@ -0,0 +1,176 @@
+.TH "EUTILS.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+eutils.eclass \- many extra (but common) functions that are used in ebuilds
+.SH "DESCRIPTION"
+The \fBeutils\fR eclass contains a suite of functions that complement
+the ones that ebuild.sh already contain. The idea is that the functions
+are not required in all ebuilds but enough utilize them to have a common
+home.
+.SH "FUNCTIONS"
+.TP
+.BR "cdrom_get_cds " "\fI<cd1 file>\fR \fI[cd2 file]\fR \fI[cd n file]\fR"
+Useful function to help ebuilds that need to read files off of a CD. This is
+most commonly used with games. Just specify a list of files, one per cd, that
+will be used to detect whether the cd is mounted or not. This function
+handles all the messy details of interaction with the user. Once this
+function returns, you will have access to the \fICDROM_ROOT\fR variable. If
+you want the message to the user to name the CD in a particular way, then
+export the variable \fICDROM_NAME\fR before calling this function. If you want
+to name more than one cd, and you want them to each have a different name, then
+export the variables \fICDROM_NAME_1\fR, \fICDROM_NAME_2\fR, etc... For more
+information on multi-cd support, see \fBcdrom_load_next_cd\fR.
+.TP
+.BR "cdrom_load_next_cd"
+Some packages are so big they come on multiple CDs. When you're done reading
+files off a CD and want access to the next one, just call this function. Again,
+all the messy details of user interaction are taken care of for you. Once this
+returns, just read the variable \fICDROM_ROOT\fR for the location of the mounted
+CD. Note that you can only go forward in the CD list, so make sure you only
+call this function when you're done using the current CD.
+.TP
+.BR "draw_line"
+Simple function to draw a line consisting of '=' the same length as $*. So
+if you run `draw_line 1234 5678` you will get back 9 '=' characters in a line.
+.TP
+.BR "edos2unix " "\fI<files>\fR"
+A handy replacement for dos2unix, recode, fixdos, etc... This allows you
+to remove all of these text utilities from DEPEND variables because this
+is a script based solution. Just give it a list of files to convert and
+they will all be changed from the DOS CRLF format to the UNIX LF format.
+.TP
+.BR "enewgroup " "\fI<group>\fR \fI[gid]\fR"
+This function does not require you to understand how to properly add a
+group to the system. Just give it a \fIgroup name\fR to add and \fBenewgroup\fR will
+do the rest. You may specify the \fIgid\fR for the group or allow the group to
+allocate the next available one.
+.TP
+.BR "enewuser " "\fI<user>\fR \fI[uid]\fR \fI[shell]\fR \fI[homedir]\fR \fI[groups]\fR \fI[params]\fR"
+Same as \fBenewgroup\fR, you are not required to understand how to properly add
+a user to the system. The only required parameter is the \fIusername\fR.
+.br
+.BR "Default Values"
+.br
+\fIuid\fR: next available (pass -1 to get default behavior)
+.br
+\fIshell\fR: /bin/false
+.br
+\fIhomedir\fR: /dev/null
+.br
+\fIgroups\fR: no groups
+.br
+\fIparams\fR: any other parameters \fBuseradd\fR(8) accepts; see the manpage for more details
+.TP
+.BR "epatch"
+See the section on \fBepatch\fR below.
+.TP
+.BR "gen_usr_ldscript"
+Generate linker scripts in /usr/lib for dynamic libs in /lib. This is to fix linking
+problems when you have the .so in /lib, and the .a in /usr/lib. What happens is that
+in some cases when linking dynamic, the .a in /usr/lib is used instead of the .so in
+/lib due to gcc/libtool tweaking ld's library search path.
+.TP
+.BR "get_number_of_jobs"
+Checks how many cpu's are present in the system and then sets -j in MAKEOPTS accordingly.
+.TP
+.BR "have_NPTL"
+This function return true if we are using the NPTL pthreads implementation of glibc.
+.TP
+.BR "make_desktop_entry " "\fI<binary>\fR \fI[name]\fR \fI[icon]\fR \fI[type]\fR \fI[path]\fR"
+Make a little shortcut in GNOME/KDE menus for your application. Just pass the name
+of the binary to execute and the rest will be done for you. If you want to change
+the name that will show up in the menu, pass the function a \fIname\fR parameter. If you
+want to specify an \fIicon\fR (default is \fB${PN}\fR.png) then pass a name of a graphic file
+relative to /usr/share/pixmaps/ or the full path to a file. If you want to specify the
+section of the menu that the icon will install to (rather than the default determined
+by \fB${CATEGORY}\fR) then pass a \fItype\fR value (see http://www.freedesktop.org/standards/menu-spec/
+for valid values). Finally, if the application needs to start up in a special directory,
+pass the last value as the full \fIpath\fR name.
+.TP
+.BR "unpack_makeself " "\fI[makeself archive]\fR \fI[byte offset]\fR"
+Unpack a makeself archive rather than relying on the script to unpack itself. Useful for when
+the scripts use old (POSIX) syntax that is no longer supported properly. If you don't specify
+a file to unpack, then \fB${A}\fR is used instead. If you don't specify the offset, then the
+proper value will be located by searching the makeself script.
+For more information on makeself archives, please visit: http://www.megastep.org/makeself/
+.TP
+.BR "unpack_pdv " "\fI<pdv archive>\fR \fI<sizeof(off_t)>\fR"
+Unpack a pdv archive rather than relying on the binary to unpack itself. Useful for when
+the static binary crashes randomly on systems and for when the binary doesn't provide a
+non-interactive extraction process. You have to specify the off_t size since I (vapier@gentoo.org)
+am unaware of a way to extract that information out of the binary executable automatically.
+The value you pass is the size of the off_t type (in bytes) on the machine that built the
+pdv archive. If you don't know the value yourself, try guessing the values 2, 4, or 8.
+For more information on pdv archives, please visit: http://pdv.sourceforge.net/
+.SH "EPATCH"
+.TP
+.B "ABOUT"
+\fBepatch\fR is designed to make patching easy. It does all the common checks that
+a developer would do with the \fBpatch\fR(1) command and then some. It will attempt
+to apply the patch for a range of offset values (-p0 to -p5, all relative to the working
+directory when \fBepatch\fR was called). If the patch fails to apply (by testing via
+dryruns), then \fBpatch\fR will stop the emerge process by calling \fBdie\fR. You will
+be given a log file of the output of the patch attempt so as to ease debugging. The
+output of a successful patch is a pretty formatted message showing what patches were
+applied. \fBepatch\fR can be used for bulk patching or for just one or two patches.
+Additionally, it can handle patches in bzip2, gzip, compress (Z), and zip formats.
+.TP
+.B "USAGE"
+.RS
+.TP
+.B "epatch " "\fI<patch file>\fR"
+The most common and easiest way to use \fBepatch\fR is by just giving it the full path
+to a patch file.
+.TP
+.B "epatch " "\fI<directory>\fR"
+A more powerful use is to fill a directory with patches and then let \fBepatch\fR apply
+all the patches inside it. The patches must be in the format ??_${\fBARCH\fR}_foo.${\fBEPATCH_SUFFIX\fR}.
+This ensures that there are a set order, and you can have \fBARCH\fR specific patches.
+
+.br
+01_all_misc-fix.patch.bz2
+.br
+ apply the misc-fix patch first for all arches
+.br
+02_sparc_another-fix.patch.bz2
+.br
+ apply the another-fix patch second but only on sparc
+.RE
+.TP
+.B VARIABLES
+.RS
+.TP
+.B "EPATCH_SOURCE" = \fI"${WORKDIR}/patch"\fR
+The patch or directory of patches for \fBepatch\fR to apply. This is set
+automatically if you call \fBepatch\fR with a parameter.
+.TP
+.B "EPATCH_SUFFIX" = \fI"patch.bz2"\fR
+When applying bulk patches this is the suffix that all patches will have.
+.TP
+.B "EPATCH_OPTS" = \fI""\fR
+Any extra options you may want to pass to \fBpatch\fR(1). We can't think
+of everything so why restrict you :). The default is "" of course.
+.TP
+.B "EPATCH_EXCLUDE" = \fI""\fR
+A space delimited list (well, actually \fB$IFS\fR delimited ...) of patch
+files to skip while bulk patching. Use only file names, not full paths.
+.TP
+.B "EPATCH_SINGLE_MSG" = \fI"Applying <patch name>"\fR
+If you only apply a single patch, then instead of displaying the default
+message you can change it to say anything you want, even 'Dont call me Radio Unit 51',
+if you are so inclined of course.
+.TP
+.B "EPATCH_FORCE" = \fI"[yes|no]"\fR
+This allows you to apply all patches in \fBEPATCH_SOURCE\fR even if they
+dont match the ??_${\fBARCH\fR}_foo.${\fBEPATCH_SUFFIX\fR} file naming
+convention. By default we want you to use the above convention.
+.RE
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/eutils.eclass
+.SH "AUTHORS"
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/eutils.eclass.5,v 1.5.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/fixheadtails.eclass.5 b/man/fixheadtails.eclass.5
new file mode 100644
index 00000000..4ddd5940
--- /dev/null
+++ b/man/fixheadtails.eclass.5
@@ -0,0 +1,32 @@
+.TH "FIXHEADTAILS.ECLASS" "5" "Aug 2004" "Portage 2.0.51" "portage"
+.SH "NAME"
+fixheadtails.eclass \- functions for replacing obsolete head/tail invocations
+with newer POSIX compliant ones.
+.SH "DESCRIPTION"
+The \fBfixheadtails\fR eclass contains functions for parsing file(s) and
+replacing obsolete head/tail invocations in the form similar to:
+.TP
+head -# <file>
+.TP
+with the newer POSIX compliant form of:
+.TP
+head -n# <file>
+.SH "FUNCTIONS"
+\fBNOTE\fR: these functions are usually used in the \fIsrc_unpack\fR function.
+.TP
+.BR "ht_fix_file " "\fI<file1> [file2] [file3] [...]\fR"
+Fixes head/tail invocations in specific files.
+.TP
+.BR "ht_fix_all"
+Scans the current directory (recursively), calling \fBht_fix_file\fR for each
+file that contains an obsolete head/tail invocation.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/fixheadtails.eclass
+.SH "AUTHORS"
+Aaron Walker <ka0ttic@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/fixheadtails.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/flag-o-matic.eclass.5 b/man/flag-o-matic.eclass.5
new file mode 100644
index 00000000..967ee9c9
--- /dev/null
+++ b/man/flag-o-matic.eclass.5
@@ -0,0 +1,84 @@
+.TH "FLAG-O-MATIC.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+flag\-o\-matic.eclass \- manipulate CFLAGS/CXXFLAGS easily and reliably
+.SH "DESCRIPTION"
+The \fBflag\-o\-matic\fR eclass contains a suite of functions to
+manipulate the CFLAGS/CXXFLAGS variables.
+.SH "FUNCTIONS"
+.TP
+.BR "append-flags " "\fI<flags>\fR"
+Add extra \fIflags\fR to the current CFLAGS/CXXFLAGS.
+.TP
+.BR "filter-flags " "\fI<flags>\fR"
+Remove particular \fIflags\fR from CFLAGS/CXXFLAGS. This function
+will only match complete flags.
+.TP
+.BR "replace-flags " "\fI<orig-flag>\fR \fI<new-flag>\fR"
+Replace all occurences of \fIoriginal flag\fR with \fInew flag\fR.
+.TP
+.BR "replace-cpu-flags " "\fI<old cpus>\fR \fI<new cpu>\fR"
+Replace all -march, -mcpu, and -mtune flags which contain \fIold cpus\fR
+with -march, -mcpu, and -mtune flags which contain \fInew cpu\fR.
+.TP
+.BR "get-flag " "\fI<flag>\fR"
+If \fIflag\fR is prefixed with -, then the whole flag will
+be echoed. If just the flag name is specified, and the flag has
+a setting, the value for the flag will be echoed instead.
+
+.I Examples:
+.br
+CFLAGS="-march=i586 -ffast-math"
+.br
+`get-flag -march` == "-march=i586"
+.br
+`get-flag march` == "i586"
+.br
+`get-flag -ffast-math` == "-ffast-math"
+.br
+`get-flag ffast-math` == "-ffast-math"
+.TP
+.BR "is-flag " "\fI<flag>\fR"
+Returns true if \fIflag\fR is in CFLAGS or CXXFLAGS.
+.TP
+.BR "filter-mfpmath " "\fI<math types>\fR"
+Remove specified \fImath types\fR from the selected fpmath units.
+If the user has -mfpmath=sse,386, running `filter-mfpmath sse`
+will leave the user with -mfpmath=386.
+.TP
+.BR "append-ldflags " "\fI<flags>\fR"
+Add extra \fIflags\fR to the current LDFLAGS.
+.TP
+.BR "filter-ldflags " "\fI<flags>\fR"
+Remove particular \fIflags\fR from LDFLAGS. This function
+will only match complete flags.
+.TP
+.BR "filter-lfs-flags"
+Remove flags that enable Large File Support.
+.TP
+.BR "append-lfs-flags"
+Add flags that enable Large File Support.
+.TP
+.BR "strip-flags"
+Strip CFLAGS/CXXFLAGS of everything except for flags known to
+be good flags, or are flags that affect the ABI. Users of stable
+profile are limited to these flags:
+.br
+.I "-O -O1 -O2 -mcpu -march -mtune -fstack-protector -pipe -g"
+.br
+Users of unstable profile are allowed the above flags and these flags:
+.br
+.I "-Os -O3 -freorder-blocks -fprefetch-loop-arrays"
+.TP
+.BR "test_flag " "\fI<flag>\fR"
+Tests to see if \fIflag\fR is supported by the active toolchain.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5),
+.BR make.conf (5)
+.SH "FILES"
+.BR /usr/portage/eclass/flag\-o\-matic.eclass
+.SH "AUTHORS"
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/flag-o-matic.eclass.5,v 1.5.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/font.eclass.5 b/man/font.eclass.5
new file mode 100644
index 00000000..87948476
--- /dev/null
+++ b/man/font.eclass.5
@@ -0,0 +1,64 @@
+.TH "FONT.ECLASS" "5" "Aug 2004" "Portage 2.0.51" "portage"
+.SH "NAME"
+font.eclass \- easy, uniform font installation
+.SH "DESCRIPTION"
+The \fBfont\fR eclass attempts to make font installation as easy as possible.
+Everything that usually involves installing fonts (such as creating scalable
+font indecis, updating the font cache, etc...) is transparently taken
+care of by the \fBfont\fR eclass.
+.SH "EXAMPLES"
+Here's a simple example ebuild:
+.nf
+inherit font
+
+DESCRIPTION="a collection of fonts for Nepali users"
+HOMEPAGE="http://www.mpp.org.np/"
+SRC_URI="mirror://gentoo/${P}.tar.bz2"
+
+LICENSE="freedist"
+SLOT="0"
+KEYWORDS="alpha amd64 ppc x86"
+IUSE=""
+
+DEPEND=""
+
+S="${WORKDIR}/${PN}"
+FONT_S=${S}
+FONT_SUFFIX="ttf"
+.fi
+.SH "VARIABLES"
+.TP
+.B "FONT_SUFFIX"
+Space-delimited list of font suffixes to install.
+.TP
+.B "FONT_S"
+Directory containing the fonts. If omitted, \fB${S}\fR will be used.
+.TP
+.B "DOCS"
+Space-delimited list of documents to install.
+.SH "FUNCTIONS"
+.TP
+.B "font_xfont_config"
+Creates font indecis for X font files and also installs a fonts.alias file,
+if it exists. This function is called by \fIfont_src_install\fR.
+.TP
+.B "font_xft_config"
+Creates fontconfig cache. This function is also called by \fIfont_src_install\fR.
+.TP
+.B "font_src_install"
+Installs all fonts ending with suffixes listed in \fB${FONT_SUFFIX}\fR as well
+as any documents listed in \fB${DOCS}\fR. This function will be used as the
+default \fIsrc_install\fR function in an ebuild that omits one.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/font.eclass
+.SH "AUTHORS"
+.nf
+Aaron Walker <ka0ttic@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+.fi
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/font.eclass.5,v 1.2.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/fortran.eclass.5 b/man/fortran.eclass.5
new file mode 100644
index 00000000..c0dc5390
--- /dev/null
+++ b/man/fortran.eclass.5
@@ -0,0 +1,53 @@
+.TH FORTRAN.ECLASS 5 "Nov 2004" "Portage 2.0.51" "portage"
+.SH NAME
+fortran.eclass \- functions for fortran packages
+.SH DESCRIPTION
+The \fBfortran\fR eclass provides an interface to ease the integration of the
+various fortran compilers available.
+.SH VARIABLES
+\fBNOTE\fR: since the \fBfortran\fR eclass does not check to see if the
+following variables are set prior to inheritance, you must ensure that if you
+need to define any of them, that you do so after inheritance occurs.
+.TP
+.B FORTRAN
+Defines a list of fortran compilers that can be used for the build. Defaults
+to 'f77'.
+.TP
+.B f77_CONF
+Defines configure option that enables the use of the f77 compiler. Defaults
+to '--with-f77'.
+.TP
+.B f2c_CONF
+Defines configure option that enables the use of the f2c compiler. Defaults
+to '--with-f2c'.
+.SH FUNCTIONS
+.TP
+.B fortran_conf
+Displays the necessary configure options for the currently selected fortran
+compiler.
+.TP
+.B need_fortran \fI[ profile1 ] < profile2 >\fR
+Checks to see if at least one of the specified profiles is installed. Currently
+supported profiles include \fBf77\fR, \fBf2c\fR, and \fBifc\fR.
+.TP
+.B patch_fortran
+Applies any patches located in \fB${FILESDIR}\fR named "\fB${P}\fR-COMPILER*",
+where COMPILER is the fortran compiler currently selected for use.
+.TP
+.B fortran_pkg_setup
+Default pkg_setup which calls \fBneed_fortran\fR to ensure that a suitable
+fortran compiler is installed.
+.TP
+.B fortran_src_unpack
+Default src_unpack which besides unpacking the distfile(s), calls
+\fBpatch_fortran\fR to apply any compiler-specific patches.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/fortran.eclass
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/fortran.eclass.5,v 1.1.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/games.eclass.5 b/man/games.eclass.5
new file mode 100644
index 00000000..7335fce1
--- /dev/null
+++ b/man/games.eclass.5
@@ -0,0 +1,119 @@
+.TH "GAMES.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+games.eclass \- standardize the install of all games
+.SH "DESCRIPTION"
+The \fBgames\fR eclass is used to centrally control how all games
+will be emerged onto systems. Here we basically control the filesystem
+locations and the ownership of all files. If you want to change an
+aspect of how your games are installed, then just edit the \fBgames\fR
+eclass ! :)
+.SH "VARIABLES"
+.TP
+.B "GAMES_PREFIX" = \fI"/usr/games"\fR
+The prefix that the game will be installed under.
+.TP
+.B "GAMES_PREFIX_OPT" = \fI"/opt"\fR
+The prefix that the game will be installed under if it is a binary distribution.
+.TP
+.B "GAMES_DATADIR" = \fI"/usr/share/games"\fR
+The prefix for installing shared data files.
+.TP
+.B "GAMES_DATADIR_BASE" = \fI"/usr/share"\fR
+Same as above, but some games auto append '/games/' to the datadir path.
+.TP
+.B "GAMES_SYSCONFDIR" = \fI"/etc/games"\fR
+The location where games will save their configuration files.
+.TP
+.B "GAMES_STATEDIR" = \fI"/var/games"\fR
+The location where games will save their state in behind runs. This
+includes things like highscore files. If a game creates more than
+one file, have it save all files inside \fB${GAMES_STATEDIR}/${PN}\fR.
+Otherwise, just create the single file in \fB${GAMES_STATEDIR}/\fR.
+Again, try to use a package specific name for the file if you are
+creating it directly in the statedir.
+.TP
+.B "GAMES_LIBDIR" = \fI"/usr/games/lib"\fR
+The location where games will store their libraries.
+.TP
+.B "GAMES_BINDIR" = \fI"/usr/games/bin"\fR
+The location where the games will store/link their executables. Putting
+game binaries here helps to cut down on the $PATH bloat.
+.TP
+.B "GAMES_ENVD" = \fI"90games"\fR
+The filename that the env.d entry will use.
+.TP
+.B "GAMES_USER" = \fI"games"\fR
+The user that will own all game related files.
+.TP
+.B "GAMES_GROUP" = \fI"games"\fR
+The group that will own all game related files.
+.SH "FUNCTIONS: general"
+.TP
+.B "prepgamesdirs" \fI[directories]\fR
+This will change ownership on all files/directories found inside of
+the \fBGAMES_*\fR variables and any extra directories specified as
+parameters. It will change the permissions on all directories to
+750 (u+rwx,g+rx-w,u-rwx) and change the permissions of all files
+with a mask of g+r,o-rwx.
+.br
+\fB*NOTE\fR: This should *always* be the last thing called in the
+\fBsrc_install\fR function. If portage allowed for hookable calls then
+this would be hooked to the end of \fBsrc_install\fR, but until that
+happens, make sure to call!
+.TP
+.B games_pkg_setup
+This will automagically add \fBGAMES_USER\fR and \fBGAMES_GROUP\fR to
+your system. If you define \fBpkg_setup\fR in your ebuild, then make
+sure to call this function at the end of the function.
+.TP
+.B games_pkg_postinst
+This will automagically generate the \fBGAMES_ENVD\fR file and display
+a little message about being in the \fBGAMES_GROUP\fR in order to play
+a game. If you define \fBpkg_postinst\fR in your ebuild, then make
+sure to call this function at the end of the function.
+.SH "FUNCTIONS: compile"
+.TP
+.B egamesconf
+The same as \fBeconf\fR except this passes all the game related variables
+(see above). For more info on \fBeconf\fR see \fBebuild\fR(5).
+.SH "FUNCTIONS: install"
+.TP
+.B egamesinstall
+The same as \fBeinstall\fR except this passes all the game related variables
+(see above). For more info on \fBeinstall\fR see \fBebuild\fR(5).
+.TP
+.B dogamesbin dogamessbin
+The same as \fBdobin\fR and \fBdosbin\fR respectively except these will
+install binaries into \fBGAMES_PREFIX\fR. For more info see \fBebuild\fR(5).
+.TP
+.B dogameslib dogameslib.a dogameslib.so
+The same as \fBdolib\fR, \fBdolib.a\fR, and \fBdolib.so\fR respectively
+except these will install binaries into \fBGAMES_PREFIX\fR. For more info
+see \fBebuild\fR(5).
+.TP
+.B newgamesbin newgamessbin
+The same as \fBnewbin\fR and \fBnewsbin\fR respectively except these will
+install binaries into \fBGAMES_PREFIX\fR. For more info see \fBebuild\fR(5).
+.TP
+.B gamesowners \fI<files/directories>\fR
+\fBgamesowners\fR will change the user and group ownership to \fBGAMES_USER\fR
+and \fBGAMES_GROUP\fR respectively.
+.TP
+.B gamesperms \fI<files/directories>\fR
+\fBgamesperms\fR will change the permissions with a mask of u+rw,g+r-w,o-rwx.
+.TP
+.B games_make_wrapper \fI<wrapper>\fR \fI<bin>\fR \fI<chdir>\fR
+Create a small wrapper script. Useful when dealing with packages that need to
+change directory to the base of their data tree before running. This will create
+a wrapper script called \fIwrapper\fR that will chdir to \fIchdir\fR before
+executing \fIbin\fR. The \fIwrapper\fR will be placed in \fBGAMES_BINDIR\fR.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/games.eclass
+.SH "AUTHORS"
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/games.eclass.5,v 1.7.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/horde.eclass.5 b/man/horde.eclass.5
new file mode 100644
index 00000000..7a620a07
--- /dev/null
+++ b/man/horde.eclass.5
@@ -0,0 +1,51 @@
+.TH "HORDE.ECLASS" "5" "Aug 2004" "Portage 2.0.51" "portage"
+.SH "NAME"
+horde.eclass \- standardize the installation of horde packages
+.SH "DESCRIPTION"
+The \fBhorde\fR eclass provides generic functions to make the writing of
+horde ebuilds trivial. The \fBhorde\fR eclass also provides transparent
+support for live CVS ebuilds via the \fBcvs.eclass\fR(5) (when \fB${PN}\fR
+contains "-cvs").
+.SH "VARIABLES"
+.BR "HORDE_PHP_FEATURES"
+A whitespace-delimited list of mod_php USE flags. If set,
+\fIhorde_pkg_setup\fR will check to make sure that mod_php was compiled with
+the specified USE flags. If not, the build will fail, notifying the user that
+they must rebuild mod_php with the specified USE flags.
+.SH "FUNCTIONS"
+.TP
+.BR "horde_pkg_setup"
+Handles the nasty details of the \fBwebapp.eclass\fR(5) and checks
+\fIHORDE_PHP_FEATURES\fR, if set.
+.TP
+.BR "horde_src_unpack"
+In the case of a live CVS ebuild, this function calls \fIcvs_src_unpack\fR
+from the \fBcvs\fR eclass. Otherwise, \fIunpack\fR is called.
+.TP
+.BR "horde_src_install"
+Installs all files in \fB${S}\fR into the \fBwebapp\fR eclass'
+\fB${MY_HTDOCSDIR}\fR directory. This will also installs documentation
+(the README and all files in in \fB${S}/docs/\fR). Then the rest of the
+nasty details of the \fBwebapp.eclass\fR(5) are taken care of.
+.TP
+.BR "horde_pkg_postinst"
+Displays various informational and/or warning messages.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5),
+.BR cvs.eclass (5),
+.BR webapp.eclass (5)
+.SH "FILES"
+.nf
+.BR /usr/portage/eclass/horde.eclass
+.BR /usr/portage/eclass/webapp.eclass
+.BR /usr/portage/eclass/cvs.eclass
+.fi
+.SH "AUTHORS"
+.nf
+Aaron Walker <ka0ttic@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+.fi
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/horde.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/libtool.eclass.5 b/man/libtool.eclass.5
new file mode 100644
index 00000000..5281d629
--- /dev/null
+++ b/man/libtool.eclass.5
@@ -0,0 +1,48 @@
+.TH "LIBTOOL.ECLASS" "5" "Aug 2004" "Portage 2.0.51" "portage"
+.SH "NAME"
+libtool.eclass \- fixes the libtool files that are distributed with some
+packages
+.SH "DESCRIPTION"
+The \fBlibtool\fR eclass provides an easy way to patch the libtool files
+that come with some packages. Often times these files are outdated and
+misbehave inside of the portage build environment.
+.SH "VARIABLES"
+.BR "ELT_APPLIED_PATCHES"
+This variable is exported by the \fBlibtool\fR eclass. It contains a
+whitespace-delimited list of patches that were successfully applied.
+.SH "FUNCTIONS"
+.TP
+.B "elibtoolize " "\fI[--portage] [--reverse-deps] [--patch-only] [--remove-internal-dep=DEP_TO_REMOVE] [--shallow]\fR"
+This function should be called from \fIsrc_unpack\fR. If called with no
+arguments, it will apply a default set of patches to all occurrences of
+ltmain.sh and then run libtoolize. The default set of patches are located
+in \fB${PORTDIR}\fR/eclass/ELT-patches.
+.RS
+.TP
+.BR "--portage"
+Apply the portage patch.
+.TP
+.BR "--reverse-deps"
+Apply the reverse dependencies patch. See http://bugzilla.gnome.org/show_bug.cgi?id=75635
+for more information.
+.TP
+.BR "--patch-only"
+If specified, libtoolize will not be run if none of the patches apply.
+.TP
+.BR "--remove-internal-deps=DEP_TO_REMOVE"
+Replaces @REM_INT_DEP@ with DEP_TO_REMOVE.
+.TP
+.BR "--shallow"
+Instead of recursively patching all occurrences of ltmain.sh, only patch the
+ltmain.sh in \fB${S}\fR.
+.RE
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/libtool.eclass
+.SH "AUTHORS"
+Aaron Walker <ka0ttic@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/libtool.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/make.conf.5 b/man/make.conf.5
new file mode 100644
index 00000000..07d1ac9c
--- /dev/null
+++ b/man/make.conf.5
@@ -0,0 +1,395 @@
+.TH "MAKE.CONF" "5" "Feb 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+make.conf \- custom settings for Portage
+.SH "SYNOPSIS"
+.B /etc/make.conf
+.SH "DESCRIPTION"
+This file contains various variables that are used by Portage.
+Portage will check the currently\-defined environment variables
+first for any settings. If no environment settings are found,
+Portage then checks /etc/make.conf. If no setting is found
+in /etc/make.conf, Portage checks /etc/make.globals. If no
+setting is found there, the profile's default setting is grabbed
+from /etc/make.profile/make.defaults. Please note that all user
+settings should be made in the environment or in /etc/make.conf,
+which is intended to be customized by the user.
+.br
+Exceptions are incremental variables such as USE, CONFIG_PROTECT*,
+and ACCEPT_KEYWORDS. Incremental variables are propagated down from
+make.defaults to make.globals to make.conf to the environment
+settings. Clearing these variables requires a clear\-all as in:
+export USE="\-*"
+.SH "VARIABLES"
+.TP
+\fBACCEPT_KEYWORDS\fR = \fI[space delimited list of KEYWORDS]\fR
+Enable testing of ebuilds that have not yet been deemed 'stable'. Users
+of the 'x86' architecture would set this to '~x86' while ppc users would
+set this to '~ppc'. This is an incremental variable. Only define a
+~arch.
+.br
+Defaults to the value of $ARCH.
+.TP
+\fBAUTOCLEAN\fR = \fI["yes" | "no"]\fR
+Automatically cleans the system by removing outdated packages which will not
+remove functionalities or prevent your system from working. On major ABI
+changes this may need to be set to off to ensure that the system can be
+rebuilt using the new libs before the old ones are removed. Downgrading with
+this option turned off may result in missing symlinks and an inoperable system.
+.br
+Defaults to yes.
+.TP
+\fBBUILD_PREFIX\fR = \fI[path]\fR
+Defines the location of the package working directory.
+.br
+Defaults to ${PORTAGE_TMPDIR}/portage
+.TP
+.B CBUILD
+This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
+as \fI\-\-build=${CBUILD}\fR only if it is defined.
+.TP
+\fBCCACHE_SIZE\fR = \fI"size"\fR
+This controls the space use limitations for ccache. The default is 2 gigabytes
+('2G'). Sizes are specified with 'G', 'M', or 'K'.
+.TP
+.B CFLAGS CXXFLAGS
+Use these variables to set the desired optimization/CPU instruction settings
+for applications that you compile. Nearly all ebuild files will take advantage
+of your custom settings, resulting in a Gentoo Linux that is fully customized
+to your specifications. Please use sane settings as some packages will fail to
+compile/run if the optimizations are too extreme.
+
+For more information:
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-3.2/gcc/Invoking\-GCC.html
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-3.3/gcc/Invoking\-GCC.html
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-2.95.3/gcc_2.html
+.TP
+.B CHOST
+This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
+step as \fI\-\-host=${CHOST}\fR. This way you can force the build\-host.
+
+For more information:
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-3.2/gcc/Submodel\-Options.html
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-3.3/gcc/Submodel\-Options.html
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-2.95.3/gcc_2.html
+.TP
+\fBCLEAN_DELAY\fR = \fIinteger\fR
+Determines how long the countdown delay will be after running `emerge clean`.
+.br
+Defaults to 5 seconds.
+.TP
+\fBCONFIG_PROTECT\fR = \fI[space delimited list of dirs]\fR
+All directories that are defined here will have "config file protection"
+enabled for them. For more information, please see `emerge \-\-help config`.
+.TP
+\fBCONFIG_PROTECT_MASK\fR = \fI[space delimited list of dirs]\fR
+All directories that are defined here will have "config file protection"
+disabled for them. For more information, please see `emerge \-\-help config`.
+.TP
+.B CTARGET
+This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
+as \fI\-\-target=${CTARGET}\fR only if it is defined.
+.TP
+\fBDISTDIR\fR = \fI[path]\fR
+Defines the location of your local source file repository.
+.br
+Defaults to ${PORTDIR}/distfiles.
+.TP
+.B EBEEP_IGNORE
+Defines whether or not to ignore audible beeps when displaying important
+informational messages. This variable is unset by default.
+.TP
+.B EPAUSE_IGNORE
+Defines whether or not to ignore short pauses that occur when displaying
+important informational messages. This variable is unset by default.
+.TP
+\fBFEATURES\fR = \fI"sandbox ccache autoaddcvs"\fR
+Defines actions portage takes by default. These options should
+not be changed by anyone but developers and/or maintainers. 'sandbox' is an important
+part of \fBFEATURES\fR and should not be disabled by default. This is
+an incremental variable.
+.RS
+.TP
+.B autoaddcvs
+Causes portage to automatically try to add files to cvs that will have to be added
+later. Done at generation times and only works when \fIcvs\fR is also in
+\fBFEATURES\fR.
+.TP
+.B buildpkg
+Binary packages will be created for all packages that are merged.
+.TP
+.B ccache
+Enable portage support for the ccache package. If the ccache dir is not
+present in the user's environment, then portage will default to
+${PORTAGE_TMPDIR}/ccache (with \fIuserpriv\fR) and to /root/.ccache otherwise.
+.TP
+.B collision\-protect
+A QA\-feature to ensure that a package doesn't overwrite files it doesn't own.
+.TP
+.B cvs
+A feature for developers that causes portage to enable all USE flags in SRC_URI
+when creating digests.
+.TP
+.B digest
+Autogenerate a digest for packages.
+.TP
+.B distcc
+Enable portage support for the distcc package.
+.TP
+.B distlocks
+Portage uses lockfiles to ensure competing instances don't clobber
+each other's files. This feature is enabled by default but may cause
+heartache on less intelligent remote filesystems like NFSv2 and some
+strangely configured Samba server (oplocks off, NFS re-export). A tool
+/usr/lib/portage/bin/clean_locks exists to help handle lock issues
+when a problem arises (normally due to a crash or disconnect).
+.TP
+.B fixpackages
+Runs the script that will fix the dependencies in all binary packages. This is
+run whenever packages are moved around in the portage tree. Please note that this
+can take a lot of time.
+.TP
+.B getbinpkg
+Force emerges to always try to fetch files from the \fIPORTAGE_BINHOST\fR. See
+\fBmake.conf\fR(5) for more information.
+.TP
+.B gpg
+Check the signatures of Manifests and make sure they are correct.
+.TP
+.B keeptemp
+Do not delete the ${T} directory after the merge process.
+.TP
+.B keepwork
+Do not delete the ${WORKDIR} directory after the merge process.
+.TP
+.B mirror
+This will cause \fBFETCHCOMMAND\fR to always be run even if
+the file already exists in \fBDISTDIR\fR.
+.TP
+.B noauto
+When utilizing \fBebuild\fR(1), only run the function requested.
+.TP
+.B noclean
+Do not delete the the source and temporary files after the merge process.
+.TP
+.B nodoc
+Do not install doc files (/usr/share/doc).
+.TP
+.B noinfo
+Do not install info pages.
+.TP
+.B noman
+Do not install manpages.
+.TP
+.B nostrip
+Prevents the stripping of binaries that are merged to the live filesystem.
+.TP
+.B notitles
+Disables xterm titlebar updates (which contains status info).
+.TP
+.B sandbox
+Enable sandbox\-ing when running \fBemerge\fR(1) and \fBebuild(1)\fR.
+.TP
+.B severe
+When checking Manifests, only accept ones that have been signed by a
+key which you trust.
+.TP
+.B sfperms
+Stands for Smart Filesystem Permissions. Before merging packages to the
+live filesystem, automatically search for and set permissions on setuid
+and setgid files. Files that are setuid have the group and other read
+bits removed while files that are setgid have the other read bit removed.
+See also \fIsuidctl\fR below.
+.TP
+.B sign
+When commiting work to cvs with \fBrepoman\fR(1), sign the Manifest with
+a GPG key. Read about the \fIPORTAGE_GPG_KEY\fR variable in \fBmake.conf\fR(5).
+.TP
+.B strict
+Have portage react strongly to conditions that have the potential to be
+dangerous (like missing or incorrect Manifests).
+.TP
+.B suidctl
+Before merging packages to the live filesystem, automatically strip setuid
+bits from any file that is not listed in \fI/etc/portage/suidctl.conf\fR.
+.TP
+.B test
+Run package\-specific tests during each merge to help make sure
+the package compiled properly. See \fItest\fR in \fBebuild\fR(1)
+and \fIsrc_test()\fR in \fBebuild\fR(5).
+.TP
+.B userpriv
+Allow portage to drop root privledges and compile packages as
+portage:portage without a sandbox (unless \fIusersandbox\fR is also used).
+.TP
+.B usersandbox
+Enable the sandbox in the compile phase, when running without root privs (\fIuserpriv\fR).
+.RE
+.TP
+\fBFETCHCOMMAND\fR
+This variable contains the command used for fetching package\-sources from
+the internet.
+.TP
+\fBGENTOO_MIRRORS\fR = \fI[URLs]\fR
+Insert your space\-seperated list of local mirrors here. These
+locations are used to download files before the ones listed in
+the \fIebuild scripts\fR. Merging 'mirrorselect' can help.
+.TP
+\fBhttp_proxy ftp_proxy\fR = \fI[host:port]\fR
+These vars are used if the sources must be downloaded from the
+internet by \fBwget\fR(1). They are only required if you use a
+proxy server for internet access.
+.TP
+\fBMAKEOPTS\fR
+Use this variable if you want to use parallel make. For example, if you
+have a dual\-processor system, set this variable to "\-j2" or "\-j3" for
+enhanced build performance with many packages. Suggested settings are
+between \fICPUs+1\fR and \fI2*CPUs+1\fR.
+For more information, see \fBmake\fR(1).
+.TP
+\fBNOCOLOR\fR = \fI["true" | "false"]\fR
+Defines if color should be disabled by default.
+.br
+Defaults to false.
+.TP
+\fBPKGDIR\fR = \fI[path]\fR
+Defines the location where created .tbz2 binary packages will be stored.
+.br
+Defaults to ${PORTDIR}/packages.
+.TP
+.B PORT_LOGDIR
+This variable defines the directory in which per\-ebuild logs are kept.
+Logs are created only when this is set and writable.
+.TP
+\fBPORTAGE_BINHOST\fR = \fI"ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon\-xp"\fR
+This is the host from which portage will grab prebuilt\-binary packages.
+The list is a single entry specifying the full address of the directory
+serving the tbz2's for your system. This is only used when running with
+the get binary pkg options are given to \fBemerge\fR. Review \fBemerge\fR(1)
+for more information. Note that it should point to the 'All' directory on
+the host that creates the binary packages and not to the root of the \fBPKGDIR\fR.
+.TP
+\fBPORTAGE_NICENESS\fR = \fI[number]\fR
+The value of this variable will be added to the current nice level that
+emerge is running at. In other words, this will not set the nice level,
+it will increment it. For more information about nice levels and what
+are acceptable ranges, see \fBnice\fR(1).
+.TP
+\fBPORTAGE_TMPDIR\fR = \fI[path]\fR
+Defines the location of the temporary build directories.
+.br
+Defaults to /var/tmp.
+.TP
+\fBPORTDIR\fR = \fI[path]\fR
+Defines the location of your Portage tree.
+.br
+Defaults to /usr/portage.
+.TP
+\fBPORTDIR_OVERLAY\fR = \fI"[path] [different\-path] [etc...]"\fR
+Defines the directories in which user made ebuilds may be stored and not
+overwriten when `emerge \-\-sync` is run. This is a space delimited list of
+directories.
+.br
+Defaults to no value.
+.TP
+\fBRESUMECOMMAND\fR
+This variable contains the command used for resuming package\-sources that
+have been partially downloaded by the \fBFETCHCOMMAND\fR.
+.TP
+\fBROOT\fR = \fI[path]\fR
+Use \fBROOT\fR to specify the target root filesystem to be used for merging
+packages or ebuilds. All \fBRDEPEND\fR and \fBPDEPEND\fR will be installed
+into \fBROOT\fR while all \fBDEPEND\fR will be still be installed into /.
+Typically, you should set this setting in the environment rather than in
+\fI/etc/make.conf\fR itself. It's commonly used for creating new build
+images.
+.br
+Defaults to /.
+.TP
+\fBRSYNC_EXCLUDEFROM\fR = \fI"/etc/portage/rsync_excludes"\fR
+This is a file that portage will pass to rsync when it updates the portage
+tree. Specific chucks of the tree may be excluded from the sync process.
+This may cause dependency failures if you are not careful. The file format
+is pattern per line, blanks and ';' or '#' lines are comments. See
+\fBrsync\fR(1) for more details.
+.TP
+\fBRSYNC_RETRIES\fR = \fI[NUMBER]\fR
+The number of times rsync should retry on failed connections before
+giving up.
+.br
+Defaults to 3.
+.TP
+\fBRSYNC_TIMEOUT\fR = \fI[SECONDS]\fR
+The number of seconds rsync should remain idle before it determines the
+connection has timed out. Dialup users may need to set this value at or
+above 300 seconds.
+.br
+Defaults to 180 seconds.
+.TP
+\fBRPMDIR\fR = \fI[path]\fR
+Defines the location where created RPM packages will be stored.
+.br
+Defaults to ${PORTDIR}/rpm.
+.TP
+\fBSYNC\fR = \fI[RSYNC]\fR
+Insert your preferred rsync mirror here. This rsync server
+is used to sync the local portage tree when `emerge \-\-sync` is run.
+.br
+Defaults to rsync://rsync.gentoo.org/gentoo\-portage
+.TP
+\fBUSE\fR = \fI[space delimited list of USE items]\fR
+This variable contains options that control the build behavior of several
+packages. More information in \fBebuild\fR(5). Possible USE values
+can be found in \fI/usr/portage/profiles/use.desc\fR.
+.TP
+\fBUSE_ORDER\fR = \fI"env:pkg:conf:auto:defaults"\fR
+Determines precedence for incrementing the setting of the USE variable.
+The above setting will cause the environment (env) to override per package (pkg)
+settings to override make.conf (conf) to override auto generated values
+from merged packages (auto) to override make.defaults (defaults).
+.br
+\fB***warning***\fR
+.br
+Do not modify this value unless you're a developer and you know what
+you're doing. If you change this and something breaks, we will not help
+you fix it.
+.br
+Defaults to "env:pkg:conf:auto:defaults".
+
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR portage (5),
+.BR ebuild (1),
+.BR ebuild (5)
+.TP
+The \fI/usr/sbin/ebuild.sh\fR script.
+.TP
+The helper apps in \fI/usr/lib/portage/bin\fR.
+.SH "FILES"
+.TP
+\fB/etc/make.conf\fR
+Contains variables for the build\-process and overwrites those in make.defaults.
+.TP
+\fB/etc/make.globals\fR
+Contains the default variables for the build\-process, you should edit \fI/etc/make.conf\fR instead.
+.TP
+\fB/usr/portage/profiles/use.desc\fR
+Contains a list of all global USE flags.
+.TP
+\fB/usr/portage/profiles/use.local.desc\fR
+Contains a list of all local USE variables.
+.SH "AUTHORS"
+Daniel Robbins <drobbins@gentoo.org>
+.br
+Nicholas Jones <carpaski@gentoo.org>
+.br
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/make.conf.5,v 1.44.2.4 2005/06/04 04:53:13 vapier Exp $
diff --git a/man/perl-module.eclass.5 b/man/perl-module.eclass.5
new file mode 100644
index 00000000..1f71a333
--- /dev/null
+++ b/man/perl-module.eclass.5
@@ -0,0 +1,66 @@
+.TH "PERL-MODULE.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+perl-module.eclass \- handles generic perl module ebuilds
+.SH "DESCRIPTION"
+The \fBperl-module\fR eclass is used for the compilation, testing, and
+installation of perl modules within the portage system, following
+vanilla procedure for modules using either \fBExtUtils::MakeMaker\fR(3pm)
+or \fBModule::Builder\fR(3pm).
+.SH "VARIABLES"
+.TP
+.B "style" = \fI"[builder|makemaker]"\fR
+This variable allows you to choose which package to use as the default
+for building the module. If you do not specify a \fIstyle\fR, then
+the default \fBExtUtils::MakeMaker\fR(3pm) will be used.
+.SH "FUNCTIONS"
+.TP
+.B perl-module_src_prep
+Create the initial Makefile.
+.TP
+.B perl-module_src_compile
+Calls \fBperl-module_src_prep\fR if it hasn't been already. Runs
+initial make.
+.TP
+.B perl-module_src_test
+If invoked, runs all the tests distributed with the module.
+.TP
+.B perl-module_src_install
+Runs `make install` (or the \fBModule::Builder\fR(3pm) equivelant if it
+is a builder module). Also cleans build paths from pod files and
+generated perllocal.pod.
+.TP
+.B perl-module_pkg_setup
+Calls \fBperlinfo\fR.
+.TP
+.B perl-module_pkg_preinst
+Calls \fBperlinfo\fR.
+.TP
+.B perl-module_pkg_postinst
+Calls \fBupdatepod\fR.
+.TP
+.B perl-module_pkg_prerm
+Calls \fBupdatepod\fR.
+.TP
+.B perl-module_pkg_postrm
+Calls \fBupdatepod\fR.
+.TP
+.B perlinfo
+Updates the gentoo-pods documentation.
+.TP
+.B updatepod
+Cleans the perllocal.pods in ARCH_LIB and SITE_LIB.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5),
+.BR ExtUtils::MakeMaker (3pm),
+.BR Module::Build (3pm),
+.BR perl (1)
+.SH "FILES"
+.BR /usr/portage/eclass/perl-module.eclass
+.SH "AUTHORS"
+Michael Cummings <mcummings@gentoo.org>
+.br
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/perl-module.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/portage.5 b/man/portage.5
new file mode 100644
index 00000000..f9cad8b0
--- /dev/null
+++ b/man/portage.5
@@ -0,0 +1,588 @@
+.TH "PORTAGE" "5" "Jan 2004" "Portage 2.0.51" "Portage"
+.SH NAME
+portage \- the heart of Gentoo
+.SH "DESCRIPTION"
+The current portage code uses many different configuration files, most of which
+are unknown to users and normal developers. Here we will try to collect all
+the odds and ends so as to help users more effectively utilize portage. This
+is a reference only for files which do not already have a man page.
+
+All files in the make.profile directory may be tweaked via parent profiles
+when using cascading profiles. For more info, please see
+http://www.gentoo.org/proj/en/releng/docs/cascading-profiles.xml
+.IP Note:
+If you are looking for information on how to emerge something, please see
+.BR emerge (1).
+.SH "SYNOPSIS"
+.TP
+.BR /etc/
+.nf
+make.globals
+.BR make.conf (5)
+.fi
+.TP
+.BR /etc/make.profile/
+.nf
+deprecated
+make.defaults
+packages
+packages.build
+package.provided
+parent
+use.defaults
+use.mask
+virtuals
+.fi
+.TP
+.BR /etc/portage/
+.nf
+bashrc
+package.mask
+package.unmask
+package.keywords
+package.use
+mirrors
+categories
+.fi
+.TP
+.BR /etc/portage/profile/
+site-specific overrides of \fB/etc/make.profile/\fR
+.TP
+.BR /usr/portage/profiles/
+.nf
+arch.list
+categories
+info_pkgs
+info_vars
+package.mask
+profiles.desc
+thirdpartymirrors
+use.desc
+use.local.desc
+.fi
+.TP
+.BR /var/lib/portage/
+world
+.SH "GLOSSARY"
+In the following sections, some terminology may be foreign to you or used
+with meaning specific to Portage. Please see the referenced manpages for
+more detailed explanations.
+.RS
+.TP
+.B DEPEND atom
+A string which matches a package. It is of the form category/package.
+It may also contain optional logical operators and versions.
+.br
+More reading:
+.BR ebuild (5)
+.TP
+.B KEYWORD
+Each architecture has a unique KEYWORD.
+.br
+More reading:
+.BR ebuild (5)
+.TP
+.B virtual
+A DEPEND atom that is part of the "virtual" category. They are used
+when different packages can satisfy a dependency and only one of them is
+needed.
+.br
+More reading:
+.BR ebuild (5)
+.RE
+.SH "SPECIFIC FILE DESCRIPTIONS"
+.TP
+.BR /etc/
+.RS
+.TP
+.BR make.globals
+The global default settings for Portage. This comes from the portage package
+itself. Settings in \fBmake.conf\fR override values here. The format
+is described extensivly in \fBmake.conf\fR(5).
+.TP
+.BR make.conf
+The global custom settings for Portage. See \fBmake.conf\fR(5).
+.RE
+.TP
+.BR /etc/make.profile/
+This is usually just a symlink to the correct profile in
+\fB/usr/portage/profiles/\fR. Since it is part of the portage tree, it
+may easily be updated/regenerated by running `emerge \-\-sync`. It defines
+what a profile is (usually arch specific stuff). If you need a custom
+profile, then you should make your own \fB/etc/make.profile/\fR
+directory and populate it. However, if you just wish to override some
+settings, do NOT edit these files because they WILL be lost with the
+next `emerge \-\-sync`. See the section below on \fB/etc/portage/\fR for
+overriding.
+.RS
+.TP
+.BR deprecated
+The existence of this file marks a profile as deprecated, meaning it is
+not supported by Gentoo anymore. The first line must be the profile to which
+users are encouraged to upgrade, optionally followed by some instructions
+explaining how they can upgrade.
+
+.I Example:
+.nf
+default-linux/x86/2005.0
+# emerge -n '>=sys-apps/portage-2.0.51'
+# rm -f /etc/make.profile
+# ln -s /usr/portage/profiles/default-linux/alpha/2005.0 /etc/make.profile
+.fi
+.TP
+.BR make.defaults
+The profile default settings for Portage. The general format is described
+in \fBmake.conf\fR(5). The \fImake.defaults\fR for your profile defines a
+few specific variables too:
+
+.PD 0
+.RS
+.TP
+.BR ARCH
+Architecture type (x86/ppc/hppa/etc...).
+.TP
+.B USERLAND = \fI"GNU"\fR
+Support BSD/cygwin/etc...
+.TP
+.B PORTAGE_LIBC = \fI"glibc"\fR
+Support uClibc/BSD libc/etc...
+.TP
+.BR PROFILE_ARCH
+Distinguish machines classes that have the same \fBARCH\fR. All sparc
+machines have ARCH=sparc but set this to either 'sparc32' or 'sparc64'.
+.TP
+.BR STAGE1_USE
+Special USE flags which may be needed when bootstrapping from stage1 to stage2.
+.TP
+.BR GRP_STAGE23_USE
+Special USE flags used by catalyst for building a stage3 and GRP sets.
+.RE
+.PD 1
+.TP
+.BR packages
+This file serves two purposes. The first is to mask out specific
+packages/versions on a per\-profile basis. The second is to provide the
+list of packages that compose the special \fIsystem\fR class.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line of what to mask OUT
+\- packages to be added to the system class begin with a *
+.fi
+.I Note:
+In a cascading profile setup, you can remove packages in children
+profiles which were added by parent profiles by prefixing the atom with
+a '\-'.
+
+.I Example:
+.nf
+# i am a comment !
+# only allow versions of glibc less than 2.3
+<sys\-libs/glibc\-2.3
+# add any version of bash to the system class
+*app\-shells/bash
+# only allow versions of readline earlier than 4.2
+# and add it to the system class
+*<sys\-libs/readline\-4.2
+.fi
+.TP
+.BR packages.build
+A list of packages (one per line) that make up a stage1 tarball. Really only
+useful for stage builders.
+.TP
+.BR package.provided
+A list of packages (one per line) that portage should assume have been
+provided. Useful for porting to non-Linux systems. Portage will not
+attempt to update a package that is listed here unless another package
+explicitly requires a version that is newer than what has been listed.
+Basically, it's a list that replaces the \fBemerge \-\-inject\fR syntax.
+
+For example, if you manage your own copy of a 2.6 kernel, then you can
+tell portage that 'sys-kernel/development-sources-2.6.7' is already taken
+care of and it should get off your back about it.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line
+\- relational operators are not allowed
+\- must include a version
+.fi
+
+.I Example:
+.nf
+# you take care of the kernel
+sys-kernel/development-sources-2.6.7
+
+# you installed your own special copy of QT
+x11-libs/qt-3.3.0
+.fi
+.TP
+.BR parent
+This contains a path to the parent profile. It may be either relative or
+absolute. The paths will be relative to the location of the profile. Most
+commonly this file contains '..' to indicate the directory above. Utilized
+only in cascading profiles.
+.TP
+.BR use.defaults
+Here we DO NOT define the default USE flags, but the so\-called auto\-USE
+flags. This rather unknown portage feature activates a USE flag if a
+specific package is installed and the flag was not explicitly
+deactivated. This file contains the associations between USE flags and
+packages that trigger the auto\-USE feature.
+
+In other words, if we never put "sdl" or "\-sdl" into our USE, but we
+have media\-libs/libsdl emerged, then portage automagically sticks "sdl"
+into our USE for us.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one USE flag per line with a list of DEPEND atom bases
+.fi
+
+.I Example:
+.nf
+# media\-libs/libsdl will activate "sdl"
+sdl media\-libs/libsdl
+# activate tcltk only if we have both
+# dev\-lang/tcl and dev\-lang/tk
+tcltk dev\-lang/tcl dev\-lang/tk
+.fi
+.TP
+.BR use.mask
+Some USE flags don't make sense on some archs (for example altivec on
+non\-ppc or mmx on non\-x86), or haven't yet been tested. Here we list
+the masked ones.
+
+.I Note:
+In a cascading profile setup, you can remove USE flags in children
+profiles which were added by parent profiles by prefixing the flag with
+a '\-'.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one USE flag per line
+.fi
+.TP
+.BR virtuals
+This controls what packages will provide a virtual by default. For example,
+if a package needs to send e\-mail, it will need virtual/mta. In the absence
+of a package that provides virtual/mta (like qmail, sendmail, postfix, etc...),
+portage will look here to see what package to use. In this case, Gentoo uses
+net\-mail/ssmtp as the default (as defined in the virtuals file) because it's
+the package that does the very bare minimum to send e\-mail.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one virtual and DEPEND atom base pair per line
+.fi
+
+.I Example:
+.nf
+# use net\-mail/ssmtp as the default mta
+virtual/mta net\-mail/ssmtp
+# use app\-dicts/aspell\-en as the default dictionary
+virtual/aspell\-dict app\-dicts/aspell\-en
+.fi
+.RE
+.TP
+.BR /etc/portage/
+.RS
+.TP
+.BR bashrc
+If needed, this file can be used to set up a special environment for ebuilds,
+different from the standard root environment. The syntax is the same as for
+any other bash script.
+.TP
+.BR package.mask
+A list of DEPEND atoms to mask. Useful if specific versions of packages do
+not work well for you. For example, you swear by the Nvidia drivers, but only
+versions earlier than 1.0.4496. No problem!
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line
+.fi
+
+.I Example:
+.nf
+# mask out versions 1.0.4496 of the nvidia
+# drivers and later
+>=media\-video/nvidia\-kernel\-1.0.4496
+>=media\-video/nvidia\-glx\-1.0.4496
+.fi
+.TP
+.BR package.unmask
+Just like package.mask above, except here you list packages you want to
+unmask. Useful for overriding the global package.mask file (see
+below). Note that this does not override packages that are masked via
+KEYWORDS.
+.TP
+.BR package.keywords
+Per\-package KEYWORDS. Useful for mixing unstable packages in with a normally
+stable machine or vice versa. This will allow you to augment ACCEPT_KEYWORDS
+for a single package.
+
+.nf
+\fINote:\fR There are two special KEYWORDS to help out here:
+\fB*\fR Match any stable KEYWORD
+\fB~*\fR Match any unstable KEYWORD
+
+.I Format:
+\- comments begin with #
+\- one DEPEND atom per line followed by additional KEYWORDS
+\- blank lines imply unstable host arch
+
+.I Example:
+# always use unstable libgd
+media\-libs/libgd ~x86
+# only use stable mplayer
+media\-video/mplayer \-~x86
+# always use unstable netcat
+net-analyzer/netcat
+.fi
+.TP
+.BR package.use
+Per\-package USE flags. Useful for tracking local USE flags or for
+enabling USE flags for certain packages only. Perhaps you develop GTK
+and thus you want documentation for it, but you don't want
+documentation for QT. Easy as pie my friend!
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line with space-delimited USE flags
+.fi
+
+.I Example:
+.nf
+# turn on docs for GTK 2.x
+=x11\-libs/gtk+\-2* doc
+# disable mysql support for QT
+x11\-libs/qt \-mysql
+.fi
+.TP
+.BR mirrors
+Whenever portage encounters a mirror:// style URL it will look up the actual
+hosts here. If the mirror set is not found here, it will check the global
+mirrors file at /usr/portage/profiles/thirdpartymirrors. You may also set a
+special mirror type called "local". This list of mirrors will be checked
+before GENTOO_MIRRORS and will be used even if the package has
+RESTRICT="nomirror".
+
+.I Format:
+.nf
+\- comments begin with #
+\- mirror type followed by a list of hosts
+.fi
+
+.I Example:
+.nf
+# local private mirrors used only by my company
+local ftp://192.168.0.3/mirrors/gentoo http://192.168.0.4/distfiles
+
+# people in japan would want to use the japanese mirror first
+sourceforge http://keihanna.dl.sourceforge.net/sourceforge
+
+# people in tawain would want to use the local gnu mirror first
+gnu ftp://ftp.nctu.edu.tw/UNIX/gnu/
+.fi
+.TP
+.BR categories
+A simple list of valid categories that may be used in /usr/portage,
+PORTDIR_OVERLAY, and PKGDIR (see \fBmake.conf\fR(5)). This allows for custom
+categories to be created.
+
+.I Format:
+.nf
+\- one category per line
+.fi
+
+.I Example:
+.nf
+app\-hackers
+media\-other
+.fi
+.TP
+.BR /usr/portage/profiles/
+Global Gentoo settings that are controlled by the developers. To override
+these settings, you can use the files in \fB/etc/portage/\fR.
+.RS
+.TP
+.BR arch.list
+A list of all valid KEYWORDS. This does not include modifiers.
+
+.I Format:
+.nf
+\- one KEYWORD per line
+.fi
+
+.I Example:
+.nf
+x86
+ppc
+sparc
+.fi
+.TP
+.BR categories
+A simple list of valid categories that may be used in /usr/portage,
+PORTDIR_OVERLAY, and PKGDIR (see \fBmake.conf\fR(5)).
+
+.I Format:
+.nf
+\- one category per line
+.fi
+
+.I Example:
+.nf
+app\-admin
+dev\-lang
+games\-strategy
+sys\-kernel
+.fi
+.TP
+.BR info_pkgs
+A list of all the packages which will be displayed when you run `emerge info`.
+.TP
+.BR info_vars
+A list of all the variables which will be displayed when you run `emerge info`.
+.TP
+.BR package.mask
+This contains a list of DEPEND atoms for packages that should not be installed
+in any profile. Useful for adding the latest KDE betas and making sure no
+one accidentally upgrades to them. Also useful for quickly masking specific
+versions due to security issues. ALWAYS include a comment explaining WHY the
+package has been masked and WHO is doing the masking.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line
+.fi
+
+.I Example:
+.nf
+# masked for security reasons
+<sys\-libs/zlib\-1.1.4
+# <caleb@gentoo.org> (10 Sep 2003)
+# new kde betas
+=kde\-base/kde\-3.2.0_beta1
+=kde\-base/kdeaccessibility\-3.2.0_beta1
+.fi
+.TP
+.BR profiles.desc
+List all the current stable and development profiles. If a profile is listed
+here, then it will be checked by repoman. At the moment, only 1 profile is
+allowed per stable/dev/KEYWORD; the last one found is the last one used.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one profile list per line in format: arch dir status
+\- arch must be listed in arch.list
+\- dir is relative to profiles.desc
+\- status must be 'stable' or 'dev'
+.fi
+
+.I Example:
+.nf
+alpha default-linux/alpha/2004.3 stable
+m68k default-linux/m68k dev
+x86 default-linux/x86/2004.3 stable
+.fi
+.TP
+.BR thirdpartymirrors
+Controls the mapping of mirror:// style URLs to actual lists of
+mirrors. Keeps us from overloading a single server.
+
+.I Format:
+.nf
+\- comments begin with #
+\- mirror type followed by a list of hosts
+.fi
+
+.I Example:
+.nf
+sourceforge http://aleron.dl.sourceforge.net/sourceforge http://unc.dl.sourceforge.net/sourceforge
+
+gentoo http://distro.ibiblio.org/pub/linux/distributions/gentoo/distfiles/ ftp://ftp.gtlib.cc.gatech.edu/pub/gentoo/distfiles
+
+kernel http://www.kernel.org/pub http://www.us.kernel.org/pub
+.fi
+.TP
+.BR use.desc
+All global USE flags must be listed here with a description of what they do.
+
+.I Format:
+.nf
+\- comments begin with #
+\- use flag \- some description
+.fi
+
+.I Example:
+.nf
+3dfx \- Adds support for 3dfx video cards
+acl \- Adds support for Access Control Lists
+doc \- Adds extra documentation
+.fi
+.TP
+.BR use.local.desc
+All local USE flags must be listed here along with the package and a
+description.
+
+.nf
+.I Format:
+\- comments begin with #
+\- package:use flag \- description
+
+.I Example:
+app\-editors/nano:justify \- Toggles the justify option
+dev\-libs/DirectFB:fusion \- Adds Multi Application support
+games\-emulation/xmess:net \- Adds network support
+.fi
+.RE
+.TP
+.BR /var/lib/portage/
+.RS
+.TP
+.BR world
+Every time you emerge a package, the package that you requested is
+recorded here. Then when you run `emerge world \-up`, the list of
+packages is read from this file. Note that this does not mean that the
+packages that were installed as dependencies are listed here. For
+example, if you run `emerge mod_php` and you do not have apache
+already, then "dev\-php/mod_php" is recorded in the world file but
+"net\-www/apache" is not. For more information, review \fBemerge\fR(1).
+
+.I Format:
+.nf
+\- one DEPEND atom base per line
+.fi
+
+.I Example:
+.nf
+games\-misc/fortune\-mod\-gentoo\-dev
+dev\-libs/uclibc
+app\-cdr/cdemu
+.fi
+.RE
+.SH "AUTHORS"
+.nf
+Marius Mauch <genone@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+Drake Wyrm <wyrm@haell.com>
+.fi
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR ebuild (1),
+.BR ebuild (5),
+.BR make.conf (5)
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/portage.5,v 1.17.2.12 2005/07/02 21:02:17 vapier Exp $
diff --git a/man/python.eclass.5 b/man/python.eclass.5
new file mode 100644
index 00000000..90db3530
--- /dev/null
+++ b/man/python.eclass.5
@@ -0,0 +1,82 @@
+.TH PYTHON.ECLASS 5 "Nov 2004" "Portage 2.0.51" portage
+.SH NAME
+python.eclass \- functions for Python-related ebuilds
+.SH DESCRIPTION
+The \fBpython\fR eclass provides general utility functions for Python-related
+ebuilds.
+.SH VARIABLES
+.TP
+.B PYVER
+Defines major and minor Python version. This is a READ-ONLY variable, set by
+the \fBpython_version\fR function.
+.TP
+.B PYVER_MAJOR
+Defines major Python version. This is a READ-ONLY variable, set by the
+\fBpython_version\fR function.
+.TP
+.B PYVER_MINOR
+Defines minor Python version. This is a READ-ONLY variable, set by the
+\fBpython_version\fR function.
+.TP
+.B PYVER_MICRO
+Defines micro Python version. This is a READ-ONLY variable, set by the
+\fBpython_version\fR function.
+.TP
+.B PYTHON_OVERRIDE_PYVER = \fI"2.2"\fR
+When set, overrides the version of Python to use in the \fBpython_mod_compile\fR
+and \fBpython_mod_optimize\fR functions.
+.SH FUNCTIONS
+.TP
+.B python_version
+Sets variables \fBPYVER\fR, \fBPYVER_MAJOR\fR, \fBPYVER_MINOR\fR, and
+\fBPYVER_MICRO\fR to the version of Python currently available.
+.TP
+.B python_disable_pyc
+Disables automatic recompilation of modules to .pyc/.pyo. This is supported by
+>=dev-lang/python-2.2.3-r3 only.
+.TP
+.B python_enable_pyc
+Enables automatic recompilation of modules to .pyc/.pyo. This is supported by
+>=dev-lang/python-2.2.3-r2 only.
+.TP
+.B python_makesym
+Creates the /usr/bin/python symbolic link to point to the latest installed
+version of Python.
+.TP
+.B python_tkinter_exists
+Checks to see if Python was compiled with Tkinter support (via USE=tcltk).
+If not, this function will print an error message informing the user that
+Tkinter support is required and then die.
+.TP
+.B python_mod_exists \fI[ module ]\fR
+Checks to see if the specified module is installed and loadable. Returns true
+(0) if so or false (1) if not.
+.TP
+.B python_mod_compile \fI[ file ]\fR
+Precompiles the specified file, creating the module's pyc and pyo files. If
+the variable, \fBPYTHON_OVERRIDE_PYVER\fR is set, this function will use the
+specified version of Python to compile rather than the version detected by
+\fBpython_version\fR. This function should only be run from \fBpkg_postinst\fR.
+.TP
+.B python_mod_optimize \fI< dir1 > < dir 2 >\fR
+If called with no arguments, this function will recompile all modules under
+sys.path without recursing into subdirectories. Called with arguments, this
+function will recursively compile all modules in the specified directories.
+If the variable, \fBPYTHON_OVERRIDE_PYVER\fR is set, this function will use
+the specified version of Python rather than the version detected by
+\fBpython_version\fR.
+.TP
+.B python_mod_cleanup \fI< dir1 > < dir2 >\fR
+Recursively searches specified directories (or /usr/lib/python*/site-packages
+if called with no arguments) removing orphaned bytecode (.pyc/.pyo files with
+no corresponding .py file).
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/python.eclass
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/python.eclass.5,v 1.1.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/quickpkg.1 b/man/quickpkg.1
new file mode 100644
index 00000000..c7f07f5e
--- /dev/null
+++ b/man/quickpkg.1
@@ -0,0 +1,56 @@
+.TH "QUICKPKG" "1" "Jul 2003" "Portage 2.0.51" "Portage"
+.SH NAME
+quickpkg \- creates portage packages
+.SH SYNOPSIS
+.B quickpkg <list of pkgs>
+.SH DESCRIPTION
+.I quickpkg
+can be utilized to quickly create a package for portage by
+utilizing the files already on your filesystem. This package
+then can be emerged on any system. To review syntax for
+emerging binary packages, review \fBemerge\fR(1). The upside
+of this process is that you don't have to wait for the package
+to unpack, configure, compile, and install before you can have
+the package ready to go. The downside is that the package will
+contain the files that exist on your filesystem even if they have
+modified since they were first installed.
+.br
+The packages, after being created, will be placed in \fBPKGDIR\fR.
+This variable is defined in \fBmake.conf\fR(5) and defaults to
+/var/tmp/portage-pkg.
+.SH OPTIONS
+.TP
+.B <list of packages>
+Each package in the list can be of two forms. First you can
+give it the full path to the installed entry in the virtual
+database. That is, /var/db/pkg/<CATEGORY>/<PKG-VERSION>/.
+The second form is a portage depend atom. This atom is of
+the same form that you would give \fBemerge\fR if you wanted
+to emerge something. See \fBebuild\fR(5) for full definition.
+.SH "EXAMPLES"
+.B quickpkg
+/var/db/pkg/dev-python/pyogg-1.1
+.br
+.B quickpkg
+planeshift
+.br
+.B quickpkg
+=apache-1.3.27-r1
+.br
+.B quickpkg
+=net-www/apache-2*
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5),
+.BR make.conf (5)
+.SH "FILES"
+.TP
+.B /etc/make.conf
+The \fBPKGDIR\fR variable is defined here.
+.SH AUTHORS
+Terry Chan (original author)
+.br
+Mike Frysinger <vapier@gentoo.org> (revamped version)
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/quickpkg.1,v 1.3 2004/09/17 00:17:10 vapier Exp $
diff --git a/man/repoman.1 b/man/repoman.1
new file mode 100644
index 00000000..5e7e422c
--- /dev/null
+++ b/man/repoman.1
@@ -0,0 +1,127 @@
+.TH "REPOMAN" "1" "Nov 2002" "Portage 2.0.51" "Portage"
+.SH NAME
+repoman \- Gentoo's program to enforce a minimal level of quality assurance in packages added to the portage tree
+.SH SYNOPSIS
+\fBrepoman\fR [\fIoption\fR] [\fImode\fR]
+.SH DESCRIPTION
+.BR "Quality is job zero."
+.br
+.BR repoman
+is meant for Gentoo developers only due to the fact it does not work on a per-ebuild basis.
+It checks the quality of CVS repositories.
+.br
+Note: \fBrepoman\fR only runs \fIinside local\fR CVS repositories.
+.SH OPTIONS
+.TP
+.B --pretend
+Don't actually perform commit or fix problems, just show what would be done.
+.TP
+.B --help
+Show the help screen.
+.SH MODES
+.TP
+.B scan
+Scan current directory tree for QA issues (default). See \fBQA KEYWORDS\fR for more
+information.
+.TP
+.B fix
+Fix those issues that can be fixed (stray digests, missing digests).
+.TP
+.B full
+Scan current directory tree for QA issues (full listing). See \fBQA KEYWORDS\fR for more
+information.
+.TP
+.B help
+Show the help screen.
+.TP
+.B commit
+Scan current directory tree for QA issues. If OK, commit via cvs.
+.SH QA KEYWORDS
+.TP
+.BR CVS/Entries.IO_error
+While attempting to commit, a CVS/Entries directory wasn't found- either the cvs co is damaged, or permissions block repoman from reading the file.
+.TP
+.BR digest.assumed
+Files listed in the digest were not found in your $DISTDIR so the existing
+digest entries are assumed to be correct.
+.TP
+.BR digest.disjointed
+The digests were not added to cvs when the matching ebuild had already been
+added.
+.TP
+.BR digest.missing
+Ebuild files were found that do not have a corresponding digest.
+.TP
+.BR digest.notadded
+The digests were found but have not been added to cvs.
+.TP
+.BR digest.stray
+Digest files were found that do not have a corresponding ebuild.
+.TP
+.BR ebuild.disjointed
+The ebuilds were not added to cvs when the matching digest had already been
+added.
+.TP
+.BR ebuild.invalidname
+The ebuild has a filename that is not-parseable by portage.
+.TP
+.BR changelog.missing
+The ChangeLog file was not found.
+.TP
+.BR ebuild.namenomatch
+The euild has a filename that does not have the same name as the parent
+directory.
+.TP
+.BR ebuild.notadded
+The ebuilds were found but have not been added to cvs.
+.TP
+.BR file.executable
+The file has the executable bit set, when it's not needed- check is limited to ebuilds, digests, Manifest, ChangeLog, and metadata.xml.
+.TP
+.BR file.size
+The file's size exceeds 20k, current policy is no files over 20k in a packages files directory.
+.TP
+.BR filedir.missing
+The package lacks a files directory.
+.TP
+.BR DEPEND.bad
+User-visible ebuilds with bad DEPEND settings (matched against *visible* ebuilds).
+In other words, user-visiable ebuilds could not be found to satisfy the DEPEND settings.
+.TP
+.BR RDEPEND.bad
+User-visible ebuilds with bad RDEPEND settings (matched against *visible* ebuilds).
+In other words, user-visiable ebuilds could not be found to satisfy the RDEPEND settings.
+.TP
+.BR DEPEND.badmasked
+Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds)
+In other words, no ebuilds could not be found to satisfy the DEPEND settings.
+.TP
+.BR RDEPEND.badmasked
+Masked ebuilds with RDEPEND settings (matched against *all* ebuilds)
+In other words, no ebuilds could not be found to satisfy the RDEPEND settings.
+.TP
+.BR ebuild.syntax
+An error occured while generating the cache entry. This typically means the ebuild contains syntax error(s).
+.TP
+.BR ebuild.output
+A simple sourcing of the ebuild produces output. This breaks ebuild policy.
+.TP
+.BR KEYWORDS.missing
+The ebuild does not have a KEYWORDS variable.
+.TP
+.BR LICENSE.missing
+The ebuild does not have a LICENSE variable.
+.TP
+.BR DESCRIPTION.missing
+The ebuild does not have a DESCRIPTION variable.
+.TP
+.BR SLOT.missing
+The ebuild does not have a SLOT variable.
+.SH AUTHORS
+Daniel Robbins <drobbins@gentoo.org>
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR emerge (1)
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/repoman.1,v 1.7.2.1 2005/01/30 12:12:26 vapier Exp $
diff --git a/man/rpm.eclass.5 b/man/rpm.eclass.5
new file mode 100644
index 00000000..0e57e3e5
--- /dev/null
+++ b/man/rpm.eclass.5
@@ -0,0 +1,37 @@
+.TH "RPM.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+rpm.eclass \- convienence class for extracting RPM's
+.SH "DESCRIPTION"
+The \fBrpm\fR eclass exists in order to unpack RPM's for you. This
+way developers dont have to keep employing their own tricks just to
+extract the source archives from an RPM. The eclass will define the
+\fBsrc_unpack\fR function and do all the unpacking for you. The
+unpack function will utilize either \fBrpmoffset\fR or \fBrpm2cpio\fR to
+unpack the RPM. If both exist on the system, then \fBrpm2cpio\fR
+will be utilized.
+.SH "VARIABLES"
+.TP
+.B USE_RPMOFFSET_ONLY = \fI"[0|1]"\fR
+If you want to force the RPM extractor to utilize \fBrpmoffset\fR
+even if \fBrpm2cpio\fR is detected, then just set this variable to 1.
+.SH "FUNCTIONS"
+.TP
+.B rpm_unpack \fI"<file to unpack>"\fR
+Unpack an RPM file in the same manner that \fBunpack\fR unpacks any
+other archive. The contents of the RPM will be extracted to \fB${WORKDIR}\fR.
+.TP
+.B rpm_src_unpack
+This replacement for \fBsrc_unpack\fR will go through \fB${A}\fR and
+unpack all the files. If the file is an RPM, then \fBrpm_unpack\fR
+will be called. Otherwise the default \fBunpack\fR function will be
+utilized.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/rpm.eclass
+.SH "AUTHORS"
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/rpm.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/ruby.eclass.5 b/man/ruby.eclass.5
new file mode 100644
index 00000000..cc41fb17
--- /dev/null
+++ b/man/ruby.eclass.5
@@ -0,0 +1,47 @@
+.TH RUBY.ECLASS 5 "Nov 2004" "Portage 2.0.51" portage
+.SH NAME
+ruby.eclass \- functions to ease installation of Ruby software
+.SH DESCRIPTION
+The \fBruby\fR eclass provides an interface designed to ease the installation
+and integration of Ruby software.
+.SH VARIABLES
+.TP
+.B RUBY = \fI"/usr/bin/ruby"\fR
+Defines the location of the Ruby binary. Defaults to '/usr/bin/ruby'.
+.TP
+.B USE_RUBY = \fI"ruby18"\fR
+Defines a white-space delimited list of supported Ruby versions. This variable
+can be set to "any" if the ebuild only installs version independant files.
+Possible values for this variable include \fBany\fR, \fBruby16\fR, \fBruby18\fR,
+and \fBruby19\fR.
+.TP
+.B RUBY_ECONF = \fI"--with-foo"\fR
+Defines any extra arguments to pass to econf.
+.TP
+.B PATCHES = \fI"foo.patch *.diff"\fR
+Defines a white-space delimited list of patches that should be applied. In
+addition to literal filenames, globbing may also be used.
+.SH FUNCTIONS
+.TP
+.B ruby_einstall
+Default einstall that executes standard Ruby installation scripts in addition
+to installing all .rb files into the local Ruby site directory.
+.TP
+.B erubydoc
+Installs documentation, HTML, and examples into /usr/share/doc/\fB${PF}\fR.
+.TP
+.B ruby_src_compile
+Default src_compile that simply executes \fBruby_econf\fR and \fBruby_emake\fR.
+.TP
+.B ruby_src_install
+Default src_install that simply runs \fBruby_einstall\fR and \fBerubydoc\fR.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/ruby.eclass
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/ruby.eclass.5,v 1.1.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/ssl-cert.eclass.5 b/man/ssl-cert.eclass.5
new file mode 100644
index 00000000..4f6b2baa
--- /dev/null
+++ b/man/ssl-cert.eclass.5
@@ -0,0 +1,54 @@
+.TH "SSL-CERT.ECLASS" "5" "Oct 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+ssl-cert.eclass \- provides common SSL certificates installation routines
+.SH "DESCRIPTION"
+The \fBssl-cert\fR eclass contains a function used to generate and
+install SSL certificates and related files for testing and initial
+configuration purposes of TLS/SSL compatible services.
+.SH "VARIABLES"
+.TP
+\fBSSL_DAYS =\fR \fI"730"\fR (2 years)
+The generated certificate will be expired after this many days.
+.TP
+\fBSSL_BITS =\fR \fI"1024"\fR
+The number of bits used for the certificate keys.
+.TP
+\fBSSL_COUNTRY =\fR \fI"US"\fR
+The country (code only) for the generated certificate.
+.TP
+\fBSSL_STATE =\fR \fI"California"\fR
+The state (no abbreviation) for the generated certificate.
+.TP
+\fBSSL_LOCALITY =\fR \fI"Santa Barbara"\fR
+The locality (city) name for the generated certificate.
+.TP
+\fBSSL_ORGANIZATION =\fR \fI"SSL Server"\fR
+The organization (business) name for the generated certificate.
+.TP
+\fBSSL_UNIT =\fR \fI"For Testing Purposes Only"\fR
+The organizational unit (department) name for the generated certificate.
+.TP
+\fBSSL_COMMONNAME =\fR \fI"localhost"\fR
+The hostname (FQDN) for the generated certificate.
+.TP
+\fBSSL_EMAIL =\fR \fI"root@localhost"\fR
+The technical contact (email address) for the generated certificate.
+.SH "FUNCTIONS"
+.TP
+.B docert \fI<cert1>\fR \fI[cert2 ...]\fR
+This function will generate and install the requested certificates into
+the current \fB${INSDESTTREE}\fR location. For example:
+.br
+\fBinsinto\fR \fI/etc/ssl/server\fR
+.br
+\fBdocert\fR \fImail\fR \fIimap\fR || die "Error creating certificates"
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/ssl-cert.eclass
+.SH "AUTHORS"
+Max Kalika <max@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/ssl-cert.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/stardict.eclass.5 b/man/stardict.eclass.5
new file mode 100644
index 00000000..c2a7e7d3
--- /dev/null
+++ b/man/stardict.eclass.5
@@ -0,0 +1,34 @@
+.TH "STARDICT.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+startdict.eclass \- convienence class to do stardict dictionary installations
+.SH "DESCRIPTION"
+The \fBstartdict\fR eclass contains appropriate variables and functions
+to quickly make ebuild's for stardictionaries. The eclass will define
+\fBsrc_compile\fR and \fBsrc_install\fR functions for you. All you
+need to do is to set the \fBDICT_SUFFIX\fR, \fBDICT_P\fR, \fBFROM_LANG\fR,
+and \fBTO_LANG\fR variables before inheriting the eclass.
+.SH "VARIABLES"
+.TP
+.B FROM_LANG = \fI"From this language"\fR
+What language is the dictionary translating from? If you have an
+English to German dictionary, this variable would be set to 'English'.
+.TP
+.B TO_LANG = \fI"To this language"\fR
+What language is the dictionary translating to? If you have an
+English to German dictionary, this variable would be set to 'German'.
+.TP
+.B DICT_PREFIX = \fI"SRC_URI prefix, like 'dictd_www.mova.org_'"\fR
+SRC_URI prefix, like "dictd_www.mova.org_".
+.TP
+.B DICT_SUFFIX = \fI"SRC_URI after the prefix"\fR
+SRC_URI after the prefix.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/stardict.eclass
+.SH "AUTHORS"
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/stardict.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/subversion.eclass.5 b/man/subversion.eclass.5
new file mode 100644
index 00000000..ddc2b5df
--- /dev/null
+++ b/man/subversion.eclass.5
@@ -0,0 +1,59 @@
+.TH SUBVERSION.ECLASS 5 "Nov 2004" "Portage 2.0.51" portage
+.SH NAME
+subversion.eclass \- provides subversion fetching functions
+.SH DESCRIPTION
+The \fBsubversion\fR eclass provides functions that enable the ebuild author
+to create 'live' ebuilds that fetch the program's sources from a subversion
+repository.
+.br
+
+\fBNOTE\fR: At the very minimum, the \fBsubversion\fR eclass requires the
+\fBESVN_REPO_URI\fR variable to be set (see below).
+.SH VARIABLES
+.TP
+.B "ESVN_REPO_URI" = \fI"svn://foo/bar/trunk"\fR
+This variable sets the URI from which the sources will be fetched. The
+\fBsubversion\fR eclass supports fetching from the following protocols:
+\fIhttp\fR, \fIhttps\fR, and \fIsvn\fR. This variable is required to be set.
+.TP
+.B "ESVN_STORE_DIR" = \fI"${DISTDIR}/svn-src"\fB
+This variable defines the location in which the fetched sources will be kept.
+The default value is '${DISTDIR}/svn-src' and should be sufficient in most
+cases.
+.TP
+.B "ESVN_FETCH_CMD" = \fI"svn checkout"\fB
+This variable defines the command used for initial checkout and defaults to 'svn checkout'.
+.TP
+.B "ESVN_UPDATE_CMD" = \fI"svn update"\fB
+This variable defines the command used for updating sources and defaults to 'svn update'.
+.TP
+.B "ESVN_PROJECT" = \fI"foobar"\fB
+This variable defines the name of the project and defaults to '${PN/-svn}'.
+.TP
+.B "ESVN_BOOTSTRAP" = \fI"autogen.sh"\fB
+This variable defines the name of the bootstrap script to execute in
+preparation for the build process. This variable is empty by default. Note:
+"./" is automatically prepended, so it is unnecessary for the ebuild author to
+do so.
+.TP
+.B "ESVN_PATCHES" = \fI"foo.patch *.diff"\fB
+This variable defines a list of patches to apply prior to fetching the sources.
+In addition to literal filenames, you may also use globbing such as *.diff.
+This variable is empty by default.
+.SH FUNCTIONS
+.TP
+.B subversion_src_unpack
+The default \fBsrc_unpack\fR provided by the \fBsubversion\fR eclass simply
+fetches the program's sources from the URI specified by \fBESVN_REPO_URI\fR,
+applies any patches specified by \fBESVN_PATCHES\fR, and then executes the
+bootstrap script specified by \fBESVN_BOOTSTRAP\fR.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/subversion.eclass
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/subversion.eclass.5,v 1.1.2.3 2005/05/10 11:30:32 swegener Exp $
diff --git a/man/tla.eclass.5 b/man/tla.eclass.5
new file mode 100644
index 00000000..53df4fee
--- /dev/null
+++ b/man/tla.eclass.5
@@ -0,0 +1,52 @@
+.TH TLA.ECLASS 5 "Nov 2004" "Portage 2.0.51" portage
+.SH NAME
+tla.eclass \- provides generic tla fetching functions
+.SH DESCRIPTION
+The \fBtla\fR eclass provides an interface to easily allow ebuild authors to
+create 'live' tla ebuilds that fetch their sources from a tla repository.
+.SH VARIABLES
+.TP
+.B ETLA_TLA_CMD = \fI"tla"\fR
+Defines tla executable. Defaults to 'tla'.
+.TP
+.B ETLA_GET_CMD = \fI"get"\fR
+Defines tla get option. Defaults to 'get'.
+.TP
+.B ETLA_UPDATE_CMD = \fI"replay"\fR
+Defines tla update option. Defaults to 'replay'.
+.TP
+.B ETLA_TOP_DIR = \fI"${DISTDIR}/tla-src"\fR
+Defines location where fetched sources will be kept. Defaults to '${DISTDIR}/tla-src'.
+.TP
+.B ETLA_VERSION = \fI"foo@bar.com--archive-name/category--branch--version"\fR
+Defines tla version in the above format. This variable will be passed as the
+argument to a tla subcommand such as get, replay, etc.
+.TP
+.B ETLA_CACHE_DIR = \fI"${ELTA_VERSION}"\fR
+Defines the location where the version shall be cached. This location is
+relative to \fBETLA_TOP_DIR\fR. Defaults to '\fBETLA_VERSION\fR'.
+.TP
+.B ETLA_ARCHIVES
+Defines a whitespace-delimited list of significant archive URI's. This variable
+should at least include the URI of the archive that the wanted version is stored
+in.
+.TP
+.B ETLA_CLEAN
+Defines whether or not to fetch a clean copy of sources if there is already a
+working copy available. If set, the working copy will be removed and a fresh
+copy will be fetched. Otherwise, the working copy will just be updated (via
+\fBETLA_UPDATE_CMD\fR). This variable is unset by default.
+.SH FUNCTIONS
+.TP
+.B tla_src_unpack
+Default src_unpack that fetches the sources and places them in \fB${WORKDIR}\fR/\fB${P}\fR.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/tla.eclass
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/tla.eclass.5,v 1.1.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/toolchain-funcs.eclass.5 b/man/toolchain-funcs.eclass.5
new file mode 100644
index 00000000..481ce138
--- /dev/null
+++ b/man/toolchain-funcs.eclass.5
@@ -0,0 +1,112 @@
+.TH "TOOLCHAIN-FUNCS.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+toolchain-funcs.eclass \- functions to get commonly needed info about the
+toolchain (binutils/gcc/glibc/etc...)
+.SH "DESCRIPTION"
+The \fBtoolchain-funcs\fR eclass contains a suite of functions that are
+used to glean information about the toolchain that is used to compile.
+This allows developers to worry about gcc specs rather than figuring
+out how to find the specs in the first place.
+.SH "TOOL FUNCTIONS"
+.TP
+.B tc-getAR
+Returns the name of the binutils archiver. Usually 'ar'.
+.TP
+.B tc-getAS
+Returns the name of the assembler. Usually 'as'.
+.TP
+.B tc-getBUILD_CC
+Returns the name of the compiler for the build system.
+Useful only when you have to compile and run a utility while
+building the package.
+.TP
+.B tc-getCC
+Returns the name of the C compiler binary. Usually 'gcc'.
+.TP
+.B tc-getCXX
+Returns the name of the C++ compiler binary. Usually 'g++'.
+.TP
+.B tc-getF77
+Returns the name of the fortran compiler.
+.TP
+.B tc-getGCJ
+Returns the name of the java compiler. Usually 'gcj'.
+.TP
+.B tc-getLD
+Returns the name of the linker. Usually 'ld'.
+.TP
+.B tc-getNM
+Returns the name of the symbol/object thingy. Usually 'nm'.
+.TP
+.B tc-getRANLIB
+Returns the name of the archiver indexer. Usually 'ranlib'.
+.SH "MISC FUNCTIONS"
+.TP
+\fBtc-arch\fR [\fITARGET\fR]
+Echo the portage $ARCH that the current toolchain represents.
+Basically this is a drop-in replacment for $ARCH usage. If no
+\fITARGET\fR is specified, then CHOST will be used.
+.TP
+\fBtc-arch-kernel\fR [\fITARGET\fR]
+Echo the kernel $ARCH that the current toolchain represents. If no
+\fITARGET\fR is specified, then CHOST will be used.
+.TP
+\fBtc-endian\fR [\fITARGET\fR]
+Echo 'little' or 'big' based upon what the current toolchain represents.
+If no \fITARGET\fR is specified, then CHOST will be used.
+.TP
+\fBtc-export\fR <\fBlist of variables\fR>
+Quickly export \fBlist of variables\fR to the environment. Much easier
+than exporting each idividual variable at a time.
+
+For example: \fBtc-export\fR CC CXX AR RANLIB
+.TP
+.B tc-is-cross-compiler
+Return shell true/false based upon whether the current building
+setup is for a cross compiler.
+.SH "VERSION FUNCTIONS"
+.TP
+.B gcc-fullversion
+Returns the version as by `$CC -dumpversion`.
+.br
+GCC \fI2.95.3\fR will return \fI2.95.3\fR
+.br
+GCC \fI3.2.1\fR will return \fI3.2.1\fR
+.TP
+.B gcc-version
+Returns the version, but only the <major>.<minor>.
+.br
+GCC \fI2.95\fR.3 will return \fI2.95\fR
+.br
+GCC \fI3.2\fR.1 will return \fI3.2\fR
+.TP
+.B gcc-major-version
+Returns the Major version.
+.br
+GCC \fI2\fR.95.3 will return \fI2\fR
+.br
+GCC \fI3\fR.2.1 will return \fI3\fR
+.TP
+.B gcc-minor-version
+Returns the Minor version.
+.br
+GCC 2.\fI95\fR.3 will return \fI95\fR
+.br
+GCC 3.\fI2\fR.1 will return \fI2\fR
+.TP
+.B gcc-micro-version
+Returns the Micro version.
+.br
+GCC 2.95.\fI3\fR will return \fI3\fR
+.br
+GCC 3.2.\fI1\fR will return \fI1\fR
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.SH "FILES"
+.BR /usr/portage/eclass/toolchain-funcs.eclass
+.SH "AUTHORS"
+Mike Frysinger <vapier@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/toolchain-funcs.eclass.5,v 1.1.2.2 2005/01/15 00:19:23 vapier Exp $
diff --git a/man/versionator.eclass.5 b/man/versionator.eclass.5
new file mode 100644
index 00000000..bded105f
--- /dev/null
+++ b/man/versionator.eclass.5
@@ -0,0 +1,53 @@
+.TH VERSIONATOR.ECLASS 5 "Nov 2004" "Portage 2.0.51" portage
+.SH NAME
+versionator.eclass \- provides functions for easy manipulation of versions
+.SH DESCRIPTION
+The \fBversionator\fR eclass provides functions to ease manipulation of
+software versions. The most common use of this eclass is for manipulation of
+the \fB${PV}\fR variable (and saving the result in a variable such as
+\fB${MY_PV}\fR).
+.SH FUNCTIONS
+\fBNOTE\fR: the following functions all operate on a version string (denoted
+as \fIPV\fR in this manual page), which defaults to \fB${PV}\fR if omitted.
+See the eclass for example version strings and their respective results.
+.TP
+.B get_all_version_components \fI< PV >\fR
+Splits PV into its component parts.
+.TP
+.B get_version_components \fI< PV >\fR
+Splits PV into its component parts, ignoring '.', '-', and '_'.
+.TP
+.B get_major_version \fI< PV >\fR
+Retrieves major version from PV.
+.TP
+.B get_version_component_range \fI[ RANGE ] < PV >\fR
+Retrieves a component or range of components, RANGE, from PV. RANGE may be
+a single number for a particular component, a range such as 1-2 for a range
+of components, or a range such as 2- for that component and everything after it.
+.TP
+.B get_after_major_version \fI< PV >\fR
+Retrieves everything after the major version and its separator (if present).
+.TP
+.B replace_version_separator \fI[ N ] [ SEP ] < PV >\fR
+Replaces the Nth separator of PV with separator, SEP. If N is a character
+literal (eg. '-'), the first separator of this kind is replaced.
+.TP
+.B replace_all_version_separators \fI[ SEP ] < PV >\fR
+Replaces all version separators in PV with separator, SEP.
+.TP
+.B delete_version_separator \fI[ N ] < PV >\fR
+Deletes the Nth separator of PV. If N is a character literal (eg. '-'), the first
+separator of this kind is deleted.
+.TP
+.B delete_all_version_separators \fI<PV>\fR
+Deletes all version separators in PV.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.BR /usr/portage/eclass/versionator.eclass
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/versionator.eclass.5,v 1.1.2.4 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/vim-plugin.eclass.5 b/man/vim-plugin.eclass.5
new file mode 100644
index 00000000..0960345e
--- /dev/null
+++ b/man/vim-plugin.eclass.5
@@ -0,0 +1,86 @@
+.TH VIM-PLUGIN.ECLASS 5 "Dec 2004" "Portage 2.0.51" portage
+.SH NAME
+vim-plugin.eclass \- functions to ease installation of Vim plugins
+.SH DESCRIPTION
+The \fBvim-plugin\fR eclass provides functions meant to simplify the
+installation of Vim plugins into a version-independent directory,
+/usr/share/vim/vimfiles.
+.SH VARIABLES
+.TP
+.B VIM_PLUGIN_HELPFILES
+Defines a white-space delimited list of help files, used soley for informing
+the user how to access them within Vim.
+.TP
+.B VIM_PLUGIN_HELPTEXT
+Defines help text to display. Used only if \fBVIM_PLUGIN_HELPFILES\fR is unset.
+.TP
+.B VIM_PLUGIN_HELPURI
+Defines a URI where on-line plugin documentation is available. This variable
+is only used if \fBVIM_PLUGIN_HELPFILES\fR and \fBVIM_PLUGIN_HELPTEXT\fR are
+unset.
+.TP
+.B VIM_PLUGIN_MESSAGES
+Defines a white-space delimited list of settings that the Vim plugin makes use
+of. Currently, only 'filetype' is supported; any other specified settings will
+be ignored.
+.SH FUNCTIONS
+.TP
+.B update_vim_afterscripts
+Creates scripts in /usr/share/vim/vimfiles/after that are comprised of the
+snippets located in /usr/share/vim/vimfiles/after/*/*.vim.d. In addition,
+any stale scripts that were previously generated by this function are removed.
+.TP
+.B display_vim_plugin_help
+Displays a message containing plugin help information. This function checks
+the variables \fBVIM_PLUGIN_HELPFILES\fR, \fBVIM_PLUGIN_HELPTEXT\fR, and
+\fBVIM_PLUGIN_HELPURI\fR (in that order) and displays the first one that is
+defined. In addition, any setting-specific messages that correspond to
+settings listed in \fBVIM_PLUGIN_MESSAGES\fR will be displayed.
+.TP
+.B vim-plugin_src_install
+Default src_install. Installs plugin documentation prior to installing the
+entire contents of \fB${S}\fR to /usr/share/vim/vimfiles.
+.TP
+.B vim-plugin_pkg_postinst
+Default pkg_postinst that updates Vim helptags (see \fBupdate_vim_helptags\fR
+in vim-doc.eclass), updates after scripts, and calls \fBdisplay_vim_plugin_help\fR.
+.TP
+.B vim-plugin_pkg_postrm
+Default pkg_postrm that updates Vim helptags (see \fBupdate_vim_helptags\fR
+in vim-doc.eclass), updates after scripts, and removes any empty directories
+in /usr/share/vim/vimfiles.
+.SH PACKAGING
+In general, tarballs for plugins cannot be used directly because of vim.org's
+idiosyncratic download system. Instead, a Gentoo-specific tarball must be made
+with the following format for contents:
+
+.nf
+ packagename-version/
+ packagename-version/doc/
+ packagename-version/doc/whatever.txt
+ packagename-version/plugin/
+ packagename-version/plugin/whatever.vim
+ packagename-version/syntax/
+ packagename-version/syntax/whatever.vim
+.fi
+.SH PACKAGE NAMING CONVENTIONS
+Where possible, the upstream script name should be used as the package name.
+For packages which provide syntax or filetype files, the name should be suffixed
+with "-syntax" (for example, "app-vim/gentoo-syntax", "app-vim/fluxbox-syntax",
+"app-vim/selinux-syntax").
+.SH PACKAGE VARIABLE CONVENTIONS
+The canonical form for the HOMEPAGE variable for vim.org scripts is
+http://www.vim.org/scripts/script.php?script_id=123.
+.SH REPORTING BUGS
+Please report bugs via http://bugs.gentoo.org/
+.SH SEE ALSO
+.BR ebuild (5)
+.SH FILES
+.nf
+.B /usr/portage/eclass/vim-plugin.eclass
+.B /usr/portage/eclass/vim-doc.eclass
+.fi
+.SH AUTHORS
+Aaron Walker <ka0ttic@gentoo.org>
+.SH CVS HEADER
+$Header: /var/cvsroot/gentoo-src/portage/man/vim-plugin.eclass.5,v 1.1.2.2 2005/01/15 00:19:36 vapier Exp $
diff --git a/man/vim.eclass.5 b/man/vim.eclass.5
new file mode 100644
index 00000000..24ff42c1
--- /dev/null
+++ b/man/vim.eclass.5
@@ -0,0 +1,56 @@
+.TH "VIM.ECLASS" "5" "Jun 2003" "Portage 2.0.51" "portage"
+.SH "NAME"
+vim.eclass \- common build routines for vim-core, vim and gvim
+.SH "DESCRIPTION"
+The \fBvim\fR eclass contains a suite of functions that are used to
+build \fBvim-core\fR, \fBvim\fR and \fBgvim\fR. The vim-core ebuild
+contains the common files installed in /usr/share/vim, /usr/share/doc
+and /etc/vim, as well as the binaries xxd and vimtutor. The vim
+ebuild contains the terminal-based version of vim. The gvim ebuild
+contains the graphical version of vim. All three of these are built
+from common source, common patches and using mostly-common configure
+options.
+.P
+There are no functions to define in an ebuild using \fBvim.eclass\fR
+because the eclass does all the unpacking, compilation and
+installation.
+.SH "VARIABLES"
+.TP
+.B VIM_VERSION = \fI"version string"\fR
+This variable is important because the ebuild version (for example
+6.2_pre5) corresponds to a vim version (for example 6.2e) but there is
+no way to make that jump without help from the ebuild author.
+Historically there was a method in the vim.eclass to calculate the vim
+version from the ebuild version, but that meant that the ebuild author
+had to make sure the ebuild was correctly versioned each time. To
+avoid that headache, it became easier to simply specify
+\fBVIM_VERSION\fR in the ebuild itself.
+.TP
+.B VIM_GENTOO_PATCHES = \fI"filename"\fR
+The filename of the Gentoo patches to apply. It's not always
+necessary to update the Gentoo patches for a new version of vim,
+so this variable separates the ebuild and vim versions from the patch
+tarball version. Take a look at
+\fBvim-6.2.011-gentoo-patches.tar.bz2\fR
+for an example of the patch directory layout.
+.TP
+.B VIM_ORG_PATCHES = \fI"filename"\fR
+The filename of the vim patches to apply. This is a tarball of
+patches from \fBftp://ftp.vim.org/pub/vim/patches/\fR which apply to
+the current version. See \fBvim-6.2.011-patches.tar.bz2\fR for an
+example of the vim.org patch tarballs.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "SEE ALSO"
+.BR ebuild (5)
+.BR vim (1)
+.SH "FILES"
+.BR /usr/portage/eclass/vim.eclass
+.SH "AUTHORS"
+Aron Griffis <agriffis@gentoo.org>
+.br
+Ryan Phillips <rphillips@gentoo.org>
+.br
+Seemant Kulleen <seemant@gentoo.org>
+.SH "CVS HEADER"
+$Header: /var/cvsroot/gentoo-src/portage/man/vim.eclass.5,v 1.3.2.1 2005/01/15 00:19:36 vapier Exp $
diff --git a/pym/cvstree.py b/pym/cvstree.py
new file mode 100644
index 00000000..4e883dd7
--- /dev/null
+++ b/pym/cvstree.py
@@ -0,0 +1,295 @@
+# cvstree.py -- cvs tree utilities
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/cvstree.py,v 1.12.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: cvstree.py,v 1.12.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import string,os,time,sys,re
+from stat import *
+
+# [D]/Name/Version/Date/Flags/Tags
+
+def pathdata(entries, path):
+ """(entries,path)
+ Returns the data(dict) for a specific file/dir at the path specified."""
+ mysplit=string.split(path,"/")
+ myentries=entries
+ mytarget=mysplit[-1]
+ mysplit=mysplit[:-1]
+ for mys in mysplit:
+ if myentries["dirs"].has_key(mys):
+ myentries=myentries["dirs"][mys]
+ else:
+ return None
+ if myentries["dirs"].has_key(mytarget):
+ return myentries["dirs"][mytarget]
+ elif myentries["files"].has_key(mytarget):
+ return myentries["files"][mytarget]
+ else:
+ return None
+
+def fileat(entries, path):
+ return pathdata(entries,path)
+
+def isadded(entries, path):
+ """(entries,path)
+ Returns true if the path exists and is added to the cvs tree."""
+ mytarget=pathdata(entries, path)
+ if mytarget:
+ if "cvs" in mytarget["status"]:
+ return 1
+
+ basedir=os.path.dirname(path)
+ filename=os.path.basename(path)
+
+ try:
+ myfile=open(basedir+"/CVS/Entries","r")
+ except IOError:
+ return 0
+ mylines=myfile.readlines()
+ myfile.close()
+
+ rep=re.compile("^\/"+re.escape(filename)+"\/");
+ for x in mylines:
+ if rep.search(x):
+ return 1
+
+ return 0
+
+def findnew(entries,recursive=0,basedir=""):
+ """(entries,recursive=0,basedir="")
+ Recurses the entries tree to find all elements that have been added but
+ have not yet been committed. Returns a list of paths, optionally prepended
+ with a basedir."""
+ if basedir and basedir[-1]!="/":
+ basedir=basedir+"/"
+ mylist=[]
+ for myfile in entries["files"].keys():
+ if "cvs" in entries["files"][myfile]["status"]:
+ if "0" == entries["files"][myfile]["revision"]:
+ mylist.append(basedir+myfile)
+ if recursive:
+ for mydir in entries["dirs"].keys():
+ mylist+=findnew(entries["dirs"][mydir],recursive,basedir+mydir)
+ return mylist
+
+def findchanged(entries,recursive=0,basedir=""):
+ """(entries,recursive=0,basedir="")
+ Recurses the entries tree to find all elements that exist in the cvs tree
+ and differ from the committed version. Returns a list of paths, optionally
+ prepended with a basedir."""
+ if basedir and basedir[-1]!="/":
+ basedir=basedir+"/"
+ mylist=[]
+ for myfile in entries["files"].keys():
+ if "cvs" in entries["files"][myfile]["status"]:
+ if "current" not in entries["files"][myfile]["status"]:
+ if "exists" in entries["files"][myfile]["status"]:
+ if entries["files"][myfile]["revision"]!="0":
+ mylist.append(basedir+myfile)
+ if recursive:
+ for mydir in entries["dirs"].keys():
+ mylist+=findchanged(entries["dirs"][mydir],recursive,basedir+mydir)
+ return mylist
+
+def findmissing(entries,recursive=0,basedir=""):
+ """(entries,recursive=0,basedir="")
+ Recurses the entries tree to find all elements that are listed in the cvs
+ tree but do not exist on the filesystem. Returns a list of paths,
+ optionally prepended with a basedir."""
+ if basedir and basedir[-1]!="/":
+ basedir=basedir+"/"
+ mylist=[]
+ for myfile in entries["files"].keys():
+ if "cvs" in entries["files"][myfile]["status"]:
+ if "exists" not in entries["files"][myfile]["status"]:
+ if "removed" not in entries["files"][myfile]["status"]:
+ mylist.append(basedir+myfile)
+ if recursive:
+ for mydir in entries["dirs"].keys():
+ mylist+=findmissing(entries["dirs"][mydir],recursive,basedir+mydir)
+ return mylist
+
+def findunadded(entries,recursive=0,basedir=""):
+ """(entries,recursive=0,basedir="")
+ Recurses the entries tree to find all elements that are in valid cvs
+ directories but are not part of the cvs tree. Returns a list of paths,
+ optionally prepended with a basedir."""
+ if basedir and basedir[-1]!="/":
+ basedir=basedir+"/"
+ mylist=[]
+
+ #ignore what cvs ignores.
+ for myfile in entries["files"].keys():
+ if "cvs" not in entries["files"][myfile]["status"]:
+ mylist.append(basedir+myfile)
+ if recursive:
+ for mydir in entries["dirs"].keys():
+ mylist+=findunadded(entries["dirs"][mydir],recursive,basedir+mydir)
+ return mylist
+
+def findremoved(entries,recursive=0,basedir=""):
+ """(entries,recursive=0,basedir="")
+ Recurses the entries tree to find all elements that are in flagged for cvs
+ deletions. Returns a list of paths, optionally prepended with a basedir."""
+ if basedir and basedir[-1]!="/":
+ basedir=basedir+"/"
+ mylist=[]
+ for myfile in entries["files"].keys():
+ if "removed" in entries["files"][myfile]["status"]:
+ mylist.append(basedir+myfile)
+ if recursive:
+ for mydir in entries["dirs"].keys():
+ mylist+=findremoved(entries["dirs"][mydir],recursive,basedir+mydir)
+ return mylist
+
+def findall(entries, recursive=0, basedir=""):
+ """(entries,recursive=0,basedir="")
+ Recurses the entries tree to find all new, changed, missing, and unadded
+ entities. Returns a 4 element list of lists as returned from each find*()."""
+
+ if basedir and basedir[-1]!="/":
+ basedir=basedir+"/"
+ mynew = findnew(entries,recursive,basedir)
+ mychanged = findchanged(entries,recursive,basedir)
+ mymissing = findmissing(entries,recursive,basedir)
+ myunadded = findunadded(entries,recursive,basedir)
+ myremoved = findremoved(entries,recursive,basedir)
+ return [mynew, mychanged, mymissing, myunadded, myremoved]
+
+ignore_list = re.compile("(^|/)(RCS(|LOG)|SCCS|CVS(|\.adm)|cvslog\..*|tags|TAGS|\.(make\.state|nse_depinfo)|.*~|(\.|)#.*|,.*|_$.*|.*\$|\.del-.*|.*\.(old|BAK|bak|orig|rej|a|olb|o|obj|so|exe|Z|elc|ln)|core)$")
+def apply_cvsignore_filter(list):
+ x=0
+ while x < len(list):
+ if ignore_list.match(list[x].split("/")[-1]):
+ list.pop(x)
+ else:
+ x+=1
+ return list
+
+def getentries(mydir,recursive=0):
+ """(basedir,recursive=0)
+ Scans the given directory and returns an datadict of all the entries in
+ the directory seperated as a dirs dict and a files dict."""
+ myfn=mydir+"/CVS/Entries"
+ # entries=[dirs, files]
+ entries={"dirs":{},"files":{}}
+ if not os.path.exists(mydir):
+ return entries
+ try:
+ myfile=open(myfn, "r")
+ mylines=myfile.readlines()
+ myfile.close()
+ except SystemExit, e:
+ raise
+ except:
+ mylines=[]
+ for line in mylines:
+ if line and line[-1]=="\n":
+ line=line[:-1]
+ if not line:
+ continue
+ if line=="D": # End of entries file
+ break
+ mysplit=string.split(line, "/")
+ if len(mysplit)!=6:
+ print "Confused:",mysplit
+ continue
+ if mysplit[0]=="D":
+ entries["dirs"][mysplit[1]]={"dirs":{},"files":{},"status":[]}
+ entries["dirs"][mysplit[1]]["status"]=["cvs"]
+ if os.path.isdir(mydir+"/"+mysplit[1]):
+ entries["dirs"][mysplit[1]]["status"]+=["exists"]
+ entries["dirs"][mysplit[1]]["flags"]=mysplit[2:]
+ if recursive:
+ rentries=getentries(mydir+"/"+mysplit[1],recursive)
+ #print rentries.keys()
+ #print entries["files"].keys()
+ #print entries["files"][mysplit[1]]
+ entries["dirs"][mysplit[1]]["dirs"]=rentries["dirs"]
+ entries["dirs"][mysplit[1]]["files"]=rentries["files"]
+ else:
+ # [D]/Name/revision/Date/Flags/Tags
+ entries["files"][mysplit[1]]={}
+ entries["files"][mysplit[1]]["revision"]=mysplit[2]
+ entries["files"][mysplit[1]]["date"]=mysplit[3]
+ entries["files"][mysplit[1]]["flags"]=mysplit[4]
+ entries["files"][mysplit[1]]["tags"]=mysplit[5]
+ entries["files"][mysplit[1]]["status"]=["cvs"]
+ if entries["files"][mysplit[1]]["revision"][0]=="-":
+ entries["files"][mysplit[1]]["status"]+=["removed"]
+
+ for file in apply_cvsignore_filter(os.listdir(mydir)):
+ if file=="CVS":
+ continue
+ if file=="digest-framerd-2.4.3":
+ print mydir,file
+ if os.path.isdir(mydir+"/"+file):
+ if not entries["dirs"].has_key(file):
+ entries["dirs"][file]={"dirs":{},"files":{}}
+ if entries["dirs"][file].has_key("status"):
+ if "exists" not in entries["dirs"][file]["status"]:
+ entries["dirs"][file]["status"]+=["exists"]
+ else:
+ entries["dirs"][file]["status"]=["exists"]
+ elif os.path.isfile(mydir+"/"+file):
+ if file=="digest-framerd-2.4.3":
+ print "isfile"
+ if not entries["files"].has_key(file):
+ entries["files"][file]={"revision":"","date":"","flags":"","tags":""}
+ if entries["files"][file].has_key("status"):
+ if file=="digest-framerd-2.4.3":
+ print "has status"
+ if "exists" not in entries["files"][file]["status"]:
+ if file=="digest-framerd-2.4.3":
+ print "no exists in status"
+ entries["files"][file]["status"]+=["exists"]
+ else:
+ if file=="digest-framerd-2.4.3":
+ print "no status"
+ entries["files"][file]["status"]=["exists"]
+ try:
+ if file=="digest-framerd-2.4.3":
+ print "stat'ing"
+ mystat=os.stat(mydir+"/"+file)
+ mytime=time.asctime(time.gmtime(mystat[ST_MTIME]))
+ if not entries["files"][file].has_key("status"):
+ if file=="digest-framerd-2.4.3":
+ print "status not set"
+ entries["files"][file]["status"]=[]
+ if file=="digest-framerd-2.4.3":
+ print "date:",entries["files"][file]["date"]
+ print "sdate:",mytime
+ if mytime==entries["files"][file]["date"]:
+ entries["files"][file]["status"]+=["current"]
+ if file=="digest-framerd-2.4.3":
+ print "stat done"
+
+ del mystat
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "failed to stat",file
+ print e
+ return
+
+ else:
+ print
+ print "File of unknown type:",mydir+"/"+file
+ print
+ return entries
+
+#class cvstree:
+# def __init__(self,basedir):
+# self.refdir=os.cwd()
+# self.basedir=basedir
+# self.entries={}
+# self.entries["dirs"]={}
+# self.entries["files"]={}
+# self.entries["dirs"][self.basedir]=getentries(self.basedir)
+# self.getrealdirs(self.dirs, self.files)
+# def getrealdirs(self,dirs,files):
+# for mydir in dirs.keys():
+# list = os.listdir(
+
+
diff --git a/pym/dcdialog.py b/pym/dcdialog.py
new file mode 100644
index 00000000..64d39983
--- /dev/null
+++ b/pym/dcdialog.py
@@ -0,0 +1,412 @@
+#
+# Changes and extensions by Carlos Castillo...
+#
+cvs_id_string="$Id: dcdialog.py,v 1.1.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+#
+# Module: dialog.py
+# Copyright (c) 2000 Robb Shecter <robb@acm.org>
+# All rights reserved.
+# This source is covered by the GNU GPL.
+#
+# This module is a Python wrapper around the Linux "dialog" utility
+# by Savio Lam and Stuart Herbert. My goals were to make dialog as
+# easy to use from Python as possible. The demo code at the end of
+# the module is a good example of how to use it. To run the demo,
+# execute:
+#
+# python dialog.py
+#
+# This module has one class in it, "Dialog". An application typically
+# creates an instance of it, and possibly sets the background title option.
+# Then, methods can be called on it for interacting with the user.
+#
+# I wrote this because I want to use my 486-33 laptop as my main
+# development computer (!), and I wanted a way to nicely interact with the
+# user in console mode. There are apparently other modules out there
+# with similar functionality, but they require the Python curses library.
+# Writing this module from scratch was easier than figuring out how to
+# recompile Python with curses enabled. :)
+#
+# One interesting feature is that the menu and selection windows allow
+# *any* objects to be displayed and selected, not just strings.
+#
+# TO DO:
+# Add code so that the input buffer is flushed before a dialog box is
+# shown. This would make the UI more predictable for users. This
+# feature could be turned on and off through an instance method.
+# Drop using temporary files when interacting with 'dialog'
+# (it's possible -- I've already tried :-).
+# Try detecting the terminal window size in order to make reasonable
+# height and width defaults. Hmmm - should also then check for
+# terminal resizing...
+# Put into a package name to make more reusable - reduce the possibility
+# of name collisions.
+#
+# NOTES:
+# there is a bug in (at least) Linux-Mandrake 7.0 Russian Edition
+# running on AMD K6-2 3D that causes core dump when 'dialog'
+# is running with --gauge option;
+# in this case you'll have to recompile 'dialog' program.
+#
+# Modifications:
+# Jul 2000, Sultanbek Tezadov (http://sultan.da.ru)
+# Added:
+# - 'gauge' widget *)
+# - 'title' option to some widgets
+# - 'checked' option to checklist dialog; clicking "Cancel" is now
+# recognizable
+# - 'selected' option to radiolist dialog; clicking "Cancel" is now
+# recognizable
+# - some other cosmetic changes and improvements
+#
+
+import os
+from tempfile import mktemp
+from string import split
+from time import sleep
+
+#
+# Path of the dialog executable
+#
+DIALOG="/usr/bin/dialog"
+
+
+class Dialog:
+ def __init__(self):
+ self.__bgTitle = '' # Default is no background title
+
+
+ def setBackgroundTitle(self, text):
+ self.__bgTitle = '--backtitle "%s"' % text
+
+
+ def __perform(self, cmd):
+ """Do the actual work of invoking dialog and getting the output."""
+ fName = mktemp()
+ rv = os.system('%s %s %s 2> %s' % (DIALOG, self.__bgTitle, cmd, fName))
+ f = open(fName)
+ output = f.readlines()
+ f.close()
+ os.unlink(fName)
+ return (rv, output)
+
+
+ def __perform_no_options(self, cmd):
+ """Call dialog w/out passing any more options. Needed by --clear."""
+ return os.system(DIALOG + ' ' + cmd)
+
+
+ def __handleTitle(self, title):
+ if len(title) == 0:
+ return ''
+ else:
+ return '--title "%s" ' % title
+
+
+ def yesno(self, text, height=10, width=30, title=''):
+ """
+ Put a Yes/No question to the user.
+ Uses the dialog --yesno option.
+ Returns a 1 or a 0.
+ """
+ (code, output) = self.__perform(self.__handleTitle(title) +\
+ '--yesno "%s" %d %d' % (text, height, width))
+ return code == 0
+
+
+ def msgbox(self, text, height=10, width=30, title=''):
+ """
+ Pop up a message to the user which has to be clicked
+ away with "ok".
+ """
+ self.__perform(self.__handleTitle(title) +\
+ '--msgbox "%s" %d %d' % (text, height, width))
+
+
+ def infobox(self, text, height=10, width=30):
+ """Make a message to the user, and return immediately."""
+ self.__perform('--infobox "%s" %d %d' % (text, height, width))
+
+
+ def inputbox(self, text, height=10, width=30, init='', title=''):
+ """
+ Request a line of input from the user.
+ Returns the user's input or None if cancel was chosen.
+ """
+ (c, o) = self.__perform(self.__handleTitle(title) +\
+ '--inputbox "%s" %d %d "%s"' % (text, height, width, init))
+ try:
+ return o[0]
+ except IndexError:
+ if c == 0: # empty string entered
+ return ''
+ else: # canceled
+ return None
+
+
+ def textbox(self, filename, height=20, width=60, title=None):
+ """Display a file in a scrolling text box."""
+ if title is None:
+ title = filename
+ self.__perform(self.__handleTitle(title) +\
+ ' --textbox "%s" %d %d' % (filename, height, width))
+
+
+ def menu(self, text, height=15, width=54, list=[]):
+ """
+ Display a menu of options to the user. This method simplifies the
+ --menu option of dialog, which allows for complex arguments. This
+ method receives a simple list of objects, and each one is assigned
+ a choice number.
+ The selected object is returned, or None if the dialog was canceled.
+ """
+ menuheight = height - 8
+ pairs = map(lambda i, item: (i + 1, item), range(len(list)), list)
+ choices = reduce(lambda res, pair: res + '%d "%s" ' % pair, pairs, '')
+ (code, output) = self.__perform('--menu "%s" %d %d %d %s' %\
+ (text, height, width, menuheight, choices))
+ try:
+ return list[int(output[0]) - 1]
+ except IndexError:
+ return None
+
+ def menu_ext(self, text, height=15, width=54, list=[], list2=[]):
+ """
+ Extended the method above for (string, string) pairs, for GLIS UI
+ """
+ menuheight = height - 8
+ pairs = []
+ for i in range(len(list)):
+ pairs.append((list2[i],list[i]))
+ #pairs = map(lambda i, item: (i + 1, item), range(len(list)), list)
+ choices = reduce(lambda res, pair: res + '%s "%s" ' % pair, pairs, '')
+ (code, output) = self.__perform('--menu "%s" %d %d %d %s' %\
+ (text, height, width, menuheight, choices))
+ try:
+ return output[0]
+ except IndexError:
+ return None
+
+
+ def checklist(self, text, height=15, width=54, list=[], checked=None):
+ """
+ Returns a list of the selected objects.
+ Returns an empty list if nothing was selected.
+ Returns None if the window was canceled.
+ checked -- a list of boolean (0/1) values; len(checked) must equal
+ len(list).
+ """
+ if checked is None:
+ checked = [0]*len(list)
+ menuheight = height - 8
+ triples = map(
+ lambda i, item, onoff, fs=('off', 'on'): (i + 1, item, fs[onoff]),
+ range(len(list)), list, checked)
+ choices = reduce(lambda res, triple: res + '%d "%s" %s ' % triple,
+ triples, '')
+ (c, o) = self.__perform('--checklist "%s" %d %d %d %s' %\
+ (text, height, width, menuheight, choices))
+ try:
+ output = o[0]
+ indexList = map(lambda x: int(x[1:-1]), split(output))
+ objectList = filter(lambda item, list=list, indexList=indexList:
+ list.index(item) + 1 in indexList,
+ list)
+ return objectList
+ except IndexError:
+ if c == 0: # Nothing was selected
+ return []
+ return None # Was canceled
+
+ def checklist_ext(self, text, height=15, width=54, list=[], list2=[], checked=None):
+ """
+ Returns a list of the selected objects.
+ Returns an empty list if nothing was selected.
+ Returns None if the window was canceled.
+ checked -- a list of boolean (0/1) values; len(checked) must equal
+ len(list).
+ """
+ if checked is None:
+ checked = [0]*len(list)
+ menuheight = height - 8
+ triples = []
+ #equally 3 lines, much more readable
+ fs = ('off','on')
+ for i in range(len(list)):
+ triples.append((list2[i],list[i],fs[checked[i]]))
+
+## triples = map(
+## lambda i, item, onoff, fs=('off', 'on'): (i + 1, item, fs[onoff]),
+## range(len(list)), list, checked)
+ choices = reduce(lambda res, triple: res + '%s "%s" %s ' % triple,
+ triples, '')
+ (c, o) = self.__perform('--checklist "%s" %d %d %d %s' %\
+ (text, height, width, menuheight, choices))
+ try:
+ output = o[0]
+ return split(output)
+## indexList = map(lambda x: int(x[1:-1]), split(output))
+## objectList = filter(lambda item, list=list, indexList=indexList:
+## list.index(item) + 1 in indexList,
+## list)
+## return objectList
+ except IndexError:
+ if c == 0: # Nothing was selected
+ return []
+ return None # Was canceled
+
+
+ def radiolist(self, text, height=15, width=54, list=[], selected=0):
+ """
+ Return the selected object.
+ Returns empty string if no choice was selected.
+ Returns None if window was canceled.
+ selected -- the selected item (must be between 1 and len(list)
+ or 0, meaning no selection).
+ """
+ menuheight = height - 8
+ triples = map(lambda i, item: (i + 1, item, 'off'),
+ range(len(list)), list)
+ if selected:
+ i, item, tmp = triples[selected - 1]
+ triples[selected - 1] = (i, item, 'on')
+ choices = reduce(lambda res, triple: res + '%d "%s" %s ' % triple,
+ triples, '')
+ (c, o) = self.__perform('--radiolist "%s" %d %d %d %s' %\
+ (text, height, width, menuheight, choices))
+ try:
+ return list[int(o[0]) - 1]
+ except IndexError:
+ if c == 0:
+ return ''
+ return None
+
+
+
+ def clear(self):
+ """
+ Clear the screen. Equivalent to the dialog --clear option.
+ """
+ self.__perform_no_options('--clear')
+
+
+ def scrollbox(self, text, height=20, width=60, title=''):
+ """
+ This is a bonus method. The dialog package only has a function to
+ display a file in a scrolling text field. This method allows any
+ string to be displayed by first saving it in a temp file, and calling
+ --textbox.
+ """
+ fName = mktemp()
+ f = open(fName, 'w')
+ f.write(text)
+ f.close()
+ self.__perform(self.__handleTitle(title) +\
+ '--textbox "%s" %d %d' % (fName, height, width))
+ os.unlink(fName)
+
+
+ def gauge_start(self, perc=0, text='', height=8, width=54, title=''):
+ """
+ Display gauge output window.
+ Gauge normal usage (assuming that there is an instace of 'Dialog'
+ class named 'd'):
+ d.gauge_start()
+ # do something
+ d.gauge_iterate(10) # passed throgh 10%
+ # ...
+ d.gauge_iterate(100, 'any text here') # work is done
+ d.stop_gauge() # clean-up actions
+ """
+ cmd = self.__handleTitle(title) +\
+ '--gauge "%s" %d %d %d' % (text, height, width, perc)
+ cmd = '%s %s %s 2> /dev/null' % (DIALOG, self.__bgTitle, cmd)
+ self.pipe = os.popen(cmd, 'w')
+ #/gauge_start()
+
+
+ def gauge_iterate(self, perc, text=''):
+ """
+ Update percentage point value.
+
+ See gauge_start() function above for the usage.
+ """
+ if text:
+ text = 'XXX\n%d\n%s\nXXX\n' % (perc, text)
+ else:
+ text = '%d\n' % perc
+ self.pipe.write(text)
+ self.pipe.flush()
+ #/gauge_iterate()
+
+
+ def gauge_stop(self):
+ """
+ Finish previously started gauge.
+
+ See gauge_start() function above for the usage.
+ """
+ self.pipe.close()
+ #/gauge_stop()
+
+
+
+#
+# DEMO APPLICATION
+#
+if __name__ == '__main__':
+ """
+ This demo tests all the features of the class.
+ """
+ d = Dialog()
+ d.setBackgroundTitle('dialog.py demo')
+
+ d.infobox(
+ "One moment... Just wasting some time here to test the infobox...")
+ sleep(3)
+
+ if d.yesno("Do you like this demo?"):
+ d.msgbox("Excellent! Here's the source code:")
+ else:
+ d.msgbox("Send your complaints to /dev/null")
+
+ d.textbox("dialog.py")
+
+ name = d.inputbox("What's your name?", init="Snow White")
+ fday = d.menu("What's your favorite day of the week?",
+ list=["Monday", "Tuesday", "Wednesday", "Thursday",
+ "Friday (The best day of all)", "Saturday", "Sunday"])
+ food = d.checklist("What sandwich toppings do you like?",
+ list=["Catsup", "Mustard", "Pesto", "Mayonaise", "Horse radish",
+ "Sun-dried tomatoes"], checked=[0,0,0,1,1,1])
+ sand = d.radiolist("What's your favorite kind of sandwich?",
+ list=["Hamburger", "Hotdog", "Burrito", "Doener", "Falafel",
+ "Bagel", "Big Mac", "Whopper", "Quarter Pounder",
+ "Peanut Butter and Jelly", "Grilled cheese"], selected=4)
+
+ # Prepare the message for the final window
+ bigMessage = "Here are some vital statistics about you:\n\nName: " + name +\
+ "\nFavorite day of the week: " + fday +\
+ "\nFavorite sandwich toppings:\n"
+ for topping in food:
+ bigMessage = bigMessage + " " + topping + "\n"
+ bigMessage = bigMessage + "Favorite sandwich: " + str(sand)
+
+ d.scrollbox(bigMessage)
+
+ #<># Gauge Demo
+ d.gauge_start(0, 'percentage: 0', title='Gauge Demo')
+ for i in range(1, 101):
+ if i < 50:
+ msg = 'percentage: %d' % i
+ elif i == 50:
+ msg = 'Over 50%'
+ else:
+ msg = ''
+ d.gauge_iterate(i, msg)
+ sleep(0.1)
+ d.gauge_stop()
+ #<>#
+
+ d.clear()
diff --git a/pym/dispatch_conf.py b/pym/dispatch_conf.py
new file mode 100644
index 00000000..27d73712
--- /dev/null
+++ b/pym/dispatch_conf.py
@@ -0,0 +1,162 @@
+# archive_conf.py -- functionality common to archive-conf and dispatch-conf
+# Copyright 2003-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/dispatch_conf.py,v 1.3.2.3 2005/04/29 03:37:30 jstubbs Exp $
+cvs_id_string="$Id: dispatch_conf.py,v 1.3.2.3 2005/04/29 03:37:30 jstubbs Exp $"[5:-2]
+
+# Library by Wayne Davison <gentoo@blorf.net>, derived from code
+# written by Jeremy Wohl (http://igmus.org)
+
+from stat import *
+import os, sys, commands, shutil
+
+sys.path = ["/usr/lib/portage/pym"]+sys.path
+import portage
+
+RCS_BRANCH = '1.1.1'
+RCS_LOCK = 'rcs -ko -M -l'
+RCS_PUT = 'ci -t-"Archived config file." -m"dispatch-conf update."'
+RCS_GET = 'co'
+RCS_MERGE = 'rcsmerge -p -r' + RCS_BRANCH + ' %s >%s'
+
+DIFF3_MERGE = 'diff3 -mE %s %s %s >%s'
+
+def read_config(mandatory_opts):
+ try:
+ opts = portage.getconfig('/etc/dispatch-conf.conf')
+ except:
+ opts = None
+
+ if not opts:
+ print >> sys.stderr, 'dispatch-conf: Error reading /etc/dispatch-conf.conf; fatal'
+ sys.exit(1)
+
+ for key in mandatory_opts:
+ if not opts.has_key(key):
+ if key == "merge":
+ opts["merge"] = "sdiff --suppress-common-lines --output=%s %s %s"
+ else:
+ print >> sys.stderr, 'dispatch-conf: Missing option "%s" in /etc/dispatch-conf.conf; fatal' % (key,)
+
+ if not os.path.exists(opts['archive-dir']):
+ os.mkdir(opts['archive-dir'])
+ elif not os.path.isdir(opts['archive-dir']):
+ print >> sys.stderr, 'dispatch-conf: Config archive dir [%s] must exist; fatal' % (opts['archive-dir'],)
+ sys.exit(1)
+
+ return opts
+
+
+def rcs_archive(archive, curconf, newconf, mrgconf):
+ """Archive existing config in rcs (on trunk). Then, if mrgconf is
+ specified and an old branch version exists, merge the user's changes
+ and the distributed changes and put the result into mrgconf. Lastly,
+ if newconf was specified, leave it in the archive dir with a .dist.new
+ suffix along with the last 1.1.1 branch version with a .dist suffix."""
+
+ try:
+ os.makedirs(os.path.dirname(archive))
+ except:
+ pass
+
+ try:
+ shutil.copy2(curconf, archive)
+ except(IOError, os.error), why:
+ print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+ (curconf, archive, str(why))
+ if os.path.exists(archive + ',v'):
+ os.system(RCS_LOCK + ' ' + archive)
+ os.system(RCS_PUT + ' ' + archive)
+
+ ret = 0
+ if newconf != '':
+ os.system(RCS_GET + ' -r' + RCS_BRANCH + ' ' + archive)
+ has_branch = os.path.exists(archive)
+ if has_branch:
+ os.rename(archive, archive + '.dist')
+
+ try:
+ shutil.copy2(newconf, archive)
+ except(IOError, os.error), why:
+ print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+ (newconf, archive, str(why))
+
+ if has_branch:
+ if mrgconf != '':
+ # This puts the results of the merge into mrgconf.
+ ret = os.system(RCS_MERGE % (archive, mrgconf))
+ mystat = os.lstat(newconf)
+ os.chmod(mrgconf, mystat[ST_MODE])
+ os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
+ os.rename(archive, archive + '.dist.new')
+ return ret
+
+
+def file_archive(archive, curconf, newconf, mrgconf):
+ """Archive existing config to the archive-dir, bumping old versions
+ out of the way into .# versions (log-rotate style). Then, if mrgconf
+ was specified and there is a .dist version, merge the user's changes
+ and the distributed changes and put the result into mrgconf. Lastly,
+ if newconf was specified, archive it as a .dist.new version (which
+ gets moved to the .dist version at the end of the processing)."""
+
+ try:
+ os.makedirs(os.path.dirname(archive))
+ except:
+ pass
+
+ # Archive the current config file if it isn't already saved
+ if os.path.exists(archive) \
+ and len(commands.getoutput('diff -aq %s %s' % (curconf,archive))) != 0:
+ suf = 1
+ while suf < 9 and os.path.exists(archive + '.' + str(suf)):
+ suf += 1
+
+ while suf > 1:
+ os.rename(archive + '.' + str(suf-1), archive + '.' + str(suf))
+ suf -= 1
+
+ os.rename(archive, archive + '.1')
+
+ try:
+ shutil.copy2(curconf, archive)
+ except(IOError, os.error), why:
+ print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+ (curconf, archive, str(why))
+
+ if newconf != '':
+ # Save off new config file in the archive dir with .dist.new suffix
+ try:
+ shutil.copy2(newconf, archive + '.dist.new')
+ except(IOError, os.error), why:
+ print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+ (newconf, archive + '.dist.new', str(why))
+
+ ret = 0
+ if mrgconf != '' and os.path.exists(archive + '.dist'):
+ # This puts the results of the merge into mrgconf.
+ ret = os.system(DIFF3_MERGE % (curconf, archive + '.dist', newconf, mrgconf))
+ mystat = os.lstat(newconf)
+ os.chmod(mrgconf, mystat[ST_MODE])
+ os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
+
+ return ret
+
+
+def rcs_archive_post_process(archive):
+ """Check in the archive file with the .dist.new suffix on the branch
+ and remove the one with the .dist suffix."""
+ os.rename(archive + '.dist.new', archive)
+ if os.path.exists(archive + '.dist'):
+ # Commit the last-distributed version onto the branch.
+ os.system(RCS_LOCK + RCS_BRANCH + ' ' + archive)
+ os.system(RCS_PUT + ' -r' + RCS_BRANCH + ' ' + archive)
+ os.unlink(archive + '.dist')
+ else:
+ # Forcefully commit the last-distributed version onto the branch.
+ os.system(RCS_PUT + ' -f -r' + RCS_BRANCH + ' ' + archive)
+
+
+def file_archive_post_process(archive):
+ """Rename the archive file with the .dist.new suffix to a .dist suffix"""
+ os.rename(archive + '.dist.new', archive + '.dist')
diff --git a/pym/emergehelp.py b/pym/emergehelp.py
new file mode 100644
index 00000000..98a399e4
--- /dev/null
+++ b/pym/emergehelp.py
@@ -0,0 +1,370 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/emergehelp.py,v 1.8.2.2 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: emergehelp.py,v 1.8.2.2 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import os,sys
+from output import bold, turquoise, green
+
+def shorthelp():
+ print
+ print
+ print bold("Usage:")
+ print " "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] [ "+turquoise("ebuildfile")+" | "+turquoise("tbz2file")+" | "+turquoise("dependency")+" ] [ ... ]"
+ print " "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] < "+turquoise("system")+" | "+turquoise("world")+" >"
+ print " "+turquoise("emerge")+" < "+turquoise("--sync")+" | "+turquoise("--metadata")+" | "+turquoise("--info")+" >"
+ print " "+turquoise("emerge")+" "+turquoise("--resume")+" [ "+green("--pretend")+" | "+green("--ask")+" | "+green("--skipfirst")+" ]"
+ print " "+turquoise("emerge")+" "+turquoise("--help")+" [ "+green("system")+" | "+green("config")+" | "+green("sync")+" ] "
+ print bold("Options:")+" "+green("-")+"["+green("abcCdDefhikKlnoOpPsSuUvV")+"] ["+green("--oneshot")+"] ["+green("--newuse")+"] ["+green("--noconfmem")+"]"
+ print " ["+green("--columns")+"] ["+green("--nospinner")+"]"
+ print bold("Actions:")+" [ "+green("--clean")+" | "+green("--depclean")+" | "+green("--inject")+" | "+green("--prune")+" | "+green("--regen")+" | "+green("--search")+" | "+green("--unmerge")+" ]"
+ print
+
+def help(myaction,myopts,havecolor=1):
+ if not havecolor:
+ nocolor()
+ if not myaction and ("--help" not in myopts):
+ shorthelp()
+ print
+ print " For more help try 'emerge --help' or consult the man page."
+ print
+ elif not myaction:
+ shorthelp()
+ print
+ print turquoise("Help (this screen):")
+ print " "+green("--help")+" ("+green("-h")+" short option)"
+ print " Displays this help; an additional argument (see above) will tell"
+ print " emerge to display detailed help."
+ print
+ print turquoise("Actions:")
+ print " "+green("--clean")+" ("+green("-c")+" short option)"
+ print " Cleans the system by removing outdated packages which will not"
+ print " remove functionalities or prevent your system from working."
+ print " The arguments can be in several different formats :"
+ print " * world "
+ print " * system or"
+ print " * 'dependency specification' (in single quotes is best.)"
+ print " Here are a few examples of the dependency specification format:"
+ print " "+bold("binutils")+" matches"
+ print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+ print " "+bold("sys-devel/binutils")+" matches"
+ print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+ print " "+bold(">sys-devel/binutils-2.11.90.0.7")+" matches"
+ print " binutils-2.11.92.0.12.3-r1"
+ print " "+bold(">=sys-devel/binutils-2.11.90.0.7")+" matches"
+ print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+ print " "+bold("<=sys-devel/binutils-2.11.92.0.12.3-r1")+" matches"
+ print " binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+ print
+ print " "+green("--depclean")
+ print " Cleans the system by removing packages that are not associated"
+ print " with explicitly merged packages. Depclean works by creating the"
+ print " full dependency tree from the system list and the world file,"
+ print " then comparing it to installed packages. Packages installed, but"
+ print " not associated with an explicit merge are listed as candidates"
+ print " for unmerging."+turquoise(" WARNING: This can seriously affect your system by")
+ print " "+turquoise("removing packages that may have been linked against, but due to")
+ print " "+turquoise("changes in USE flags may no longer be part of the dep tree. Use")
+ print " "+turquoise("caution when employing this feature.")
+ print
+ print " "+green("--info")
+ print " Displays important portage variables that will be exported to"
+ print " ebuild.sh when performing merges. This information is useful"
+ print " for bug reports and verification of settings. All settings in"
+ print " make.{conf,globals,defaults} and the environment show up if"
+ print " run with the '--verbose' flag."
+ print
+ print " "+green("--metadata")
+ print " Causes portage to process all the metacache files as is normally done"
+ print " on the tail end of an rsync update using "+bold("emerge --sync")+". The"
+ print " processing creates the cache database that portage uses for"
+ print " pre-parsed lookups of package data."
+ print
+ print " "+green("--prune")+" ("+green("-P")+" short option)"
+ print " "+turquoise("WARNING: This action can remove important packages!")
+ print " Removes all but the most recently installed version of a package"
+ print " from your system. This action doesn't verify the possible binary"
+ print " compatibility between versions and can thus remove essential"
+ print " dependencies from your system."
+ print " The argument format is the same as for the "+bold("--clean")+" action."
+ print
+ print " "+green("--regen")
+ print " Causes portage to check and update the dependency cache of all"
+ print " ebuilds in the portage tree. This is not recommended for rsync"
+ print " users as rsync updates the cache using server-side caches."
+ print " Rsync users should simply 'emerge --sync' to regenerate."
+ print
+ print " "+green("--search")+" ("+green("-s")+" short option)"
+ print " searches for matches of the supplied string in the current local"
+ print " portage tree. The search string is a regular expression. Prepending"
+ print " the expression with a '@' will cause the category to be included in"
+ print " the search."
+ print " A few examples:"
+ print " "+bold("emerge search '^kde'")
+ print " list all packages starting with kde"
+ print " "+bold("emerge search 'gcc$'")
+ print " list all packages ending with gcc"
+ print " "+bold("emerge search @^dev-java.*jdk")
+ print " list all available Java JDKs"
+ print
+ print " "+green("--unmerge")+" ("+green("-C")+" short option)"
+ print " "+turquoise("WARNING: This action can remove important packages!")
+ print " Removes all matching packages "+bold("completely")+" from"
+ print " your system. Specify arguments using the dependency specification"
+ print " format described in the "+bold("--clean")+" action above."
+ print
+ print turquoise("Options:")
+ print " "+green("--ask")+" ("+green("-a")+" short option)"
+ print " before performing the merge, display what ebuilds and tbz2s will"
+ print " be installed, in the same format as when using --pretend; then"
+ print " ask whether to continue with the merge or abort. Using --ask is"
+ print " more efficient than using --pretend and then executing the same"
+ print " command without --pretend, as dependencies will only need to be"
+ print " calculated once."
+ print
+ print " "+green("--buildpkg")+" ("+green("-b")+" short option)"
+ print " Tell emerge to build binary packages for all ebuilds processed"
+ print " (in addition to actually merging the packages. Useful for"
+ print " maintainers or if you administrate multiple Gentoo Linux"
+ print " systems (build once, emerge tbz2s everywhere) as well as disaster"
+ print " recovery."
+ print
+ print " "+green("--buildpkgonly")+" ("+green("-B")+" short option)"
+ print " Creates a binary package, but does not merge it to the"
+ print " system. This has the restriction that unsatisfied dependencies"
+ print " must not exist for the desired package as they cannot be used if"
+ print " they do not exist on the system."
+ print
+ print " "+green("--changelog")+" ("+green("-l")+" short option)"
+ print " When pretending, also display the ChangeLog entries for packages"
+ print " that will be upgraded."
+ print
+ print " "+green("--columns")
+ print " Display the pretend output in a tabular form. Versions are"
+ print " aligned vertically."
+ print
+ print " "+green("--debug")+" ("+green("-d")+" short option)"
+ print " Tell emerge to run the ebuild command in --debug mode. In this"
+ print " mode, the bash build environment will run with the -x option,"
+ print " causing it to output verbose debug information print to stdout."
+ print " --debug is great for finding bash syntax errors as providing"
+ print " very verbose information about the dependency and build process."
+ print
+ print " "+green("--deep")+" ("+green("-D")+" short option)"
+ print " When used in conjunction with --update, this flag forces emerge"
+ print " to consider the entire dependency tree of packages, instead of"
+ print " checking only the immediate dependencies of the packages. As an"
+ print " example, this catches updates in libraries that are not directly"
+ print " listed in the dependencies of a package."
+ print
+ print " "+green("--emptytree")+" ("+green("-e")+" short option)"
+ print " Virtually tweaks the tree of installed packages to contain"
+ print " nothing. This is great to use together with --pretend. This makes"
+ print " it possible for developers to get a complete overview of the"
+ print " complete dependency tree of a certain package."
+ print
+ print " "+green("--fetchonly")+" ("+green("-f")+" short option)"
+ print " Instead of doing any package building, just perform fetches for"
+ print " all packages (main package as well as all dependencies.) When"
+ print " used in combination with --pretend all the SRC_URIs will be"
+ print " displayed multiple mirrors per line, one line per file."
+ print
+ print " "+green("--fetch-all-uri")
+ print " Same as --fetchonly except that all package files, including those"
+ print " not required to build the package, will be processed."
+ print
+ print " "+green("--getbinpkg")+" ("+green("-g")+" short option)"
+ print " Using the server and location defined in PORTAGE_BINHOST, portage"
+ print " will download the information from each binary file there and it"
+ print " will use that information to help build the dependency list. This"
+ print " option implies '-k'. (Use -gK for binary-only merging.)"
+ print
+ print " "+green("--getbinpkgonly")+" ("+green("-G")+" short option)"
+ print " This option is identical to -g, as above, except it will not use"
+ print " ANY information from the local machine. All binaries will be"
+ print " downloaded from the remote server without consulting packages"
+ print " existing in the packages directory."
+ print
+ print " "+green("--newuse")
+ print " Tells emerge to include installed packages where USE flags have "
+ print " changed since installation."
+ print
+ print " "+green("--noconfmem")
+ print " Portage keeps track of files that have been placed into"
+ print " CONFIG_PROTECT directories, and normally it will not merge the"
+ print " same file more than once, as that would become annoying. This"
+ print " can lead to problems when the user wants the file in the case"
+ print " of accidental deletion. With this option, files will always be"
+ print " merged to the live fs instead of silently dropped."
+ print
+ print " "+green("--nodeps")+" ("+green("-O")+" short option)"
+ print " Merge specified packages, but don't merge any dependencies."
+ print " Note that the build may fail if deps aren't satisfied."
+ print
+ print " "+green("--noreplace")+" ("+green("-n")+" short option)"
+ print " Skip the packages specified on the command-line that have"
+ print " already been installed. Without this option, any packages,"
+ print " ebuilds, or deps you specify on the command-line *will* cause"
+ print " Portage to remerge the package, even if it is already installed."
+ print " Note that Portage won't remerge dependencies by default."
+ print
+ print " "+green("--nospinner")
+ print " Disables the spinner regardless of terminal type."
+ print
+ print " "+green("--oneshot")
+ print " Emerge as normal, but don't add packages to the world profile."
+ print " This package will only be updated if it is depended upon by"
+ print " another package."
+ print
+ print " "+green("--onlydeps")+" ("+green("-o")+" short option)"
+ print " Only merge (or pretend to merge) the dependencies of the"
+ print " specified packages, not the packages themselves."
+ print
+ print " "+green("--pretend")+" ("+green("-p")+" short option)"
+ print " Instead of actually performing the merge, simply display what"
+ print " ebuilds and tbz2s *would* have been installed if --pretend"
+ print " weren't used. Using --pretend is strongly recommended before"
+ print " installing an unfamiliar package. In the printout, N = new,"
+ print " U = updating, R = replacing, F = fetch restricted, B = blocked"
+ print " by an already installed package, D = possible downgrading,"
+ print " S = slotted install. --verbose causes affecting use flags to be"
+ print " printed out accompanied by a '+' for enabled and a '-' for"
+ print " disabled USE flags."
+ print
+ print " "+green("--quiet")+" ("+green("-q")+" short option)"
+ print " Effects vary, but the general outcome is a reduced or condensed"
+ print " output from portage's displays."
+ print
+ print " "+green("--resume")
+ print " Resumes the last merge operation. Can be treated just like a"
+ print " regular merge as --pretend and other options work along side."
+ print " 'emerge --resume' only returns an error on failure. Nothing to"
+ print " do exits with a message and a success condition."
+ print
+ print " "+green("--searchdesc")+" ("+green("-S")+" short option)"
+ print " Matches the search string against the description field as well"
+ print " the package's name. Take caution as the descriptions are also"
+ print " matched as regular expressions."
+ print " emerge -S html"
+ print " emerge -S applet"
+ print " emerge -S 'perl.*module'"
+ print
+ print " "+green("--skipfirst")
+ print " This option is only valid in a resume situation. It removes the"
+ print " first package in the resume list so that a merge may continue in"
+ print " the presence of an uncorrectable or inconsequential error. This"
+ print " should only be used in cases where skipping the package will not"
+ print " result in failed dependencies."
+ print
+ print " "+green("--tree")+" ("+green("-t")+" short option)"
+ print " Shows the dependency tree using indentation for dependencies."
+ print " The packages are also listed in reverse merge order so that"
+ print " a package's dependencies follow the package. Only really useful"
+ print " in combination with --emptytree, --update or --deep."
+ print
+ print " "+green("--update")+" ("+green("-u")+" short option)"
+ print " Updates packages to the best version available, which may not"
+ print " always be the highest version number due to masking for testing"
+ print " and development. This will also update direct dependencies which"
+ print " may not what you want. In general use this option only in combi-"
+ print " nation with the world or system target."
+ print
+ print " "+green("--usepkg")+" ("+green("-k")+" short option)"
+ print " Tell emerge to use binary packages (from $PKGDIR) if they are"
+ print " available, thus possibly avoiding some time-consuming compiles."
+ print " This option is useful for CD installs; you can export"
+ print " PKGDIR=/mnt/cdrom/packages and then use this option to have"
+ print " emerge \"pull\" binary packages from the CD in order to satisfy"
+ print " dependencies."
+ print
+ print " "+green("--usepkgonly")+" ("+green("-K")+" short option)"
+ print " Like --usepkg above, except this only allows the use of binary"
+ print " packages, and it will abort the emerge if the package is not"
+ print " available at the time of dependency calculation."
+ print
+ print " "+green("--verbose")+" ("+green("-v")+" short option)"
+ print " Effects vary, but the general outcome is an increased or expanded"
+ print " display of content in portage's displays."
+ print
+ print " "+green("--version")+" ("+green("-V")+" short option)"
+ print " Displays the currently installed version of portage along with"
+ print " other information useful for quick reference on a system. See"
+ print " "+bold("emerge info")+" for more advanced information."
+ print
+ elif myaction in ["rsync","sync"]:
+ print
+ print bold("Usage: ")+turquoise("emerge")+" "+turquoise("--sync")
+ print
+ print " 'emerge --sync' tells emerge to update the Portage tree as specified in"
+ print " The SYNC variable found in /etc/make.conf. By default, SYNC instructs"
+ print " emerge to perform an rsync-style update with rsync.gentoo.org."
+ print
+ print " 'emerge-webrsync' exists as a helper app to emerge --sync, providing a"
+ print " method to receive the entire portage tree as a tarball that can be"
+ print " extracted and used. First time syncs would benefit greatly from this."
+ print
+ print " "+turquoise("WARNING:")
+ print " If using our rsync server, emerge will clean out all files that do not"
+ print " exist on it, including ones that you may have created. The exceptions"
+ print " to this are the distfiles, local and packages directories."
+ print
+ elif myaction=="system":
+ print
+ print bold("Usage: ")+turquoise("emerge")+" [ "+green("options")+" ] "+turquoise("system")
+ print
+ print " \"emerge system\" is the Portage system update command. When run, it"
+ print " will scan the etc/make.profile/packages file and determine what"
+ print " packages need to be installed so that your system meets the minimum"
+ print " requirements of your current system profile. Note that this doesn't"
+ print " necessarily bring your system up-to-date at all; instead, it just"
+ print " ensures that you have no missing parts. For example, if your system"
+ print " profile specifies that you should have sys-apps/iptables installed"
+ print " and you don't, then \"emerge system\" will install it (the most"
+ print " recent version that matches the profile spec) for you. It's always a"
+ print " good idea to do an \"emerge --pretend system\" before an \"emerge"
+ print " system\", just so you know what emerge is planning to do."
+ print
+ elif myaction=="config":
+ outstuff=green("Config file management support (preliminary)")+"""
+
+Portage has a special feature called "config file protection". The purpose of
+this feature is to prevent new package installs from clobbering existing
+configuration files. By default, config file protection is turned on for /etc
+and the KDE configuration dirs; more may be added in the future.
+
+When Portage installs a file into a protected directory tree like /etc, any
+existing files will not be overwritten. If a file of the same name already
+exists, Portage will change the name of the to-be- installed file from 'foo' to
+'._cfg0000_foo'. If '._cfg0000_foo' already exists, this name becomes
+'._cfg0001_foo', etc. In this way, existing files are not overwritten,
+allowing the administrator to manually merge the new config files and avoid any
+unexpected changes.
+
+In addition to protecting overwritten files, Portage will not delete any files
+from a protected directory when a package is unmerged. While this may be a
+little bit untidy, it does prevent potentially valuable config files from being
+deleted, which is of paramount importance.
+
+Protected directories are set using the CONFIG_PROTECT variable, normally
+defined in /etc/make.globals. Directory exceptions to the CONFIG_PROTECTed
+directories can be specified using the CONFIG_PROTECT_MASK variable. To find
+files that need to be updated in /etc, type:
+
+# find /etc -iname '._cfg????_*'
+
+You can disable this feature by setting CONFIG_PROTECT="-*" in /etc/make.conf.
+Then, Portage will mercilessly auto-update your config files. Alternatively,
+you can leave Config File Protection on but tell Portage that it can overwrite
+files in certain specific /etc subdirectories. For example, if you wanted
+Portage to automatically update your rc scripts and your wget configuration,
+but didn't want any other changes made without your explicit approval, you'd
+add this to /etc/make.conf:
+
+CONFIG_PROTECT_MASK="/etc/wget /etc/rc.d"
+
+etc-update is also available to aid in the merging of these files. It provides
+a vimdiff interactive merging setup and can auto-merge trivial changes.
+
+"""
+ print outstuff
+
diff --git a/pym/getbinpkg.py b/pym/getbinpkg.py
new file mode 100644
index 00000000..7145d3ad
--- /dev/null
+++ b/pym/getbinpkg.py
@@ -0,0 +1,541 @@
+# getbinpkg.py -- Portage binary-package helper functions
+# Copyright 2003-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/getbinpkg.py,v 1.12.2.3 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: getbinpkg.py,v 1.12.2.3 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+from output import *
+import htmllib,HTMLParser,string,formatter,sys,os,xpak,time,tempfile,cPickle,base64
+
+try:
+ import ftplib
+except SystemExit, e:
+ raise
+except Exception, e:
+ sys.stderr.write(red("!!! CANNOT IMPORT FTPLIB: ")+str(e)+"\n")
+
+try:
+ import httplib
+except SystemExit, e:
+ raise
+except Exception, e:
+ sys.stderr.write(red("!!! CANNOT IMPORT HTTPLIB: ")+str(e)+"\n")
+
+def make_metadata_dict(data):
+ myid,myglob = data
+
+ mydict = {}
+ for x in xpak.getindex_mem(myid):
+ mydict[x] = xpak.getitem(data,x)
+
+ return mydict
+
+class ParseLinks(HTMLParser.HTMLParser):
+ """Parser class that overrides HTMLParser to grab all anchors from an html
+ page and provide suffix and prefix limitors"""
+ def __init__(self):
+ self.PL_anchors = []
+ HTMLParser.HTMLParser.__init__(self)
+
+ def get_anchors(self):
+ return self.PL_anchors
+
+ def get_anchors_by_prefix(self,prefix):
+ newlist = []
+ for x in self.PL_anchors:
+ if (len(x) >= len(prefix)) and (x[:len(suffix)] == prefix):
+ if x not in newlist:
+ newlist.append(x[:])
+ return newlist
+
+ def get_anchors_by_suffix(self,suffix):
+ newlist = []
+ for x in self.PL_anchors:
+ if (len(x) >= len(suffix)) and (x[-len(suffix):] == suffix):
+ if x not in newlist:
+ newlist.append(x[:])
+ return newlist
+
+ def handle_endtag(self,tag):
+ pass
+
+ def handle_starttag(self,tag,attrs):
+ if tag == "a":
+ for x in attrs:
+ if x[0] == 'href':
+ if x[1] not in self.PL_anchors:
+ self.PL_anchors.append(x[1])
+
+
+def create_conn(baseurl,conn=None):
+ """(baseurl,conn) --- Takes a protocol://site:port/address url, and an
+ optional connection. If connection is already active, it is passed on.
+ baseurl is reduced to address and is returned in tuple (conn,address)"""
+ parts = string.split(baseurl, "://", 1)
+ if len(parts) != 2:
+ raise ValueError, "Provided URL does not contain protocol identifier. '%s'" % baseurl
+ protocol,url_parts = parts
+ del parts
+ host,address = string.split(url_parts, "/", 1)
+ del url_parts
+ address = "/"+address
+
+ userpass_host = string.split(host, "@", 1)
+ if len(userpass_host) == 1:
+ host = userpass_host[0]
+ userpass = ["anonymous"]
+ else:
+ host = userpass_host[1]
+ userpass = string.split(userpass_host[0], ":")
+ del userpass_host
+
+ if len(userpass) > 2:
+ raise ValueError, "Unable to interpret username/password provided."
+ elif len(userpass) == 2:
+ username = userpass[0]
+ password = userpass[1]
+ elif len(userpass) == 1:
+ username = userpass[0]
+ password = None
+ del userpass
+
+ http_headers = {}
+ http_params = {}
+ if username and password:
+ http_headers = {
+ "Authorization": "Basic %s" %
+ string.replace(
+ base64.encodestring("%s:%s" % (username, password)),
+ "\012",
+ ""
+ ),
+ }
+
+ if not conn:
+ if protocol == "https":
+ conn = httplib.HTTPSConnection(host)
+ elif protocol == "http":
+ conn = httplib.HTTPConnection(host)
+ elif protocol == "ftp":
+ passive = 1
+ if(host[-1] == "*"):
+ passive = 0
+ host = host[:-1]
+ conn = ftplib.FTP(host)
+ if password:
+ conn.login(username,password)
+ else:
+ sys.stderr.write(yellow(" * No password provided for username")+" '"+str(username)+"'\n\n")
+ conn.login(username)
+ conn.set_pasv(passive)
+ conn.set_debuglevel(0)
+ else:
+ raise NotImplementedError, "%s is not a supported protocol." % protocol
+
+ return (conn,protocol,address, http_params, http_headers)
+
+def make_ftp_request(conn, address, rest=None, dest=None):
+ """(conn,address,rest) --- uses the conn object to request the data
+ from address and issuing a rest if it is passed."""
+ try:
+
+ if dest:
+ fstart_pos = dest.tell()
+
+ conn.voidcmd("TYPE I")
+ fsize = conn.size(address)
+
+ if (rest != None) and (rest < 0):
+ rest = fsize+int(rest)
+ if rest < 0:
+ rest = 0
+
+ if rest != None:
+ mysocket = conn.transfercmd("RETR "+str(address), rest)
+ else:
+ mysocket = conn.transfercmd("RETR "+str(address))
+
+ mydata = ""
+ while 1:
+ somedata = mysocket.recv(8192)
+ if somedata:
+ if dest:
+ dest.write(somedata)
+ else:
+ mydata = mydata + somedata
+ else:
+ break
+
+ if dest:
+ data_size = fstart_pos - dest.tell()
+ else:
+ data_size = len(mydata)
+
+ mysocket.close()
+ conn.voidresp()
+ conn.voidcmd("TYPE A")
+
+ return mydata,not (fsize==data_size),""
+
+ except ValueError, e:
+ return None,int(str(e)[:4]),str(e)
+
+
+def make_http_request(conn, address, params={}, headers={}, dest=None):
+ """(conn,address,params,headers) --- uses the conn object to request
+ the data from address, performing Location forwarding and using the
+ optional params and headers."""
+
+ rc = 0
+ response = None
+ while (rc == 0) or (rc == 301) or (rc == 302):
+ try:
+ if (rc != 0):
+ conn,ignore,ignore,ignore,ignore = create_conn(address)
+ conn.request("GET", address, params, headers)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ return None,None,"Server request failed: "+str(e)
+ response = conn.getresponse()
+ rc = response.status
+
+ # 301 means that the page address is wrong.
+ if ((rc == 301) or (rc == 302)):
+ ignored_data = response.read()
+ del ignored_data
+ for x in string.split(str(response.msg), "\n"):
+ parts = string.split(x, ": ", 1)
+ if parts[0] == "Location":
+ if (rc == 301):
+ sys.stderr.write(red("Location has moved: ")+str(parts[1])+"\n")
+ if (rc == 302):
+ sys.stderr.write(red("Location has temporarily moved: ")+str(parts[1])+"\n")
+ address = parts[1]
+ break
+
+ if (rc != 200) and (rc != 206):
+ sys.stderr.write(str(response.msg)+"\n")
+ sys.stderr.write(response.read()+"\n")
+ sys.stderr.write("address: "+address+"\n")
+ return None,rc,"Server did not respond successfully ("+str(response.status)+": "+str(response.reason)+")"
+
+ if dest:
+ dest.write(response.read())
+ return "",0,""
+
+ return response.read(),0,""
+
+
+def match_in_array(array, prefix="", suffix="", match_both=1, allow_overlap=0):
+ myarray = []
+
+ if not (prefix and suffix):
+ match_both = 0
+
+ for x in array:
+ add_p = 0
+ if prefix and (len(x) >= len(prefix)) and (x[:len(prefix)] == prefix):
+ add_p = 1
+
+ if match_both:
+ if prefix and not add_p: # Require both, but don't have first one.
+ continue
+ else:
+ if add_p: # Only need one, and we have it.
+ myarray.append(x[:])
+ continue
+
+ if not allow_overlap: # Not allow to overlap prefix and suffix
+ if len(x) >= (len(prefix)+len(suffix)):
+ y = x[len(prefix):]
+ else:
+ continue # Too short to match.
+ else:
+ y = x # Do whatever... We're overlapping.
+
+ if suffix and (len(x) >= len(suffix)) and (x[-len(suffix):] == suffix):
+ myarray.append(x) # It matches
+ else:
+ continue # Doesn't match.
+
+ return myarray
+
+
+
+def dir_get_list(baseurl,conn=None):
+ """(baseurl[,connection]) -- Takes a base url to connect to and read from.
+ URL should be in the for <proto>://<site>[:port]<path>
+ Connection is used for persistent connection instances."""
+
+ if not conn:
+ keepconnection = 0
+ else:
+ keepconnection = 1
+
+ conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+ listing = None
+ if protocol in ["http","https"]:
+ page,rc,msg = make_http_request(conn,address,params,headers)
+
+ if page:
+ parser = ParseLinks()
+ parser.feed(page)
+ del page
+ listing = parser.get_anchors()
+ else:
+ raise Exception, "Unable to get listing: %s %s" % (rc,msg)
+ elif protocol in ["ftp"]:
+ if address[-1] == '/':
+ olddir = conn.pwd()
+ conn.cwd(address)
+ listing = conn.nlst()
+ conn.cwd(olddir)
+ del olddir
+ else:
+ listing = conn.nlst(address)
+ else:
+ raise TypeError, "Unknown protocol. '%s'" % protocol
+
+ if not keepconnection:
+ conn.close()
+
+ return listing
+
+def file_get_metadata(baseurl,conn=None, chunk_size=3000):
+ """(baseurl[,connection]) -- Takes a base url to connect to and read from.
+ URL should be in the for <proto>://<site>[:port]<path>
+ Connection is used for persistent connection instances."""
+
+ if not conn:
+ keepconnection = 0
+ else:
+ keepconnection = 1
+
+ conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+ if protocol in ["http","https"]:
+ headers["Range"] = "bytes=-"+str(chunk_size)
+ data,rc,msg = make_http_request(conn, address, params, headers)
+ elif protocol in ["ftp"]:
+ data,rc,msg = make_ftp_request(conn, address, -chunk_size)
+ else:
+ raise TypeError, "Unknown protocol. '%s'" % protocol
+
+ if data:
+ xpaksize = xpak.decodeint(data[-8:-4])
+ if (xpaksize+8) > chunk_size:
+ myid = file_get_metadata(baseurl, conn, (xpaksize+8))
+ if not keepconnection:
+ conn.close()
+ return myid
+ else:
+ xpak_data = data[len(data)-(xpaksize+8):-8]
+ del data
+
+ myid = xpak.xsplit_mem(xpak_data)
+ if not myid:
+ myid = None,None
+ del xpak_data
+ else:
+ myid = None,None
+
+ if not keepconnection:
+ conn.close()
+
+ return myid
+
+
+def file_get(baseurl,dest,conn=None,fcmd=None):
+ """(baseurl,dest,fcmd=) -- Takes a base url to connect to and read from.
+ URL should be in the for <proto>://[user[:pass]@]<site>[:port]<path>"""
+
+ if not fcmd:
+ return file_get_lib(baseurl,dest,conn)
+
+ fcmd = string.replace(fcmd, "${DISTDIR}", dest)
+ fcmd = string.replace(fcmd, "${URI}", baseurl)
+ fcmd = string.replace(fcmd, "${FILE}", os.path.basename(baseurl))
+ mysplit = string.split(fcmd)
+ mycmd = mysplit[0]
+ myargs = [os.path.basename(mycmd)]+mysplit[1:]
+ mypid=os.fork()
+ if mypid == 0:
+ os.execv(mycmd,myargs)
+ sys.stderr.write("!!! Failed to spawn fetcher.\n")
+ sys.exit(1)
+ retval=os.waitpid(mypid,0)[1]
+ if (retval & 0xff) == 0:
+ retval = retval >> 8
+ else:
+ sys.stderr.write("Spawned processes caught a signal.\n")
+ sys.exit(1)
+ if retval != 0:
+ sys.stderr.write("Fetcher exited with a failure condition.\n")
+ return 0
+ return 1
+
+def file_get_lib(baseurl,dest,conn=None):
+ """(baseurl[,connection]) -- Takes a base url to connect to and read from.
+ URL should be in the for <proto>://<site>[:port]<path>
+ Connection is used for persistent connection instances."""
+
+ if not conn:
+ keepconnection = 0
+ else:
+ keepconnection = 1
+
+ conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+ sys.stderr.write("Fetching '"+str(os.path.basename(address)+"'\n"))
+ if protocol in ["http","https"]:
+ data,rc,msg = make_http_request(conn, address, params, headers, dest=dest)
+ elif protocol in ["ftp"]:
+ data,rc,msg = make_ftp_request(conn, address, dest=dest)
+ else:
+ raise TypeError, "Unknown protocol. '%s'" % protocol
+
+ if not keepconnection:
+ conn.close()
+
+ return rc
+
+
+def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=1, makepickle=None):
+ """(baseurl,conn,chunk_size,verbose) --
+ """
+ if not conn:
+ keepconnection = 0
+ else:
+ keepconnection = 1
+
+ if makepickle == None:
+ makepickle = "/var/cache/edb/metadata.idx.most_recent"
+
+ conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+ filedict = {}
+
+ try:
+ metadatafile = open("/var/cache/edb/remote_metadata.pickle")
+ metadata = cPickle.load(metadatafile)
+ sys.stderr.write("Loaded metadata pickle.\n")
+ metadatafile.close()
+ except SystemExit, e:
+ raise
+ except:
+ metadata = {}
+ if not metadata.has_key(baseurl):
+ metadata[baseurl]={}
+ if not metadata[baseurl].has_key("indexname"):
+ metadata[baseurl]["indexname"]=""
+ if not metadata[baseurl].has_key("timestamp"):
+ metadata[baseurl]["timestamp"]=0
+ if not metadata[baseurl].has_key("unmodified"):
+ metadata[baseurl]["unmodified"]=0
+ if not metadata[baseurl].has_key("data"):
+ metadata[baseurl]["data"]={}
+
+ filelist = dir_get_list(baseurl, conn)
+ tbz2list = match_in_array(filelist, suffix=".tbz2")
+ metalist = match_in_array(filelist, prefix="metadata.idx")
+ del filelist
+
+ # Determine if our metadata file is current.
+ metalist.sort()
+ metalist.reverse() # makes the order new-to-old.
+ havecache=0
+ for mfile in metalist:
+ if usingcache and \
+ ((metadata[baseurl]["indexname"] != mfile) or \
+ (metadata[baseurl]["timestamp"] < int(time.time()-(60*60*24)))):
+ # Try to download new cache until we succeed on one.
+ data=""
+ for trynum in [1,2,3]:
+ mytempfile = tempfile.TemporaryFile()
+ try:
+ file_get(baseurl+"/"+mfile, mytempfile, conn)
+ if mytempfile.tell() > len(data):
+ mytempfile.seek(0)
+ data = mytempfile.read()
+ except ValueError, e:
+ sys.stderr.write("--- "+str(e)+"\n")
+ if trynum < 3:
+ sys.stderr.write("Retrying...\n")
+ mytempfile.close()
+ continue
+ if match_in_array([mfile],suffix=".gz"):
+ sys.stderr.write("gzip'd\n")
+ try:
+ import gzip
+ mytempfile.seek(0)
+ gzindex = gzip.GzipFile(mfile[:-3],'rb',9,mytempfile)
+ data = gzindex.read()
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ mytempfile.close()
+ sys.stderr.write("!!! Failed to use gzip: "+str(e)+"\n")
+ mytempfile.close()
+ try:
+ metadata[baseurl]["data"] = cPickle.loads(data)
+ del data
+ metadata[baseurl]["indexname"] = mfile
+ metadata[baseurl]["timestamp"] = int(time.time())
+ metadata[baseurl]["modified"] = 0 # It's not, right after download.
+ sys.stderr.write("Pickle loaded.\n")
+ break
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ sys.stderr.write("!!! Failed to read data from index: "+str(mfile)+"\n")
+ sys.stderr.write("!!! "+str(e)+"\n")
+ try:
+ metadatafile = open("/var/cache/edb/remote_metadata.pickle", "w+")
+ cPickle.dump(metadata,metadatafile)
+ metadatafile.close()
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ sys.stderr.write("!!! Failed to write binary metadata to disk!\n")
+ sys.stderr.write("!!! "+str(e)+"\n")
+ break
+ # We may have metadata... now we run through the tbz2 list and check.
+ sys.stderr.write(yellow("cache miss: 'x'")+" --- "+green("cache hit: 'o'")+"\n")
+ for x in tbz2list:
+ x = os.path.basename(x)
+ if ((not metadata[baseurl]["data"].has_key(x)) or \
+ (x not in metadata[baseurl]["data"].keys())):
+ sys.stderr.write(yellow("x"))
+ metadata[baseurl]["modified"] = 1
+ myid = file_get_metadata(baseurl+"/"+x, conn, chunk_size)
+
+ if myid[0]:
+ metadata[baseurl]["data"][x] = make_metadata_dict(myid)
+ elif verbose:
+ sys.stderr.write(red("!!! Failed to retrieve metadata on: ")+str(x)+"\n")
+ else:
+ sys.stderr.write(green("o"))
+ sys.stderr.write("\n")
+
+ try:
+ if metadata[baseurl].has_key("modified") and metadata[baseurl]["modified"]:
+ metadata[baseurl]["timestamp"] = int(time.time())
+ metadatafile = open("/var/cache/edb/remote_metadata.pickle", "w+")
+ cPickle.dump(metadata,metadatafile)
+ metadatafile.close()
+ if makepickle:
+ metadatafile = open(makepickle, "w")
+ cPickle.dump(metadata[baseurl]["data"],metadatafile)
+ metadatafile.close()
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ sys.stderr.write("!!! Failed to write binary metadata to disk!\n")
+ sys.stderr.write("!!! "+str(e)+"\n")
+
+ if not keepconnection:
+ conn.close()
+
+ return metadata[baseurl]["data"]
diff --git a/pym/output.py b/pym/output.py
new file mode 100644
index 00000000..ddb85c1a
--- /dev/null
+++ b/pym/output.py
@@ -0,0 +1,167 @@
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/output.py,v 1.24.2.4 2005/04/17 09:01:55 jstubbs Exp $
+cvs_id_string="$Id: output.py,v 1.24.2.4 2005/04/17 09:01:55 jstubbs Exp $"[5:-2]
+
+import os,sys,re
+
+havecolor=1
+dotitles=1
+
+esc_seq = "\x1b["
+
+g_attr = {}
+g_attr["normal"] = 0
+
+g_attr["bold"] = 1
+g_attr["faint"] = 2
+g_attr["standout"] = 3
+g_attr["underline"] = 4
+g_attr["blink"] = 5
+g_attr["overline"] = 6 # Why is overline actually useful?
+g_attr["reverse"] = 7
+g_attr["invisible"] = 8
+
+g_attr["no-attr"] = 22
+g_attr["no-standout"] = 23
+g_attr["no-underline"] = 24
+g_attr["no-blink"] = 25
+g_attr["no-overline"] = 26
+g_attr["no-reverse"] = 27
+# 28 isn't defined?
+# 29 isn't defined?
+g_attr["black"] = 30
+g_attr["red"] = 31
+g_attr["green"] = 32
+g_attr["yellow"] = 33
+g_attr["blue"] = 34
+g_attr["magenta"] = 35
+g_attr["cyan"] = 36
+g_attr["white"] = 37
+# 38 isn't defined?
+g_attr["default"] = 39
+g_attr["bg_black"] = 40
+g_attr["bg_red"] = 41
+g_attr["bg_green"] = 42
+g_attr["bg_yellow"] = 43
+g_attr["bg_blue"] = 44
+g_attr["bg_magenta"] = 45
+g_attr["bg_cyan"] = 46
+g_attr["bg_white"] = 47
+g_attr["bg_default"] = 49
+
+
+# make_seq("blue", "black", "normal")
+def color(fg, bg="default", attr=["normal"]):
+ mystr = esc_seq[:] + "%02d" % g_attr[fg]
+ for x in [bg]+attr:
+ mystr += ";%02d" % g_attr[x]
+ return mystr+"m"
+
+
+
+codes={}
+codes["reset"] = esc_seq + "39;49;00m"
+
+codes["bold"] = esc_seq + "01m"
+codes["faint"] = esc_seq + "02m"
+codes["standout"] = esc_seq + "03m"
+codes["underline"] = esc_seq + "04m"
+codes["blink"] = esc_seq + "05m"
+codes["overline"] = esc_seq + "06m" # Who made this up? Seriously.
+
+codes["teal"] = esc_seq + "36m"
+codes["turquoise"] = esc_seq + "36;01m"
+
+codes["fuchsia"] = esc_seq + "35;01m"
+codes["purple"] = esc_seq + "35m"
+
+codes["blue"] = esc_seq + "34;01m"
+codes["darkblue"] = esc_seq + "34m"
+
+codes["green"] = esc_seq + "32;01m"
+codes["darkgreen"] = esc_seq + "32m"
+
+codes["yellow"] = esc_seq + "33;01m"
+codes["brown"] = esc_seq + "33m"
+
+codes["red"] = esc_seq + "31;01m"
+codes["darkred"] = esc_seq + "31m"
+
+def nc_len(mystr):
+ tmp = re.sub(esc_seq + "^m]+m", "", mystr);
+ return len(tmp)
+
+def xtermTitle(mystr):
+ if havecolor and dotitles and os.environ.has_key("TERM") and sys.stderr.isatty():
+ myt=os.environ["TERM"]
+ legal_terms = ["xterm","Eterm","aterm","rxvt","screen","kterm","rxvt-unicode"]
+ for term in legal_terms:
+ if myt.startswith(term):
+ sys.stderr.write("\x1b]2;"+str(mystr)+"\x07")
+ sys.stderr.flush()
+ break
+
+def xtermTitleReset():
+ if havecolor and dotitles and os.environ.has_key("TERM"):
+ myt=os.environ["TERM"]
+ xtermTitle(os.environ["TERM"])
+
+
+def notitles():
+ "turn off title setting"
+ dotitles=0
+
+def nocolor():
+ "turn off colorization"
+ havecolor=0
+ for x in codes.keys():
+ codes[x]=""
+
+def resetColor():
+ return codes["reset"]
+
+def ctext(color,text):
+ return codes[ctext]+text+codes["reset"]
+
+def bold(text):
+ return codes["bold"]+text+codes["reset"]
+def white(text):
+ return bold(text)
+
+def teal(text):
+ return codes["teal"]+text+codes["reset"]
+def turquoise(text):
+ return codes["turquoise"]+text+codes["reset"]
+def darkteal(text):
+ return turquoise(text)
+
+def fuscia(text): # Don't use this one. It's spelled wrong!
+ return codes["fuchsia"]+text+codes["reset"]
+def fuchsia(text):
+ return codes["fuchsia"]+text+codes["reset"]
+def purple(text):
+ return codes["purple"]+text+codes["reset"]
+
+def blue(text):
+ return codes["blue"]+text+codes["reset"]
+def darkblue(text):
+ return codes["darkblue"]+text+codes["reset"]
+
+def green(text):
+ return codes["green"]+text+codes["reset"]
+def darkgreen(text):
+ return codes["darkgreen"]+text+codes["reset"]
+
+def yellow(text):
+ return codes["yellow"]+text+codes["reset"]
+def brown(text):
+ return codes["brown"]+text+codes["reset"]
+def darkyellow(text):
+ return brown(text)
+
+def red(text):
+ return codes["red"]+text+codes["reset"]
+def darkred(text):
+ return codes["darkred"]+text+codes["reset"]
+
diff --git a/pym/portage.py b/pym/portage.py
new file mode 100644
index 00000000..a6702344
--- /dev/null
+++ b/pym/portage.py
@@ -0,0 +1,7452 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage.py,v 1.524.2.76 2005/05/29 12:40:08 jstubbs Exp $
+cvs_id_string="$Id: portage.py,v 1.524.2.76 2005/05/29 12:40:08 jstubbs Exp $"[5:-2]
+
+VERSION="$Revision: 1.524.2.76 $"[11:-2] + "-cvs"
+
+# ===========================================================================
+# START OF IMPORTS -- START OF IMPORTS -- START OF IMPORTS -- START OF IMPORT
+# ===========================================================================
+
+try:
+ import sys
+except SystemExit, e:
+ raise
+except:
+ print "Failed to import sys! Something is _VERY_ wrong with python."
+ raise SystemExit, 127
+
+try:
+ import os,string,types,atexit,signal,fcntl
+ import time,cPickle,traceback,copy
+ import re,pwd,grp,commands
+ import shlex,shutil
+
+ import stat
+ import commands
+ from time import sleep
+ from random import shuffle
+except SystemExit, e:
+ raise
+except Exception, e:
+ sys.stderr.write("\n\n")
+ sys.stderr.write("!!! Failed to complete python imports. There are internal modules for\n")
+ sys.stderr.write("!!! python and failure here indicates that you have a problem with python\n")
+ sys.stderr.write("!!! itself and thus portage is no able to continue processing.\n\n")
+
+ sys.stderr.write("!!! You might consider starting python with verbose flags to see what has\n")
+ sys.stderr.write("!!! gone wrong. Here is the information we got for this exception:\n")
+
+ sys.stderr.write(" "+str(e)+"\n\n");
+ sys.exit(127)
+except:
+ sys.stderr.write("\n\n")
+ sys.stderr.write("!!! Failed to complete python imports. There are internal modules for\n")
+ sys.stderr.write("!!! python and failure here indicates that you have a problem with python\n")
+ sys.stderr.write("!!! itself and thus portage is no able to continue processing.\n\n")
+
+ sys.stderr.write("!!! You might consider starting python with verbose flags to see what has\n")
+ sys.stderr.write("!!! gone wrong. The exception was non-standard and we were unable to catch it.\n\n")
+ sys.exit(127)
+
+try:
+ # XXX: This should get renamed to bsd_chflags, I think.
+ import chflags
+ bsd_chflags = chflags
+except SystemExit, e:
+ raise
+except:
+ # XXX: This should get renamed to bsd_chflags, I think.
+ bsd_chflags = None
+
+try:
+ import cvstree
+ import xpak
+ import getbinpkg
+ import portage_dep
+
+ # XXX: This needs to get cleaned up.
+ import output
+ from output import blue, bold, brown, darkblue, darkgreen, darkred, darkteal, \
+ darkyellow, fuchsia, fuscia, green, purple, red, teal, turquoise, white, \
+ xtermTitle, xtermTitleReset, yellow
+
+ import portage_const
+ from portage_const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \
+ USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
+ PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
+ EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
+ MOVE_BINARY, PRELINK_BINARY, WORLD_FILE, MAKE_CONF_FILE, MAKE_DEFAULTS_FILE, \
+ DEPRECATED_PROFILE_FILE, USER_VIRTUALS_FILE, EBUILD_SH_ENV_FILE, \
+ INVALID_ENV_FILE, CUSTOM_MIRRORS_FILE, SANDBOX_PIDS_FILE, CONFIG_MEMORY_FILE,\
+ INCREMENTALS, STICKIES
+
+ from portage_data import ostype, lchown, userland, secpass, uid, wheelgid, \
+ portage_uid, portage_gid
+
+ import portage_util
+ from portage_util import grab_multiple, grabdict, grabdict_package, grabfile, grabfile_package, \
+ grabints, map_dictlist_vals, pickle_read, pickle_write, stack_dictlist, stack_dicts, stack_lists, \
+ unique_array, varexpand, writedict, writeints, writemsg, getconfig
+ import portage_exception
+ import portage_gpg
+ import portage_locks
+ import portage_exec
+ from portage_locks import unlockfile,unlockdir,lockfile,lockdir
+ import portage_checksum
+ from portage_checksum import perform_md5,perform_checksum,prelink_capable
+ from portage_localization import _
+except SystemExit, e:
+ raise
+except Exception, e:
+ sys.stderr.write("\n\n")
+ sys.stderr.write("!!! Failed to complete portage imports. There are internal modules for\n")
+ sys.stderr.write("!!! portage and failure here indicates that you have a problem with your\n")
+ sys.stderr.write("!!! installation of portage. Please try a rescue portage located in the\n")
+ sys.stderr.write("!!! portage tree under '/usr/portage/sys-apps/portage/files/' (default).\n")
+ sys.stderr.write("!!! There is a README.RESCUE file that details the steps required to perform\n")
+ sys.stderr.write("!!! a recovery of portage.\n")
+
+ sys.stderr.write(" "+str(e)+"\n\n")
+ sys.exit(127)
+
+
+# ===========================================================================
+# END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END
+# ===========================================================================
+
+
+def exithandler(signum,frame):
+ """Handles ^C interrupts in a sane manner"""
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
+
+ # 0=send to *everybody* in process group
+ portageexit()
+ print "Exiting due to signal"
+ os.kill(0,signum)
+ sys.exit(1)
+
+signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+signal.signal(signal.SIGINT, exithandler)
+signal.signal(signal.SIGTERM, exithandler)
+signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+def load_mod(name):
+ modname = string.join(string.split(name,".")[:-1],".")
+ mod = __import__(modname)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+def best_from_dict(key, top_dict, key_order, EmptyOnError=1, FullCopy=1, AllowEmpty=1):
+ for x in key_order:
+ if top_dict.has_key(x) and top_dict[x].has_key(key):
+ if FullCopy:
+ return copy.deepcopy(top_dict[x][key])
+ else:
+ return top_dict[x][key]
+ if EmptyOnError:
+ return ""
+ else:
+ raise KeyError, "Key not found in list; '%s'" % key
+
+def getcwd():
+ "this fixes situations where the current directory doesn't exist"
+ try:
+ return os.getcwd()
+ except SystemExit, e:
+ raise
+ except:
+ os.chdir("/")
+ return "/"
+getcwd()
+
+def abssymlink(symlink):
+ "This reads symlinks, resolving the relative symlinks, and returning the absolute."
+ mylink=os.readlink(symlink)
+ if mylink[0] != '/':
+ mydir=os.path.dirname(symlink)
+ mylink=mydir+"/"+mylink
+ return os.path.normpath(mylink)
+
+def suffix_array(array,suffix,doblanks=1):
+ """Appends a given suffix to each element in an Array/List/Tuple.
+ Returns a List."""
+ if type(array) not in [types.ListType, types.TupleType]:
+ raise TypeError, "List or Tuple expected. Got %s" % type(array)
+ newarray=[]
+ for x in array:
+ if x or doblanks:
+ newarray.append(x + suffix)
+ else:
+ newarray.append(x)
+ return newarray
+
+def prefix_array(array,prefix,doblanks=1):
+ """Prepends a given prefix to each element in an Array/List/Tuple.
+ Returns a List."""
+ if type(array) not in [types.ListType, types.TupleType]:
+ raise TypeError, "List or Tuple expected. Got %s" % type(array)
+ newarray=[]
+ for x in array:
+ if x or doblanks:
+ newarray.append(prefix + x)
+ else:
+ newarray.append(x)
+ return newarray
+
+def normalize_path(mypath):
+ newpath = os.path.normpath(mypath)
+ if len(newpath) > 1:
+ if newpath[:2] == "//":
+ newpath = newpath[1:]
+ return newpath
+
+dircache = {}
+cacheHit=0
+cacheMiss=0
+cacheStale=0
+def cacheddir(my_original_path, ignorecvs, ignorelist, EmptyOnError, followSymlinks=True):
+ global cacheHit,cacheMiss,cacheStale
+ mypath = normalize_path(my_original_path)
+ if dircache.has_key(mypath):
+ cacheHit += 1
+ cached_mtime, list, ftype = dircache[mypath]
+ else:
+ cacheMiss += 1
+ cached_mtime, list, ftype = -1, [], []
+ try:
+ pathstat = os.stat(mypath)
+ if stat.S_ISDIR(pathstat[stat.ST_MODE]):
+ mtime = pathstat[stat.ST_MTIME]
+ else:
+ raise Exception
+ except SystemExit, e:
+ raise
+ except:
+ if EmptyOnError:
+ return [], []
+ return None, None
+ if mtime != cached_mtime:
+ if dircache.has_key(mypath):
+ cacheStale += 1
+ list = os.listdir(mypath)
+ ftype = []
+ for x in list:
+ try:
+ if followSymlinks:
+ pathstat = os.stat(mypath+"/"+x)
+ else:
+ pathstat = os.lstat(mypath+"/"+x)
+
+ if stat.S_ISREG(pathstat[stat.ST_MODE]):
+ ftype.append(0)
+ elif stat.S_ISDIR(pathstat[stat.ST_MODE]):
+ ftype.append(1)
+ elif stat.S_ISLNK(pathstat[stat.ST_MODE]):
+ ftype.append(2)
+ else:
+ ftype.append(3)
+ except SystemExit, e:
+ raise
+ except:
+ ftype.append(3)
+ dircache[mypath] = mtime, list, ftype
+
+ ret_list = []
+ ret_ftype = []
+ for x in range(0, len(list)):
+ if(ignorecvs and (len(list[x]) > 2) and (list[x][:2]!=".#")):
+ ret_list.append(list[x])
+ ret_ftype.append(ftype[x])
+ elif (list[x] not in ignorelist):
+ ret_list.append(list[x])
+ ret_ftype.append(ftype[x])
+
+ writemsg("cacheddirStats: H:%d/M:%d/S:%d\n" % (cacheHit, cacheMiss, cacheStale),10)
+ return ret_list, ret_ftype
+
+
+def listdir(mypath, recursive=False, filesonly=False, ignorecvs=False, ignorelist=[], followSymlinks=True,
+ EmptyOnError=False):
+
+ list, ftype = cacheddir(mypath, ignorecvs, ignorelist, EmptyOnError, followSymlinks)
+
+ if list is None:
+ list=[]
+ if ftype is None:
+ ftype=[]
+
+ if not filesonly and not recursive:
+ return list
+
+ if recursive:
+ x=0
+ while x<len(ftype):
+ if ftype[x]==1 and not (ignorecvs and os.path.basename(list[x]) in ('CVS','.svn','SCCS')):
+ l,f = cacheddir(mypath+"/"+list[x], ignorecvs, ignorelist, EmptyOnError,
+ followSymlinks)
+
+ l=l[:]
+ for y in range(0,len(l)):
+ l[y]=list[x]+"/"+l[y]
+ list=list+l
+ ftype=ftype+f
+ x+=1
+ if filesonly:
+ rlist=[]
+ for x in range(0,len(ftype)):
+ if ftype[x]==0:
+ rlist=rlist+[list[x]]
+ else:
+ rlist=list
+
+ return rlist
+
+starttime=long(time.time())
+features=[]
+
+def tokenize(mystring):
+ """breaks a string like 'foo? (bar) oni? (blah (blah))'
+ into embedded lists; returns None on paren mismatch"""
+
+ # This function is obsoleted.
+ # Use dep_parenreduce
+
+ newtokens=[]
+ curlist=newtokens
+ prevlists=[]
+ level=0
+ accum=""
+ for x in mystring:
+ if x=="(":
+ if accum:
+ curlist.append(accum)
+ accum=""
+ prevlists.append(curlist)
+ curlist=[]
+ level=level+1
+ elif x==")":
+ if accum:
+ curlist.append(accum)
+ accum=""
+ if level==0:
+ writemsg("!!! tokenizer: Unmatched left parenthesis in:\n'"+str(mystring)+"'\n")
+ return None
+ newlist=curlist
+ curlist=prevlists.pop()
+ curlist.append(newlist)
+ level=level-1
+ elif x in string.whitespace:
+ if accum:
+ curlist.append(accum)
+ accum=""
+ else:
+ accum=accum+x
+ if accum:
+ curlist.append(accum)
+ if (level!=0):
+ writemsg("!!! tokenizer: Exiting with unterminated parenthesis in:\n'"+str(mystring)+"'\n")
+ return None
+ return newtokens
+
+def flatten(mytokens):
+ """this function now turns a [1,[2,3]] list into
+ a [1,2,3] list and returns it."""
+ newlist=[]
+ for x in mytokens:
+ if type(x)==types.ListType:
+ newlist.extend(flatten(x))
+ else:
+ newlist.append(x)
+ return newlist
+
+#beautiful directed graph object
+
+class digraph:
+ def __init__(self):
+ self.dict={}
+ #okeys = keys, in order they were added (to optimize firstzero() ordering)
+ self.okeys=[]
+
+ def addnode(self,mykey,myparent):
+ if not self.dict.has_key(mykey):
+ self.okeys.append(mykey)
+ if myparent==None:
+ self.dict[mykey]=[0,[]]
+ else:
+ self.dict[mykey]=[0,[myparent]]
+ self.dict[myparent][0]=self.dict[myparent][0]+1
+ return
+ if myparent and (not myparent in self.dict[mykey][1]):
+ self.dict[mykey][1].append(myparent)
+ self.dict[myparent][0]=self.dict[myparent][0]+1
+
+ def delnode(self,mykey):
+ if not self.dict.has_key(mykey):
+ return
+ for x in self.dict[mykey][1]:
+ self.dict[x][0]=self.dict[x][0]-1
+ del self.dict[mykey]
+ while 1:
+ try:
+ self.okeys.remove(mykey)
+ except ValueError:
+ break
+
+ def allnodes(self):
+ "returns all nodes in the dictionary"
+ return self.dict.keys()
+
+ def firstzero(self):
+ "returns first node with zero references, or NULL if no such node exists"
+ for x in self.okeys:
+ if self.dict[x][0]==0:
+ return x
+ return None
+
+ def depth(self, mykey):
+ depth=0
+ while (self.dict[mykey][1]):
+ depth=depth+1
+ mykey=self.dict[mykey][1][0]
+ return depth
+
+ def allzeros(self):
+ "returns all nodes with zero references, or NULL if no such node exists"
+ zerolist = []
+ for x in self.dict.keys():
+ mys = string.split(x)
+ if mys[0] != "blocks" and self.dict[x][0]==0:
+ zerolist.append(x)
+ return zerolist
+
+ def hasallzeros(self):
+ "returns 0/1, Are all nodes zeros? 1 : 0"
+ zerolist = []
+ for x in self.dict.keys():
+ if self.dict[x][0]!=0:
+ return 0
+ return 1
+
+ def empty(self):
+ if len(self.dict)==0:
+ return 1
+ return 0
+
+ def hasnode(self,mynode):
+ return self.dict.has_key(mynode)
+
+ def copy(self):
+ mygraph=digraph()
+ for x in self.dict.keys():
+ mygraph.dict[x]=self.dict[x][:]
+ mygraph.okeys=self.okeys[:]
+ return mygraph
+
+# valid end of version components; integers specify offset from release version
+# pre=prerelease, p=patchlevel (should always be followed by an int), rc=release candidate
+# all but _p (where it is required) can be followed by an optional trailing integer
+
+endversion={"pre":-2,"p":0,"alpha":-4,"beta":-3,"rc":-1}
+# as there's no reliable way to set {}.keys() order
+# netversion_keys will be used instead of endversion.keys
+# to have fixed search order, so that "pre" is checked
+# before "p"
+endversion_keys = ["pre", "p", "alpha", "beta", "rc"]
+
+#parse /etc/env.d and generate /etc/profile.env
+
+def env_update(makelinks=1):
+ global root
+ if not os.path.exists(root+"etc/env.d"):
+ prevmask=os.umask(0)
+ os.makedirs(root+"etc/env.d",0755)
+ os.umask(prevmask)
+ fns=listdir(root+"etc/env.d",EmptyOnError=1)
+ fns.sort()
+ pos=0
+ while (pos<len(fns)):
+ if len(fns[pos])<=2:
+ del fns[pos]
+ continue
+ if (fns[pos][0] not in string.digits) or (fns[pos][1] not in string.digits):
+ del fns[pos]
+ continue
+ pos=pos+1
+
+ specials={
+ "KDEDIRS":[],"PATH":[],"CLASSPATH":[],"LDPATH":[],"MANPATH":[],
+ "INFODIR":[],"INFOPATH":[],"ROOTPATH":[],"CONFIG_PROTECT":[],
+ "CONFIG_PROTECT_MASK":[],"PRELINK_PATH":[],"PRELINK_PATH_MASK":[],
+ "PYTHONPATH":[], "ADA_INCLUDE_PATH":[], "ADA_OBJECTS_PATH":[]
+ }
+ colon_separated = [
+ "ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH",
+ "LDPATH", "MANPATH",
+ "PATH", "PRELINK_PATH",
+ "PRELINK_PATH_MASK", "PYTHONPATH"
+ ]
+
+ env={}
+
+ for x in fns:
+ # don't process backup files
+ if x[-1]=='~' or x[-4:]==".bak":
+ continue
+ myconfig=getconfig(root+"etc/env.d/"+x)
+ if myconfig==None:
+ writemsg("!!! Parsing error in "+str(root)+"etc/env.d/"+str(x)+"\n")
+ #parse error
+ continue
+ # process PATH, CLASSPATH, LDPATH
+ for myspec in specials.keys():
+ if myconfig.has_key(myspec):
+ if myspec in colon_separated:
+ specials[myspec].extend(myconfig[myspec].split(":"))
+ else:
+ specials[myspec].append(myconfig[myspec])
+ del myconfig[myspec]
+ # process all other variables
+ for myenv in myconfig.keys():
+ env[myenv]=myconfig[myenv]
+
+ if os.path.exists(root+"etc/ld.so.conf"):
+ myld=open(root+"etc/ld.so.conf")
+ myldlines=myld.readlines()
+ myld.close()
+ oldld=[]
+ for x in myldlines:
+ #each line has at least one char (a newline)
+ if x[0]=="#":
+ continue
+ oldld.append(x[:-1])
+ # os.rename(root+"etc/ld.so.conf",root+"etc/ld.so.conf.bak")
+ # Where is the new ld.so.conf generated? (achim)
+ else:
+ oldld=None
+
+ ld_cache_update=False
+ if os.environ.has_key("PORTAGE_CALLER") and \
+ os.environ["PORTAGE_CALLER"] == "env-update":
+ ld_cache_update = True
+
+ newld=specials["LDPATH"]
+ if (oldld!=newld):
+ #ld.so.conf needs updating and ldconfig needs to be run
+ myfd=open(root+"etc/ld.so.conf","w")
+ myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n")
+ myfd.write("# contents of /etc/env.d directory\n")
+ for x in specials["LDPATH"]:
+ myfd.write(x+"\n")
+ myfd.close()
+ ld_cache_update=True
+
+ # Update prelink.conf if we are prelink-enabled
+ if prelink_capable:
+ newprelink=open(root+"etc/prelink.conf","w")
+ newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n")
+ newprelink.write("# contents of /etc/env.d directory\n")
+
+ for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]:
+ newprelink.write("-l "+x+"\n");
+ for x in specials["LDPATH"]+specials["PATH"]+specials["PRELINK_PATH"]:
+ if not x:
+ continue
+ if x[-1]!='/':
+ x=x+"/"
+ plmasked=0
+ for y in specials["PRELINK_PATH_MASK"]:
+ if not y:
+ continue
+ if y[-1]!='/':
+ y=y+"/"
+ if y==x[0:len(y)]:
+ plmasked=1
+ break
+ if not plmasked:
+ newprelink.write("-h "+x+"\n")
+ for x in specials["PRELINK_PATH_MASK"]:
+ newprelink.write("-b "+x+"\n")
+ newprelink.close()
+
+ if not mtimedb.has_key("ldpath"):
+ mtimedb["ldpath"]={}
+
+ for x in specials["LDPATH"]+['/usr/lib','/lib']:
+ try:
+ newldpathtime=os.stat(x)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except:
+ newldpathtime=0
+ if mtimedb["ldpath"].has_key(x):
+ if mtimedb["ldpath"][x]==newldpathtime:
+ pass
+ else:
+ mtimedb["ldpath"][x]=newldpathtime
+ ld_cache_update=True
+ else:
+ mtimedb["ldpath"][x]=newldpathtime
+ ld_cache_update=True
+
+ # ldconfig has very different behaviour between FreeBSD and Linux
+ if ostype=="Linux" or ostype.lower().endswith("gnu"):
+ if (ld_cache_update or makelinks):
+ # We can't update links if we haven't cleaned other versions first, as
+ # an older package installed ON TOP of a newer version will cause ldconfig
+ # to overwrite the symlinks we just made. -X means no links. After 'clean'
+ # we can safely create links.
+ writemsg(">>> Regenerating "+str(root)+"etc/ld.so.cache...\n")
+ if makelinks:
+ commands.getstatusoutput("cd / ; /sbin/ldconfig -r "+root)
+ else:
+ commands.getstatusoutput("cd / ; /sbin/ldconfig -X -r "+root)
+ elif ostype == "FreeBSD":
+ if (ld_cache_update):
+ writemsg(">>> Regenerating "+str(root)+"var/run/ld-elf.so.hints...\n")
+ commands.getstatusoutput("cd / ; /sbin/ldconfig -elf -f "+str(root)+"var/run/ld-elf.so.hints "+str(root)+"etc/ld.so.conf")
+
+ del specials["LDPATH"]
+
+ penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
+ penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
+ cenvnotice = penvnotice[:]
+ penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
+ cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"
+
+ #create /etc/profile.env for bash support
+ outfile=open(root+"/etc/profile.env","w")
+ outfile.write(penvnotice)
+
+ for path in specials.keys():
+ if len(specials[path])==0:
+ continue
+ outstring="export "+path+"='"
+ if path in ["CONFIG_PROTECT","CONFIG_PROTECT_MASK"]:
+ for x in specials[path][:-1]:
+ outstring += x+" "
+ else:
+ for x in specials[path][:-1]:
+ outstring=outstring+x+":"
+ outstring=outstring+specials[path][-1]+"'"
+ outfile.write(outstring+"\n")
+
+ #create /etc/profile.env
+ for x in env.keys():
+ if type(env[x])!=types.StringType:
+ continue
+ outfile.write("export "+x+"='"+env[x]+"'\n")
+ outfile.close()
+
+ #create /etc/csh.env for (t)csh support
+ outfile=open(root+"/etc/csh.env","w")
+ outfile.write(cenvnotice)
+
+ for path in specials.keys():
+ if len(specials[path])==0:
+ continue
+ outstring="setenv "+path+" '"
+ if path in ["CONFIG_PROTECT","CONFIG_PROTECT_MASK"]:
+ for x in specials[path][:-1]:
+ outstring += x+" "
+ else:
+ for x in specials[path][:-1]:
+ outstring=outstring+x+":"
+ outstring=outstring+specials[path][-1]+"'"
+ outfile.write(outstring+"\n")
+ #get it out of the way
+ del specials[path]
+
+ #create /etc/csh.env
+ for x in env.keys():
+ if type(env[x])!=types.StringType:
+ continue
+ outfile.write("setenv "+x+" '"+env[x]+"'\n")
+ outfile.close()
+
+def new_protect_filename(mydest, newmd5=None):
+ """Resolves a config-protect filename for merging, optionally
+ using the last filename if the md5 matches.
+ (dest,md5) ==> 'string' --- path_to_target_filename
+ (dest) ==> ('next', 'highest') --- next_target and most-recent_target
+ """
+
+ # config protection filename format:
+ # ._cfg0000_foo
+ # 0123456789012
+ prot_num=-1
+ last_pfile=""
+
+ if (len(mydest) == 0):
+ raise ValueError, "Empty path provided where a filename is required"
+ if (mydest[-1]=="/"): # XXX add better directory checking
+ raise ValueError, "Directory provided but this function requires a filename"
+ if not os.path.exists(mydest):
+ return mydest
+
+ real_filename = os.path.basename(mydest)
+ real_dirname = os.path.dirname(mydest)
+ for pfile in listdir(real_dirname):
+ if pfile[0:5] != "._cfg":
+ continue
+ if pfile[10:] != real_filename:
+ continue
+ try:
+ new_prot_num = int(pfile[5:9])
+ if new_prot_num > prot_num:
+ prot_num = new_prot_num
+ last_pfile = pfile
+ except SystemExit, e:
+ raise
+ except:
+ continue
+ prot_num = prot_num + 1
+
+ new_pfile = os.path.normpath(real_dirname+"/._cfg"+string.zfill(prot_num,4)+"_"+real_filename)
+ old_pfile = os.path.normpath(real_dirname+"/"+last_pfile)
+ if last_pfile and newmd5:
+ if portage_checksum.perform_md5(real_dirname+"/"+last_pfile) == newmd5:
+ return old_pfile
+ else:
+ return new_pfile
+ elif newmd5:
+ return new_pfile
+ else:
+ return (new_pfile, old_pfile)
+
+#XXX: These two are now implemented in portage_util.py but are needed here
+#XXX: until the isvalidatom() dependency is sorted out.
+
+def grabdict_package(myfilename,juststrings=0):
+ pkgs=grabdict(myfilename, juststrings=juststrings, empty=1)
+ for x in pkgs.keys():
+ if not isvalidatom(x):
+ del(pkgs[x])
+ writemsg("--- Invalid atom in %s: %s\n" % (myfilename, x))
+ return pkgs
+
+def grabfile_package(myfilename,compatlevel=0):
+ pkgs=grabfile(myfilename,compatlevel)
+ for x in range(len(pkgs)-1,-1,-1):
+ pkg = pkgs[x]
+ if pkg[0] == "-":
+ pkg = pkg[1:]
+ if pkg[0] == "*":
+ pkg = pkg[1:]
+ if not isvalidatom(pkg):
+ writemsg("--- Invalid atom in %s: %s\n" % (myfilename, pkgs[x]))
+ del(pkgs[x])
+ return pkgs
+
+# returns a tuple. (version[string], error[string])
+# They are pretty much mutually exclusive.
+# Either version is a string and error is none, or
+# version is None and error is a string
+#
+def ExtractKernelVersion(base_dir):
+ lines = []
+ pathname = os.path.join(base_dir, 'Makefile')
+ try:
+ f = open(pathname, 'r')
+ except OSError, details:
+ return (None, str(details))
+ except IOError, details:
+ return (None, str(details))
+
+ try:
+ for i in range(4):
+ lines.append(f.readline())
+ except OSError, details:
+ return (None, str(details))
+ except IOError, details:
+ return (None, str(details))
+
+ lines = map(string.strip, lines)
+
+ version = ''
+
+ #XXX: The following code relies on the ordering of vars within the Makefile
+ for line in lines:
+ # split on the '=' then remove annoying whitespace
+ items = string.split(line, '=')
+ items = map(string.strip, items)
+ if items[0] == 'VERSION' or \
+ items[0] == 'PATCHLEVEL':
+ version += items[1]
+ version += "."
+ elif items[0] == 'SUBLEVEL':
+ version += items[1]
+ elif items[0] == 'EXTRAVERSION' and \
+ items[-1] != items[0]:
+ version += items[1]
+
+ # Grab a list of files named localversion* and sort them
+ localversions = os.listdir(base_dir)
+ for x in range(len(localversions)-1,-1,-1):
+ if localversions[x][:12] != "localversion":
+ del localversions[x]
+ localversions.sort()
+
+ # Append the contents of each to the version string, stripping ALL whitespace
+ for lv in localversions:
+ version += string.join(string.split(string.join(grabfile(base_dir+"/"+lv))), "")
+
+ # Check the .config for a CONFIG_LOCALVERSION and append that too, also stripping whitespace
+ kernelconfig = getconfig(base_dir+"/.config")
+ if kernelconfig and kernelconfig.has_key("CONFIG_LOCALVERSION"):
+ version += string.join(string.split(kernelconfig["CONFIG_LOCALVERSION"]), "")
+
+ return (version,None)
+
+
+autouse_val = None
+def autouse(myvartree,use_cache=1):
+ "returns set of USE variables auto-enabled due to packages being installed"
+ global usedefaults, autouse_val
+ if autouse_val is not None:
+ return autouse_val
+ if profiledir==None:
+ autouse_val = ""
+ return ""
+ myusevars=""
+ for myuse in usedefaults:
+ dep_met = True
+ for mydep in usedefaults[myuse]:
+ if not myvartree.dep_match(mydep,use_cache=True):
+ dep_met = False
+ break
+ if dep_met:
+ myusevars += " "+myuse
+ autouse_val = myusevars
+ return myusevars
+
+def check_config_instance(test):
+ if not test or (str(test.__class__) != 'portage.config'):
+ raise TypeError, "Invalid type for config object: %s" % test.__class__
+
+class config:
+ def __init__(self, clone=None, mycpv=None, config_profile_path=None, config_incrementals=None):
+
+ self.already_in_regenerate = 0
+
+ self.locked = 0
+ self.mycpv = None
+ self.puse = []
+ self.modifiedkeys = []
+
+ self.virtuals = {}
+ self.v_count = 0
+
+ # Virtuals obtained from the vartree
+ self.treeVirtuals = {}
+ # Virtuals by user specification. Includes negatives.
+ self.userVirtuals = {}
+ # Virtual negatives from user specifications.
+ self.negVirtuals = {}
+
+ self.user_profile_dir = None
+
+ if clone:
+ self.incrementals = copy.deepcopy(clone.incrementals)
+ self.profile_path = copy.deepcopy(clone.profile_path)
+ self.user_profile_dir = copy.deepcopy(clone.user_profile_dir)
+
+ self.module_priority = copy.deepcopy(clone.module_priority)
+ self.modules = copy.deepcopy(clone.modules)
+
+ self.depcachedir = copy.deepcopy(clone.depcachedir)
+
+ self.packages = copy.deepcopy(clone.packages)
+ self.virtuals = copy.deepcopy(clone.virtuals)
+
+ self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
+ self.userVirtuals = copy.deepcopy(clone.userVirtuals)
+ self.negVirtuals = copy.deepcopy(clone.negVirtuals)
+
+ self.use_defs = copy.deepcopy(clone.use_defs)
+ self.usemask = copy.deepcopy(clone.usemask)
+
+ self.configlist = copy.deepcopy(clone.configlist)
+ self.configlist[-1] = os.environ.copy()
+ self.configdict = { "globals": self.configlist[0],
+ "defaults": self.configlist[1],
+ "conf": self.configlist[2],
+ "pkg": self.configlist[3],
+ "auto": self.configlist[4],
+ "backupenv": self.configlist[5],
+ "env": self.configlist[6] }
+ self.profiles = copy.deepcopy(clone.profiles)
+ self.backupenv = copy.deepcopy(clone.backupenv)
+ self.pusedict = copy.deepcopy(clone.pusedict)
+ self.categories = copy.deepcopy(clone.categories)
+ self.pkeywordsdict = copy.deepcopy(clone.pkeywordsdict)
+ self.pmaskdict = copy.deepcopy(clone.pmaskdict)
+ self.punmaskdict = copy.deepcopy(clone.punmaskdict)
+ self.prevmaskdict = copy.deepcopy(clone.prevmaskdict)
+ self.pprovideddict = copy.deepcopy(clone.pprovideddict)
+ self.lookuplist = copy.deepcopy(clone.lookuplist)
+ self.uvlist = copy.deepcopy(clone.uvlist)
+ self.dirVirtuals = copy.deepcopy(clone.dirVirtuals)
+ self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
+ else:
+ self.depcachedir = DEPCACHE_PATH
+
+ if not config_profile_path:
+ global profiledir
+ writemsg("config_profile_path not specified to class config\n")
+ self.profile_path = profiledir[:]
+ else:
+ self.profile_path = config_profile_path[:]
+
+ if not config_incrementals:
+ writemsg("incrementals not specified to class config\n")
+ self.incrementals = copy.deepcopy(portage_const.INCREMENTALS)
+ else:
+ self.incrementals = copy.deepcopy(config_incrementals)
+
+ self.module_priority = ["user","default"]
+ self.modules = {}
+ self.modules["user"] = getconfig(MODULES_FILE_PATH)
+ if self.modules["user"] == None:
+ self.modules["user"] = {}
+ self.modules["default"] = {
+ "portdbapi.metadbmodule": "portage_db_flat.database",
+ "portdbapi.auxdbmodule": "portage_db_flat.database",
+ "eclass_cache.dbmodule": "portage_db_cpickle.database",
+ }
+
+ self.usemask=[]
+ self.configlist=[]
+ self.backupenv={}
+ # back up our incremental variables:
+ self.configdict={}
+ # configlist will contain: [ globals, defaults, conf, pkg, auto, backupenv (incrementals), origenv ]
+
+ # The symlink might not exist or might not be a symlink.
+ try:
+ self.profiles=[abssymlink(self.profile_path)]
+ except SystemExit, e:
+ raise
+ except:
+ self.profiles=[self.profile_path]
+
+ mypath = self.profiles[0]
+ while os.path.exists(mypath+"/parent"):
+ mypath = os.path.normpath(mypath+"///"+grabfile(mypath+"/parent")[0])
+ if os.path.exists(mypath):
+ self.profiles.insert(0,mypath)
+
+ if os.environ.has_key("PORTAGE_CALLER") and os.environ["PORTAGE_CALLER"] == "repoman":
+ pass
+ else:
+ # XXX: This should depend on ROOT?
+ if os.path.exists("/"+CUSTOM_PROFILE_PATH):
+ self.user_profile_dir = os.path.normpath("/"+"///"+CUSTOM_PROFILE_PATH)
+ self.profiles.append(self.user_profile_dir[:])
+
+ self.packages_list = grab_multiple("packages", self.profiles, grabfile_package)
+ self.packages = stack_lists(self.packages_list, incremental=1)
+ del self.packages_list
+ #self.packages = grab_stacked("packages", self.profiles, grabfile, incremental_lines=1)
+
+ # revmaskdict
+ self.prevmaskdict={}
+ for x in self.packages:
+ mycatpkg=dep_getkey(x)
+ if not self.prevmaskdict.has_key(mycatpkg):
+ self.prevmaskdict[mycatpkg]=[x]
+ else:
+ self.prevmaskdict[mycatpkg].append(x)
+
+ # get profile-masked use flags -- INCREMENTAL Child over parent
+ usemask_lists = grab_multiple("use.mask", self.profiles, grabfile)
+ self.usemask = stack_lists(usemask_lists, incremental=True)
+ del usemask_lists
+ use_defs_lists = grab_multiple("use.defaults", self.profiles, grabdict)
+ self.use_defs = stack_dictlist(use_defs_lists, incremental=True)
+ del use_defs_lists
+
+ try:
+ mygcfg_dlists = grab_multiple("make.globals", self.profiles+["/etc"], getconfig)
+ self.mygcfg = stack_dicts(mygcfg_dlists, incrementals=portage_const.INCREMENTALS, ignore_none=1)
+
+ if self.mygcfg == None:
+ self.mygcfg = {}
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! %s\n" % (e))
+ writemsg("!!! Incorrect multiline literals can cause this. Do not use them.\n")
+ writemsg("!!! Errors in this file should be reported on bugs.gentoo.org.\n")
+ sys.exit(1)
+ self.configlist.append(self.mygcfg)
+ self.configdict["globals"]=self.configlist[-1]
+
+ self.mygcfg = {}
+ if self.profiles:
+ try:
+ mygcfg_dlists = grab_multiple("make.defaults", self.profiles, getconfig)
+ self.mygcfg = stack_dicts(mygcfg_dlists, incrementals=portage_const.INCREMENTALS, ignore_none=1)
+ #self.mygcfg = grab_stacked("make.defaults", self.profiles, getconfig)
+ if self.mygcfg == None:
+ self.mygcfg = {}
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! %s\n" % (e))
+ writemsg("!!! 'rm -Rf /usr/portage/profiles; emerge sync' may fix this. If it does\n")
+ writemsg("!!! not then please report this to bugs.gentoo.org and, if possible, a dev\n")
+ writemsg("!!! on #gentoo (irc.freenode.org)\n")
+ sys.exit(1)
+ self.configlist.append(self.mygcfg)
+ self.configdict["defaults"]=self.configlist[-1]
+
+ try:
+ # XXX: Should depend on root?
+ self.mygcfg=getconfig("/"+MAKE_CONF_FILE,allow_sourcing=True)
+ if self.mygcfg == None:
+ self.mygcfg = {}
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! %s\n" % (e))
+ writemsg("!!! Incorrect multiline literals can cause this. Do not use them.\n")
+ sys.exit(1)
+
+
+ self.configlist.append(self.mygcfg)
+ self.configdict["conf"]=self.configlist[-1]
+
+ self.configlist.append({})
+ self.configdict["pkg"]=self.configlist[-1]
+
+ #auto-use:
+ self.configlist.append({})
+ self.configdict["auto"]=self.configlist[-1]
+
+ #backup-env (for recording our calculated incremental variables:)
+ self.backupenv = os.environ.copy()
+ self.configlist.append(self.backupenv) # XXX Why though?
+ self.configdict["backupenv"]=self.configlist[-1]
+
+ self.configlist.append(os.environ.copy())
+ self.configdict["env"]=self.configlist[-1]
+
+
+ # make lookuplist for loading package.*
+ self.lookuplist=self.configlist[:]
+ self.lookuplist.reverse()
+
+ archlist = grabfile(self["PORTDIR"]+"/profiles/arch.list")
+ self.configdict["conf"]["PORTAGE_ARCHLIST"] = string.join(archlist)
+
+ if os.environ.get("PORTAGE_CALLER","") == "repoman":
+ # repoman shouldn't use local settings.
+ locations = [self["PORTDIR"] + "/profiles"]
+ self.pusedict = {}
+ self.pkeywordsdict = {}
+ self.punmaskdict = {}
+ else:
+ locations = [self["PORTDIR"] + "/profiles", USER_CONFIG_PATH]
+ for ov in self["PORTDIR_OVERLAY"].split():
+ ov = os.path.normpath(ov)
+ if os.path.isdir(ov+"/profiles"):
+ locations.append(ov+"/profiles")
+
+ pusedict=grabdict_package(USER_CONFIG_PATH+"/package.use")
+ self.pusedict = {}
+ for key in pusedict.keys():
+ cp = dep_getkey(key)
+ if not self.pusedict.has_key(cp):
+ self.pusedict[cp] = {}
+ self.pusedict[cp][key] = pusedict[key]
+
+ #package.keywords
+ pkgdict=grabdict_package(USER_CONFIG_PATH+"/package.keywords")
+ self.pkeywordsdict = {}
+ for key in pkgdict.keys():
+ # default to ~arch if no specific keyword is given
+ if not pkgdict[key]:
+ mykeywordlist = []
+ if self.configdict["defaults"] and self.configdict["defaults"].has_key("ACCEPT_KEYWORDS"):
+ groups = self.configdict["defaults"]["ACCEPT_KEYWORDS"].split()
+ else:
+ groups = []
+ for keyword in groups:
+ if not keyword[0] in "~-":
+ mykeywordlist.append("~"+keyword)
+ pkgdict[key] = mykeywordlist
+ cp = dep_getkey(key)
+ if not self.pkeywordsdict.has_key(cp):
+ self.pkeywordsdict[cp] = {}
+ self.pkeywordsdict[cp][key] = pkgdict[key]
+
+ #package.unmask
+ pkgunmasklines = grabfile_package(USER_CONFIG_PATH+"/package.unmask")
+ self.punmaskdict = {}
+ for x in pkgunmasklines:
+ mycatpkg=dep_getkey(x)
+ if self.punmaskdict.has_key(mycatpkg):
+ self.punmaskdict[mycatpkg].append(x)
+ else:
+ self.punmaskdict[mycatpkg]=[x]
+
+ #getting categories from an external file now
+ categories = grab_multiple("categories", locations, grabfile)
+ self.categories = stack_lists(categories, incremental=1)
+ del categories
+
+ # get virtuals -- needs categories
+ self.loadVirtuals('/')
+
+ #package.mask
+ pkgmasklines = grab_multiple("package.mask", self.profiles + locations, grabfile_package)
+ pkgmasklines = stack_lists(pkgmasklines, incremental=1)
+
+ self.pmaskdict = {}
+ for x in pkgmasklines:
+ mycatpkg=dep_getkey(x)
+ if self.pmaskdict.has_key(mycatpkg):
+ self.pmaskdict[mycatpkg].append(x)
+ else:
+ self.pmaskdict[mycatpkg]=[x]
+
+ pkgprovidedlines = grab_multiple("package.provided", self.profiles, grabfile)
+ pkgprovidedlines = stack_lists(pkgprovidedlines, incremental=1)
+ for x in range(len(pkgprovidedlines)-1, -1, -1):
+ cpvr = catpkgsplit(pkgprovidedlines[x])
+ if not cpvr or cpvr[0] == "null":
+ writemsg("Invalid package name in package.provided: "+pkgprovidedlines[x]+"\n")
+ del pkgprovidedlines[x]
+
+ self.pprovideddict = {}
+ for x in pkgprovidedlines:
+ cpv=catpkgsplit(x)
+ if not x:
+ continue
+ mycatpkg=dep_getkey(x)
+ if self.pprovideddict.has_key(mycatpkg):
+ self.pprovideddict[mycatpkg].append(x)
+ else:
+ self.pprovideddict[mycatpkg]=[x]
+
+ self.lookuplist=self.configlist[:]
+ self.lookuplist.reverse()
+
+ useorder=self["USE_ORDER"]
+ if not useorder:
+ # reasonable defaults; this is important as without USE_ORDER,
+ # USE will always be "" (nothing set)!
+ useorder="env:pkg:conf:auto:defaults"
+ useordersplit=useorder.split(":")
+
+ self.uvlist=[]
+ for x in useordersplit:
+ if self.configdict.has_key(x):
+ if "PKGUSE" in self.configdict[x].keys():
+ del self.configdict[x]["PKGUSE"] # Delete PkgUse, Not legal to set.
+ #prepend db to list to get correct order
+ self.uvlist[0:0]=[self.configdict[x]]
+
+ self.configdict["env"]["PORTAGE_GID"]=str(portage_gid)
+ self.backupenv["PORTAGE_GID"]=str(portage_gid)
+
+ if self.has_key("PORT_LOGDIR") and not self["PORT_LOGDIR"]:
+ # port_logdir is defined, but empty. this causes a traceback in doebuild.
+ writemsg(yellow("!!!")+" PORT_LOGDIR was defined, but set to nothing.\n")
+ writemsg(yellow("!!!")+" Disabling it. Please set it to a non null value.\n")
+ del self["PORT_LOGDIR"]
+
+ if self["PORTAGE_CACHEDIR"]:
+ # XXX: Deprecated -- April 15 -- NJ
+ writemsg(yellow(">>> PORTAGE_CACHEDIR has been deprecated!")+"\n")
+ writemsg(">>> Please use PORTAGE_DEPCACHEDIR instead.\n")
+ self.depcachedir = self["PORTAGE_CACHEDIR"]
+ del self["PORTAGE_CACHEDIR"]
+
+ if self["PORTAGE_DEPCACHEDIR"]:
+ #the auxcache is the only /var/cache/edb/ entry that stays at / even when "root" changes.
+ # XXX: Could move with a CHROOT functionality addition.
+ self.depcachedir = self["PORTAGE_DEPCACHEDIR"]
+ del self["PORTAGE_DEPCACHEDIR"]
+
+ overlays = string.split(self["PORTDIR_OVERLAY"])
+ if overlays:
+ new_ov=[]
+ for ov in overlays:
+ ov=os.path.normpath(ov)
+ if os.path.isdir(ov):
+ new_ov.append(ov)
+ else:
+ writemsg(red("!!! Invalid PORTDIR_OVERLAY (not a dir): "+ov+"\n"))
+ self["PORTDIR_OVERLAY"] = string.join(new_ov)
+ self.backup_changes("PORTDIR_OVERLAY")
+
+ self.regenerate()
+
+ self.features = portage_util.unique_array(self["FEATURES"].split())
+
+ #XXX: Should this be temporary? Is it possible at all to have a default?
+ if "gpg" in self.features:
+ if not os.path.exists(self["PORTAGE_GPG_DIR"]) or not os.path.isdir(self["PORTAGE_GPG_DIR"]):
+ writemsg("PORTAGE_GPG_DIR is invalid. Removing gpg from FEATURES.\n")
+ self.features.remove("gpg")
+
+ if "maketest" in self.features and "test" not in self.features:
+ self.features.append("test")
+
+ if not portage_exec.sandbox_capable and ("sandbox" in self.features or "usersandbox" in self.features):
+ writemsg(red("!!! Problem with sandbox binary. Disabling...\n\n"))
+ if "sandbox" in self.features:
+ self.features.remove("sandbox")
+ if "usersandbox" in self.features:
+ self.features.remove("usersandbox")
+
+ self.features.sort()
+ self["FEATURES"] = " ".join(["-*"]+self.features)
+ self.backup_changes("FEATURES")
+
+ if not len(self["CBUILD"]) and len(self["CHOST"]):
+ self["CBUILD"] = self["CHOST"]
+ self.backup_changes("CBUILD")
+
+ if mycpv:
+ self.setcpv(mycpv)
+
+ def loadVirtuals(self,root):
+ self.virtuals = self.getvirtuals(root)
+
+ def load_best_module(self,property_string):
+ best_mod = best_from_dict(property_string,self.modules,self.module_priority)
+ return load_mod(best_mod)
+
+ def lock(self):
+ self.locked = 1
+
+ def unlock(self):
+ self.locked = 0
+
+ def modifying(self):
+ if self.locked:
+ raise Exception, "Configuration is locked."
+
+ def backup_changes(self,key=None):
+ if key and self.configdict["env"].has_key(key):
+ self.backupenv[key] = copy.deepcopy(self.configdict["env"][key])
+ else:
+ raise KeyError, "No such key defined in environment: %s" % key
+
+ def reset(self,keeping_pkg=0,use_cache=1):
+ "reset environment to original settings"
+ for x in self.configlist[-1].keys():
+ if x not in self.backupenv.keys():
+ del self.configlist[-1][x]
+
+ self.configdict["env"].update(self.backupenv)
+
+ self.modifiedkeys = []
+ if not keeping_pkg:
+ self.puse = ""
+ self.configdict["pkg"].clear()
+ self.regenerate(use_cache=use_cache)
+
+ def load_infodir(self,infodir):
+ if self.configdict.has_key("pkg"):
+ for x in self.configdict["pkg"].keys():
+ del self.configdict["pkg"][x]
+ else:
+ writemsg("No pkg setup for settings instance?\n")
+ sys.exit(17)
+
+ if os.path.exists(infodir):
+ if os.path.exists(infodir+"/environment"):
+ self.configdict["pkg"]["PORT_ENV_FILE"] = infodir+"/environment"
+
+ myre = re.compile('^[A-Z]+$')
+ for filename in listdir(infodir,filesonly=1,EmptyOnError=1):
+ if myre.match(filename):
+ try:
+ mydata = string.strip(open(infodir+"/"+filename).read())
+ if len(mydata)<2048:
+ if filename == "USE":
+ self.configdict["pkg"][filename] = "-* "+mydata
+ else:
+ self.configdict["pkg"][filename] = mydata
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("!!! Unable to read file: %s\n" % infodir+"/"+filename)
+ pass
+ return 1
+ return 0
+
+ def setcpv(self,mycpv,use_cache=1):
+ self.modifying()
+ self.mycpv = mycpv
+ cp = dep_getkey(mycpv)
+ newpuse = ""
+ if self.pusedict.has_key(cp):
+ self.pusekey = best_match_to_list(self.mycpv, self.pusedict[cp].keys())
+ if self.pusekey:
+ newpuse = string.join(self.pusedict[cp][self.pusekey])
+ if newpuse == self.puse:
+ return
+ self.puse = newpuse
+ self.configdict["pkg"]["PKGUSE"] = self.puse[:] # For saving to PUSE file
+ self.configdict["pkg"]["USE"] = self.puse[:] # this gets appended to USE
+ self.reset(keeping_pkg=1,use_cache=use_cache)
+
+ def setinst(self,mycpv,mydbapi):
+ # Grab the virtuals this package provides and add them into the tree virtuals.
+ provides = mydbapi.aux_get(mycpv, ["PROVIDE"])[0]
+ if isinstance(mydbapi, portdbapi):
+ myuse = self["USE"]
+ else:
+ myuse = mydbapi.aux_get(mycpv, ["USE"])[0]
+ virts = flatten(portage_dep.use_reduce(portage_dep.paren_reduce(provides), uselist=myuse.split()))
+
+ cp = dep_getkey(mycpv)
+ for virt in virts:
+ virt = dep_getkey(virt)
+ if not self.treeVirtuals.has_key(virt):
+ self.treeVirtuals[virt] = []
+ # XXX: Is this bad? -- It's a permanent modification
+ self.treeVirtuals[virt] = portage_util.unique_array(self.treeVirtuals[virt]+[cp])
+
+ self.virtuals = self.__getvirtuals_compile()
+
+
+ def regenerate(self,useonly=0,use_cache=1):
+ global usesplit,profiledir
+
+ if self.already_in_regenerate:
+ # XXX: THIS REALLY NEEDS TO GET FIXED. autouse() loops.
+ writemsg("!!! Looping in regenerate.\n",1)
+ return
+ else:
+ self.already_in_regenerate = 1
+
+ if useonly:
+ myincrementals=["USE"]
+ else:
+ myincrementals=portage_const.INCREMENTALS
+ for mykey in myincrementals:
+ if mykey=="USE":
+ mydbs=self.uvlist
+ # XXX Global usage of db... Needs to go away somehow.
+ if db.has_key(root) and db[root].has_key("vartree"):
+ self.configdict["auto"]["USE"]=autouse(db[root]["vartree"],use_cache=use_cache)
+ else:
+ self.configdict["auto"]["USE"]=""
+ else:
+ mydbs=self.configlist[:-1]
+
+ myflags=[]
+ for curdb in mydbs:
+ if not curdb.has_key(mykey):
+ continue
+ #variables are already expanded
+ mysplit=curdb[mykey].split()
+
+ for x in mysplit:
+ if x=="-*":
+ # "-*" is a special "minus" var that means "unset all settings".
+ # so USE="-* gnome" will have *just* gnome enabled.
+ myflags=[]
+ continue
+
+ if x[0]=="+":
+ # Not legal. People assume too much. Complain.
+ writemsg(red("USE flags should not start with a '+': %s\n" % x))
+ x=x[1:]
+
+ if (x[0]=="-"):
+ if (x[1:] in myflags):
+ # Unset/Remove it.
+ del myflags[myflags.index(x[1:])]
+ continue
+
+ # We got here, so add it now.
+ if x not in myflags:
+ myflags.append(x)
+
+ myflags.sort()
+ #store setting in last element of configlist, the original environment:
+ self.configlist[-1][mykey]=string.join(myflags," ")
+ del myflags
+
+ #cache split-up USE var in a global
+ usesplit=[]
+
+ for x in string.split(self.configlist[-1]["USE"]):
+ if x not in self.usemask:
+ usesplit.append(x)
+
+ if self.has_key("USE_EXPAND"):
+ for var in string.split(self["USE_EXPAND"]):
+ if self.has_key(var):
+ for x in string.split(self[var]):
+ mystr = string.lower(var)+"_"+x
+ if mystr not in usesplit:
+ usesplit.append(mystr)
+
+ # Pre-Pend ARCH variable to USE settings so '-*' in env doesn't kill arch.
+ if self.configdict["defaults"].has_key("ARCH"):
+ if self.configdict["defaults"]["ARCH"]:
+ if self.configdict["defaults"]["ARCH"] not in usesplit:
+ usesplit.insert(0,self.configdict["defaults"]["ARCH"])
+
+ self.configlist[-1]["USE"]=string.join(usesplit," ")
+
+ self.already_in_regenerate = 0
+
+ def getvirtuals(self, myroot):
+ myvirts = {}
+
+ # This breaks catalyst/portage when setting to a fresh/empty root.
+ # Virtuals cannot be calculated because there is nothing to work
+ # from. So the only ROOT prefixed dir should be local configs.
+ #myvirtdirs = prefix_array(self.profiles,myroot+"/")
+ myvirtdirs = copy.deepcopy(self.profiles)
+ while self.user_profile_dir in myvirtdirs:
+ myvirtdirs.remove(self.user_profile_dir)
+
+
+ # Rules
+ # R1: Collapse profile virtuals
+ # R2: Extract user-negatives.
+ # R3: Collapse user-virtuals.
+ # R4: Apply user negatives to all except user settings.
+
+ # Order of preference:
+ # 1. user-declared that are installed
+ # 3. installed and in profile
+ # 4. installed
+ # 2. user-declared set
+ # 5. profile
+
+ self.dirVirtuals = grab_multiple("virtuals", myvirtdirs, grabdict)
+ self.dirVirtuals.reverse()
+
+ if self.user_profile_dir and os.path.exists(self.user_profile_dir+"/virtuals"):
+ self.userVirtuals = grabdict(self.user_profile_dir+"/virtuals")
+
+ # Store all the negatives for later.
+ for x in self.userVirtuals.keys():
+ self.negVirtuals[x] = []
+ for y in self.userVirtuals[x]:
+ if y[0] == '-':
+ self.negVirtuals[x].append(y[:])
+
+ # Collapse the user virtuals so that we don't deal with negatives.
+ self.userVirtuals = stack_dictlist([self.userVirtuals],incremental=1)
+
+ # Collapse all the profile virtuals including user negations.
+ self.dirVirtuals = stack_dictlist([self.negVirtuals]+self.dirVirtuals,incremental=1)
+
+ # Repoman does not use user or tree virtuals.
+ if os.environ.get("PORTAGE_CALLER","") != "repoman":
+ # XXX: vartree does not use virtuals, does user set matter?
+ temp_vartree = vartree(myroot,self.dirVirtuals,categories=self.categories)
+ # Reduce the provides into a list by CP.
+ self.treeVirtuals = map_dictlist_vals(getCPFromCPV,temp_vartree.get_all_provides())
+
+ return self.__getvirtuals_compile()
+
+ def __getvirtuals_compile(self):
+ """Actually generate the virtuals we have collected.
+ The results are reversed so the list order is left to right.
+ Given data is [Best,Better,Good] sets of [Good, Better, Best]"""
+
+ # Virtuals by profile+tree preferences.
+ ptVirtuals = {}
+ # Virtuals by user+tree preferences.
+ utVirtuals = {}
+
+ # If a user virtual is already installed, we preference it.
+ for x in self.userVirtuals.keys():
+ utVirtuals[x] = []
+ if self.treeVirtuals.has_key(x):
+ for y in self.userVirtuals[x]:
+ if y in self.treeVirtuals[x]:
+ utVirtuals[x].append(y)
+ #print "F:",utVirtuals
+ #utVirtuals[x].reverse()
+ #print "R:",utVirtuals
+
+ # If a profile virtual is already installed, we preference it.
+ for x in self.dirVirtuals.keys():
+ ptVirtuals[x] = []
+ if self.treeVirtuals.has_key(x):
+ for y in self.dirVirtuals[x]:
+ if y in self.treeVirtuals[x]:
+ ptVirtuals[x].append(y)
+
+ # UserInstalled, ProfileInstalled, Installed, User, Profile
+ biglist = [utVirtuals, ptVirtuals, self.treeVirtuals,
+ self.userVirtuals, self.dirVirtuals]
+
+ # We reverse each dictlist so that the order matches everything
+ # else in portage. [-*, a, b] [b, c, d] ==> [b, a]
+ for dictlist in biglist:
+ for key in dictlist:
+ dictlist[key].reverse()
+
+ # User settings and profile settings take precedence over tree.
+ val = stack_dictlist(biglist,incremental=1)
+
+ return val
+
+ def __delitem__(self,mykey):
+ for x in self.lookuplist:
+ if x != None:
+ if mykey in x:
+ del x[mykey]
+
+ def __getitem__(self,mykey):
+ match = ''
+ for x in self.lookuplist:
+ if x == None:
+ writemsg("!!! lookuplist is null.\n")
+ elif x.has_key(mykey):
+ match = x[mykey]
+ break
+
+ if 0 and match and mykey in ["PORTAGE_BINHOST"]:
+ # These require HTTP Encoding
+ try:
+ import urllib
+ if urllib.unquote(match) != match:
+ writemsg("Note: %s already contains escape codes." % (mykey))
+ else:
+ match = urllib.quote(match)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("Failed to fix %s using urllib, attempting to continue.\n" % (mykey))
+ pass
+
+ elif mykey == "CONFIG_PROTECT_MASK":
+ match += " /etc/env.d"
+
+ return match
+
+ def has_key(self,mykey):
+ for x in self.lookuplist:
+ if x.has_key(mykey):
+ return 1
+ return 0
+
+ def keys(self):
+ mykeys=[]
+ for x in self.lookuplist:
+ for y in x.keys():
+ if y not in mykeys:
+ mykeys.append(y)
+ return mykeys
+
+ def __setitem__(self,mykey,myvalue):
+ "set a value; will be thrown away at reset() time"
+ if type(myvalue) != types.StringType:
+ raise ValueError("Invalid type being used as a value: '%s': '%s'" % (str(mykey),str(myvalue)))
+ self.modifying()
+ self.modifiedkeys += [mykey]
+ self.configdict["env"][mykey]=myvalue
+
+ def environ(self):
+ "return our locally-maintained environment"
+ mydict={}
+ for x in self.keys():
+ mydict[x]=self[x]
+ if not mydict.has_key("HOME") and mydict.has_key("BUILD_PREFIX"):
+ writemsg("*** HOME not set. Setting to "+mydict["BUILD_PREFIX"]+"\n")
+ mydict["HOME"]=mydict["BUILD_PREFIX"][:]
+
+ return mydict
+
+
+# XXX This would be to replace getstatusoutput completely.
+# XXX Issue: cannot block execution. Deadlock condition.
+def spawn(mystring,mysettings,debug=0,free=0,droppriv=0,fd_pipes=None,**keywords):
+ """spawn a subprocess with optional sandbox protection,
+ depending on whether sandbox is enabled. The "free" argument,
+ when set to 1, will disable sandboxing. This allows us to
+ spawn processes that are supposed to modify files outside of the
+ sandbox. We can't use os.system anymore because it messes up
+ signal handling. Using spawn allows our Portage signal handler
+ to work."""
+
+ if type(mysettings) == types.DictType:
+ env=mysettings
+ keywords["opt_name"]="[ %s ]" % "portage"
+ else:
+ check_config_instance(mysettings)
+ env=mysettings.environ()
+ keywords["opt_name"]="[%s]" % mysettings["PF"]
+
+ # XXX: Negative RESTRICT word
+ droppriv=(droppriv and ("userpriv" in features) and not \
+ (("nouserpriv" in string.split(mysettings["RESTRICT"])) or \
+ ("userpriv" in string.split(mysettings["RESTRICT"]))))
+
+ if droppriv and not uid and portage_gid and portage_uid:
+ keywords.update({"uid":portage_uid,"gid":portage_gid,"groups":[portage_gid],"umask":002})
+
+ if not free:
+ free=((droppriv and "usersandbox" not in features) or \
+ (not droppriv and "sandbox" not in features and "usersandbox" not in features))
+
+ if not free:
+ keywords["opt_name"] += " sandbox"
+ return portage_exec.spawn_sandbox(mystring,env=env,**keywords)
+ else:
+ keywords["opt_name"] += " bash"
+ return portage_exec.spawn_bash(mystring,env=env,**keywords)
+
+
+
+def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks",use_locks=1, try_mirrors=1):
+ "fetch files. Will use digest file if available."
+
+ # 'nomirror' is bad/negative logic. You Restrict mirroring, not no-mirroring.
+ if ("mirror" in mysettings["RESTRICT"].split()) or \
+ ("nomirror" in mysettings["RESTRICT"].split()):
+ if ("mirror" in features) and ("lmirror" not in features):
+ # lmirror should allow you to bypass mirror restrictions.
+ # XXX: This is not a good thing, and is temporary at best.
+ print ">>> \"mirror\" mode desired and \"mirror\" restriction found; skipping fetch."
+ return 1
+
+ global thirdpartymirrors
+
+ check_config_instance(mysettings)
+
+ custommirrors=grabdict(CUSTOM_MIRRORS_FILE)
+
+ mymirrors=[]
+
+ if listonly or ("distlocks" not in features):
+ use_locks = 0
+
+ fetch_to_ro = 0
+ if "skiprocheck" in features:
+ fetch_to_ro = 1
+
+ if not os.access(mysettings["DISTDIR"],os.W_OK) and fetch_to_ro:
+ if use_locks:
+ writemsg(red("!!! You are fetching to a read-only filesystem, you should turn locking off"));
+ writemsg("!!! This can be done by adding -distlocks to FEATURES in /etc/make.conf");
+# use_locks = 0
+
+ # local mirrors are always added
+ if custommirrors.has_key("local"):
+ mymirrors += custommirrors["local"]
+
+ if ("nomirror" in mysettings["RESTRICT"].split()) or \
+ ("mirror" in mysettings["RESTRICT"].split()):
+ # We don't add any mirrors.
+ pass
+ else:
+ if try_mirrors:
+ for x in mysettings["GENTOO_MIRRORS"].split():
+ if x:
+ if x[-1] == '/':
+ mymirrors += [x[:-1]]
+ else:
+ mymirrors += [x]
+
+ mydigests = {}
+ digestfn = mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+ if os.path.exists(digestfn):
+ mydigests = digestParseFile(digestfn)
+
+ fsmirrors = []
+ for x in range(len(mymirrors)-1,-1,-1):
+ if mymirrors[x] and mymirrors[x][0]=='/':
+ fsmirrors += [mymirrors[x]]
+ del mymirrors[x]
+
+ for myuri in myuris:
+ myfile=os.path.basename(myuri)
+ try:
+ destdir = mysettings["DISTDIR"]+"/"
+ if not os.path.exists(destdir+myfile):
+ for mydir in fsmirrors:
+ if os.path.exists(mydir+"/"+myfile):
+ writemsg(_("Local mirror has file: %(file)s\n" % {"file":myfile}))
+ shutil.copyfile(mydir+"/"+myfile,destdir+"/"+myfile)
+ break
+ except (OSError,IOError),e:
+ # file does not exist
+ writemsg(_("!!! %(file)s not found in %(dir)s\n") % {"file":myfile, "dir":mysettings["DISTDIR"]})
+ gotit=0
+
+ if "fetch" in mysettings["RESTRICT"].split():
+ # fetch is restricted. Ensure all files have already been downloaded; otherwise,
+ # print message and exit.
+ gotit=1
+ for myuri in myuris:
+ myfile=os.path.basename(myuri)
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/"+myfile)
+ except (OSError,IOError),e:
+ # file does not exist
+ writemsg(_("!!! %(file)s not found in %(dir)s\n") % {"file":myfile, "dir":mysettings["DISTDIR"]})
+ gotit=0
+ if not gotit:
+ print
+ print "!!!",mysettings["CATEGORY"]+"/"+mysettings["PF"],"has fetch restriction turned on."
+ print "!!! This probably means that this ebuild's files must be downloaded"
+ print "!!! manually. See the comments in the ebuild for more information."
+ print
+ spawn(EBUILD_SH_BINARY+" nofetch",mysettings)
+ return 0
+ return 1
+ locations=mymirrors[:]
+ filedict={}
+ primaryuri_indexes={}
+ for myuri in myuris:
+ myfile=os.path.basename(myuri)
+ if not filedict.has_key(myfile):
+ filedict[myfile]=[]
+ for y in range(0,len(locations)):
+ filedict[myfile].append(locations[y]+"/distfiles/"+myfile)
+ if myuri[:9]=="mirror://":
+ eidx = myuri.find("/", 9)
+ if eidx != -1:
+ mirrorname = myuri[9:eidx]
+
+ # Try user-defined mirrors first
+ if custommirrors.has_key(mirrorname):
+ for cmirr in custommirrors[mirrorname]:
+ filedict[myfile].append(cmirr+"/"+myuri[eidx+1:])
+ # remove the mirrors we tried from the list of official mirrors
+ if cmirr.strip() in thirdpartymirrors[mirrorname]:
+ thirdpartymirrors[mirrorname].remove(cmirr)
+ # now try the official mirrors
+ if thirdpartymirrors.has_key(mirrorname):
+ try:
+ shuffle(thirdpartymirrors[mirrorname])
+ except SystemExit, e:
+ raise
+ except:
+ writemsg(red("!!! YOU HAVE A BROKEN PYTHON/GLIBC.\n"))
+ writemsg( "!!! You are most likely on a pentium4 box and have specified -march=pentium4\n")
+ writemsg( "!!! or -fpmath=sse2. GCC was generating invalid sse2 instructions in versions\n")
+ writemsg( "!!! prior to 3.2.3. Please merge the latest gcc or rebuid python with either\n")
+ writemsg( "!!! -march=pentium3 or set -mno-sse2 in your cflags.\n\n\n")
+ time.sleep(10)
+
+ for locmirr in thirdpartymirrors[mirrorname]:
+ filedict[myfile].append(locmirr+"/"+myuri[eidx+1:])
+
+ if not filedict[myfile]:
+ writemsg("No known mirror by the name: %s\n" % (mirrorname))
+ else:
+ writemsg("Invalid mirror definition in SRC_URI:\n")
+ writemsg(" %s\n" % (myuri))
+ else:
+ if "primaryuri" in mysettings["RESTRICT"].split():
+ # Use the source site first.
+ if primaryuri_indexes.has_key(myfile):
+ primaryuri_indexes[myfile] += 1
+ else:
+ primaryuri_indexes[myfile] = 0
+ filedict[myfile].insert(primaryuri_indexes[myfile], myuri)
+ else:
+ filedict[myfile].append(myuri)
+
+ missingSourceHost = False
+ for myfile in filedict.keys(): # Gives a list, not just the first one
+ if not filedict[myfile]:
+ writemsg("Warning: No mirrors available for file '%s'\n" % (myfile))
+ missingSourceHost = True
+ if missingSourceHost:
+ return 0
+ del missingSourceHost
+
+ can_fetch=True
+ if not os.access(mysettings["DISTDIR"]+"/",os.W_OK):
+ if not fetch_to_ro:
+ print "!!! No write access to %s" % mysettings["DISTDIR"]+"/"
+ can_fetch=False
+ else:
+ mystat=os.stat(mysettings["DISTDIR"]+"/")
+ if mystat.st_gid != portage_gid:
+ try:
+ os.chown(mysettings["DISTDIR"],-1,portage_gid)
+ except OSError, oe:
+ if oe.errno == 1:
+ print red("!!!")+" Unable to chgrp of %s to portage, continuing\n" % mysettings["DISTDIR"]
+ else:
+ raise oe
+
+ # writable by portage_gid? This is specific to root, adjust perms if needed automatically.
+ if not stat.S_IMODE(mystat.st_mode) & 020:
+ try:
+ os.chmod(mysettings["DISTDIR"],stat.S_IMODE(mystat.st_mode) | 020)
+ except OSError, oe:
+ if oe.errno == 1:
+ print red("!!!")+" Unable to chmod %s to perms 0755. Non-root users will experience issues.\n" % mysettings["DISTDIR"]
+ else:
+ raise oe
+
+ if use_locks and locks_in_subdir:
+ if os.path.exists(mysettings["DISTDIR"]+"/"+locks_in_subdir):
+ if not os.access(mysettings["DISTDIR"]+"/"+locks_in_subdir,os.W_OK):
+ writemsg("!!! No write access to write to %s. Aborting.\n" % mysettings["DISTDIR"]+"/"+locks_in_subdir)
+ return 0
+ else:
+ old_umask=os.umask(0002)
+ os.mkdir(mysettings["DISTDIR"]+"/"+locks_in_subdir,0775)
+ if os.stat(mysettings["DISTDIR"]+"/"+locks_in_subdir).st_gid != portage_gid:
+ try:
+ os.chown(mysettings["DISTDIR"]+"/"+locks_in_subdir,-1,portage_gid)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ os.umask(old_umask)
+
+
+ for myfile in filedict.keys():
+ fetched=0
+ file_lock = None
+ if listonly:
+ writemsg("\n")
+ else:
+ if use_locks and can_fetch:
+ if locks_in_subdir:
+ file_lock = portage_locks.lockfile(mysettings["DISTDIR"]+"/"+locks_in_subdir+"/"+myfile,wantnewlockfile=1)
+ else:
+ file_lock = portage_locks.lockfile(mysettings["DISTDIR"]+"/"+myfile,wantnewlockfile=1)
+ try:
+ for loc in filedict[myfile]:
+ if listonly:
+ writemsg(loc+" ")
+ continue
+ # allow different fetchcommands per protocol
+ protocol = loc[0:loc.find("://")]
+ if mysettings.has_key("FETCHCOMMAND_"+protocol.upper()):
+ fetchcommand=mysettings["FETCHCOMMAND_"+protocol.upper()]
+ else:
+ fetchcommand=mysettings["FETCHCOMMAND"]
+ if mysettings.has_key("RESUMECOMMAND_"+protocol.upper()):
+ resumecommand=mysettings["RESUMECOMMAND_"+protocol.upper()]
+ else:
+ resumecommand=mysettings["RESUMECOMMAND"]
+
+ fetchcommand=string.replace(fetchcommand,"${DISTDIR}",mysettings["DISTDIR"])
+ resumecommand=string.replace(resumecommand,"${DISTDIR}",mysettings["DISTDIR"])
+
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/"+myfile)
+ if mydigests.has_key(myfile):
+ #if we have the digest file, we know the final size and can resume the download.
+ if mystat[stat.ST_SIZE]<mydigests[myfile]["size"]:
+ fetched=1
+ else:
+ #we already have it downloaded, skip.
+ #if our file is bigger than the recorded size, digestcheck should catch it.
+ if not fetchonly:
+ fetched=2
+ else:
+ # Check md5sum's at each fetch for fetchonly.
+ verified_ok,reason = portage_checksum.verify_all(mysettings["DISTDIR"]+"/"+myfile, mydigests[myfile])
+ if not verified_ok:
+ writemsg("!!! Previously fetched file: "+str(myfile)+"\n!!! Reason: "+reason+"\nRefetching...\n\n")
+ os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+ fetched=0
+ else:
+ for x_key in mydigests[myfile].keys():
+ writemsg(">>> Previously fetched file: "+str(myfile)+" "+x_key+" ;-)\n")
+ fetched=2
+ break #No need to keep looking for this file, we have it!
+ else:
+ #we don't have the digest file, but the file exists. Assume it is fully downloaded.
+ fetched=2
+ except (OSError,IOError),e:
+ writemsg("An exception was caught(1)...\nFailing the download: %s.\n" % (str(e)),1)
+ fetched=0
+
+ if not can_fetch:
+ if fetched != 2:
+ if fetched == 0:
+ writemsg("!!! File %s isn't fetched but unable to get it.\n" % myfile)
+ else:
+ writemsg("!!! File %s isn't fully fetched, but unable to complete it\n" % myfile)
+ return 0
+ else:
+ continue
+
+ # check if we can actually write to the directory/existing file.
+ if fetched!=2 and os.path.exists(mysettings["DISTDIR"]+"/"+myfile) != \
+ os.access(mysettings["DISTDIR"]+"/"+myfile, os.W_OK) and not fetch_to_ro:
+ writemsg(red("***")+" Lack write access to %s, failing fetch\n" % str(mysettings["DISTDIR"]+"/"+myfile))
+ fetched=0
+ break
+ elif fetched!=2:
+ #we either need to resume or start the download
+ #you can't use "continue" when you're inside a "try" block
+ if fetched==1:
+ #resume mode:
+ writemsg(">>> Resuming download...\n")
+ locfetch=resumecommand
+ else:
+ #normal mode:
+ locfetch=fetchcommand
+ writemsg(">>> Downloading "+str(loc)+"\n")
+ myfetch=string.replace(locfetch,"${URI}",loc)
+ myfetch=string.replace(myfetch,"${FILE}",myfile)
+ try:
+ if selinux_enabled:
+ con=selinux.getcontext()
+ con=string.replace(con,mysettings["PORTAGE_T"],mysettings["PORTAGE_FETCH_T"])
+ selinux.setexec(con)
+ myret=spawn(myfetch,mysettings,free=1, droppriv=("userfetch" in mysettings.features))
+ selinux.setexec(None)
+ else:
+ myret=spawn(myfetch,mysettings,free=1, droppriv=("userfetch" in mysettings.features))
+ finally:
+ #if root, -always- set the perms.
+ if os.path.exists(mysettings["DISTDIR"]+"/"+myfile) and (fetched != 1 or os.getuid() == 0) \
+ and os.access(mysettings["DISTDIR"]+"/",os.W_OK):
+ if os.stat(mysettings["DISTDIR"]+"/"+myfile).st_gid != portage_gid:
+ try:
+ os.chown(mysettings["DISTDIR"]+"/"+myfile,-1,portage_gid)
+ except SystemExit, e:
+ raise
+ except:
+ portage_util.writemsg("chown failed on distfile: " + str(myfile))
+ os.chmod(mysettings["DISTDIR"]+"/"+myfile,0664)
+
+ if mydigests!=None and mydigests.has_key(myfile):
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/"+myfile)
+ # no exception? file exists. let digestcheck() report
+ # an appropriately for size or md5 errors
+ if (mystat[stat.ST_SIZE]<mydigests[myfile]["size"]):
+ # Fetch failed... Try the next one... Kill 404 files though.
+ if (mystat[stat.ST_SIZE]<100000) and (len(myfile)>4) and not ((myfile[-5:]==".html") or (myfile[-4:]==".htm")):
+ html404=re.compile("<title>.*(not found|404).*</title>",re.I|re.M)
+ try:
+ if html404.search(open(mysettings["DISTDIR"]+"/"+myfile).read()):
+ try:
+ os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+ writemsg(">>> Deleting invalid distfile. (Improper 404 redirect from server.)\n")
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ continue
+ if not fetchonly:
+ fetched=2
+ break
+ else:
+ # File is the correct size--check the MD5 sum for the fetched
+ # file NOW, for those users who don't have a stable/continuous
+ # net connection. This way we have a chance to try to download
+ # from another mirror...
+ verified_ok,reason = portage_checksum.verify_all(mysettings["DISTDIR"]+"/"+myfile, mydigests[myfile])
+ if not verified_ok:
+ writemsg("!!! Fetched file: "+str(myfile)+" VERIFY FAILED!\n!!! Reason: "+reason+"\nRemoving corrupt distfile...\n")
+ os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+ fetched=0
+ else:
+ for x_key in mydigests[myfile].keys():
+ writemsg(">>> "+str(myfile)+" "+x_key+" ;-)\n")
+ fetched=2
+ break
+ except (OSError,IOError),e:
+ writemsg("An exception was caught(2)...\nFailing the download: %s.\n" % (str(e)),1)
+ fetched=0
+ else:
+ if not myret:
+ fetched=2
+ break
+ elif mydigests!=None:
+ writemsg("No digest file available and download failed.\n\n")
+ finally:
+ if use_locks and file_lock:
+ portage_locks.unlockfile(file_lock)
+
+ if listonly:
+ writemsg("\n")
+ if (fetched!=2) and not listonly:
+ writemsg("!!! Couldn't download "+str(myfile)+". Aborting.\n")
+ return 0
+ return 1
+
+
+def digestCreate(myfiles,basedir,oldDigest={}):
+ """Takes a list of files and the directory they are in and returns the
+ dict of dict[filename][CHECKSUM_KEY] = hash
+ returns None on error."""
+ mydigests={}
+ for x in myfiles:
+ print "<<<",x
+ myfile=os.path.normpath(basedir+"///"+x)
+ if os.path.exists(myfile):
+ if not os.access(myfile, os.R_OK):
+ print "!!! Given file does not appear to be readable. Does it exist?"
+ print "!!! File:",myfile
+ return None
+ mydigests[x] = portage_checksum.perform_all(myfile)
+ mysize = os.stat(myfile)[stat.ST_SIZE]
+ else:
+ if x in oldDigest:
+ # DeepCopy because we might not have a unique reference.
+ mydigests[x] = copy.deepcopy(oldDigest[x])
+ mysize = copy.deepcopy(oldDigest[x]["size"])
+ else:
+ print "!!! We have a source URI, but no file..."
+ print "!!! File:",myfile
+ return None
+
+ if mydigests[x].has_key("size") and (mydigests[x]["size"] != mysize):
+ raise portage_exception.DigestException, "Size mismatch during checksums"
+ mydigests[x]["size"] = copy.deepcopy(mysize)
+ return mydigests
+
+def digestCreateLines(filelist, mydict):
+ mylines = []
+ mydigests = copy.deepcopy(mydict)
+ for myarchive in filelist:
+ mysize = mydigests[myarchive]["size"]
+ if len(mydigests[myarchive]) == 0:
+ raise portage_exception.DigestException, "No generate digest for '%(file)s'" % {"file":myarchive}
+ for sumName in mydigests[myarchive].keys():
+ if sumName not in portage_checksum.get_valid_checksum_keys():
+ continue
+ mysum = mydigests[myarchive][sumName]
+
+ myline = sumName[:]
+ myline += " "+mysum
+ myline += " "+myarchive
+ myline += " "+str(mysize)
+ if sumName != "MD5":
+ # XXXXXXXXXXXXXXXX This cannot be used!
+ # Older portage make very dumb assumptions about the formats.
+ # We need a lead-in period before we break everything.
+ continue
+ mylines.append(myline)
+ return mylines
+
+def digestgen(myarchives,mysettings,overwrite=1,manifestonly=0):
+ """generates digest file if missing. Assumes all files are available. If
+ overwrite=0, the digest will only be created if it doesn't already exist."""
+
+ # archive files
+ basedir=mysettings["DISTDIR"]+"/"
+ digestfn=mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+
+ # portage files -- p(ortagefiles)basedir
+ pbasedir=mysettings["O"]+"/"
+ manifestfn=pbasedir+"Manifest"
+
+ if not manifestonly:
+ if not os.path.isdir(mysettings["FILESDIR"]):
+ os.makedirs(mysettings["FILESDIR"])
+ mycvstree=cvstree.getentries(pbasedir, recursive=1)
+
+ if ("cvs" in features) and os.path.exists(pbasedir+"/CVS"):
+ if not cvstree.isadded(mycvstree,"files"):
+ if "autoaddcvs" in features:
+ print ">>> Auto-adding files/ dir to CVS..."
+ spawn("cd "+pbasedir+"; cvs add files",mysettings,free=1)
+ else:
+ print "--- Warning: files/ is not added to cvs."
+
+ if (not overwrite) and os.path.exists(digestfn):
+ return 1
+
+ print green(">>> Generating digest file...")
+
+ # Track the old digest so we can assume checksums without requiring
+ # all files to be downloaded. 'Assuming'
+ myolddigest = {}
+ if os.path.exists(digestfn):
+ myolddigest = digestParseFile(digestfn)
+
+ mydigests=digestCreate(myarchives, basedir, oldDigest=myolddigest)
+ if mydigests==None: # There was a problem, exit with an errorcode.
+ return 0
+
+ try:
+ outfile=open(digestfn, "w+")
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Filesystem error skipping generation. (Read-Only?)"
+ print "!!!",e
+ return 0
+ for x in digestCreateLines(myarchives, mydigests):
+ outfile.write(x+"\n")
+ outfile.close()
+ try:
+ os.chown(digestfn,os.getuid(),portage_gid)
+ os.chmod(digestfn,0664)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ print e
+
+ print green(">>> Generating manifest file...")
+ mypfiles=listdir(pbasedir,recursive=1,filesonly=1,ignorecvs=1,EmptyOnError=1)
+ mypfiles=cvstree.apply_cvsignore_filter(mypfiles)
+ for x in ["Manifest"]:
+ if x in mypfiles:
+ mypfiles.remove(x)
+
+ mydigests=digestCreate(mypfiles, pbasedir)
+ if mydigests==None: # There was a problem, exit with an errorcode.
+ return 0
+
+ try:
+ outfile=open(manifestfn, "w+")
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Filesystem error skipping generation. (Read-Only?)"
+ print "!!!",e
+ return 0
+ for x in digestCreateLines(mypfiles, mydigests):
+ outfile.write(x+"\n")
+ outfile.close()
+ try:
+ os.chown(manifestfn,os.getuid(),portage_gid)
+ os.chmod(manifestfn,0664)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ print e
+
+ if "cvs" in features and os.path.exists(pbasedir+"/CVS"):
+ mycvstree=cvstree.getentries(pbasedir, recursive=1)
+ myunaddedfiles=""
+ if not manifestonly and not cvstree.isadded(mycvstree,digestfn):
+ if digestfn[:len(pbasedir)]==pbasedir:
+ myunaddedfiles=digestfn[len(pbasedir):]+" "
+ else:
+ myunaddedfiles=digestfn+" "
+ if not cvstree.isadded(mycvstree,manifestfn[len(pbasedir):]):
+ if manifestfn[:len(pbasedir)]==pbasedir:
+ myunaddedfiles+=manifestfn[len(pbasedir):]+" "
+ else:
+ myunaddedfiles+=manifestfn
+ if myunaddedfiles:
+ if "autoaddcvs" in features:
+ print blue(">>> Auto-adding digest file(s) to CVS...")
+ spawn("cd "+pbasedir+"; cvs add "+myunaddedfiles,mysettings,free=1)
+ else:
+ print "--- Warning: digests are not yet added into CVS."
+ print darkgreen(">>> Computed message digests.")
+ print
+ return 1
+
+
+def digestParseFile(myfilename):
+ """(filename) -- Parses a given file for entries matching:
+ MD5 MD5_STRING_OF_HEX_CHARS FILE_NAME FILE_SIZE
+ Ignores lines that do not begin with 'MD5' and returns a
+ dict with the filenames as keys and [md5,size] as the values."""
+
+ if not os.path.exists(myfilename):
+ return None
+ mylines = portage_util.grabfile(myfilename, compat_level=1)
+
+ mydigests={}
+ for x in mylines:
+ myline=string.split(x)
+ if len(myline) < 4:
+ #invalid line
+ continue
+ if myline[0] not in portage_checksum.get_valid_checksum_keys():
+ continue
+ mykey = myline.pop(0)
+ myhash = myline.pop(0)
+ mysize = long(myline.pop())
+ myfn = string.join(myline, " ")
+ if myfn not in mydigests:
+ mydigests[myfn] = {}
+ mydigests[myfn][mykey] = myhash
+ if "size" in mydigests[myfn]:
+ if mydigests[myfn]["size"] != mysize:
+ raise portage_exception.DigestException, "Conflicting sizes in digest: %(filename)s" % {"filename":myfilename}
+ else:
+ mydigests[myfn]["size"] = mysize
+ return mydigests
+
+# XXXX strict was added here to fix a missing name error.
+# XXXX It's used below, but we're not paying attention to how we get it?
+def digestCheckFiles(myfiles, mydigests, basedir, note="", strict=0):
+ """(fileslist, digestdict, basedir) -- Takes a list of files and a dict
+ of their digests and checks the digests against the indicated files in
+ the basedir given. Returns 1 only if all files exist and match the md5s.
+ """
+ for x in myfiles:
+ if not mydigests.has_key(x):
+ print
+ print red("!!! No message digest entry found for file \""+x+".\"")
+ print "!!! Most likely a temporary problem. Try 'emerge sync' again later."
+ print "!!! If you are certain of the authenticity of the file then you may type"
+ print "!!! the following to generate a new digest:"
+ print "!!! ebuild /usr/portage/category/package/package-version.ebuild digest"
+ return 0
+ myfile=os.path.normpath(basedir+"/"+x)
+ if not os.path.exists(myfile):
+ if strict:
+ print "!!! File does not exist:",myfile
+ return 0
+ continue
+
+ ok,reason = portage_checksum.verify_all(myfile,mydigests[x])
+ if not ok:
+ print
+ print red("!!! Digest verification Failed:")
+ print red("!!!")+" "+str(myfile)
+ print red("!!! Reason: ")+reason
+ print
+ return 0
+ else:
+ print ">>> md5 "+note+" ;-)",x
+ return 1
+
+
+def digestcheck(myfiles, mysettings, strict=0):
+ """Checks md5sums. Assumes all files have been downloaded."""
+ # archive files
+ basedir=mysettings["DISTDIR"]+"/"
+ digestfn=mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+
+ # portage files -- p(ortagefiles)basedir
+ pbasedir=mysettings["O"]+"/"
+ manifestfn=pbasedir+"Manifest"
+
+ if not (os.path.exists(digestfn) and os.path.exists(manifestfn)):
+ if "digest" in features:
+ print ">>> No package digest/Manifest file found."
+ print ">>> \"digest\" mode enabled; auto-generating new digest..."
+ return digestgen(myfiles,mysettings)
+ else:
+ if not os.path.exists(manifestfn):
+ if strict:
+ print red("!!! No package manifest found:"),manifestfn
+ return 0
+ else:
+ print "--- No package manifest found:",manifestfn
+ if not os.path.exists(digestfn):
+ print "!!! No package digest file found:",digestfn
+ print "!!! Type \"ebuild foo.ebuild digest\" to generate it."
+ return 0
+
+ mydigests=digestParseFile(digestfn)
+ if mydigests==None:
+ print "!!! Failed to parse digest file:",digestfn
+ return 0
+ mymdigests=digestParseFile(manifestfn)
+ if "strict" not in features:
+ # XXX: Remove this when manifests become mainstream.
+ pass
+ elif mymdigests==None:
+ print "!!! Failed to parse manifest file:",manifestfn
+ if strict:
+ return 0
+ else:
+ # Check the portage-related files here.
+ mymfiles=listdir(pbasedir,recursive=1,filesonly=1,ignorecvs=1,EmptyOnError=1)
+ manifest_files = mymdigests.keys()
+ for x in ["Manifest", "ChangeLog", "metadata.xml"]:
+ while x in mymfiles:
+ mymfiles.remove(x)
+ while x in manifest_files:
+ manifest_files.remove(x)
+ for x in range(len(mymfiles)-1,-1,-1):
+ if mymfiles[x] in manifest_files:
+ manifest_files.remove(mymfiles[x])
+ elif len(cvstree.apply_cvsignore_filter([mymfiles[x]]))==0:
+ # we filter here, rather then above; manifest might have files flagged by the filter.
+ # if something is returned, then it's flagged as a bad file
+ # manifest doesn't know about it, so we kill it here.
+ del mymfiles[x]
+ else:
+ print red("!!! Security Violation: A file exists that is not in the manifest.")
+ print "!!! File:",mymfiles[x]
+ if strict:
+ return 0
+ if manifest_files and strict:
+ print red("!!! Files listed in the manifest do not exist!")
+ for x in manifest_files:
+ print x
+ return 0
+
+ if not digestCheckFiles(mymfiles, mymdigests, pbasedir, note="files ", strict=strict):
+ if strict:
+ print ">>> Please ensure you have sync'd properly. Please try '"+bold("emerge sync")+"' and"
+ print ">>> optionally examine the file(s) for corruption. "+bold("A sync will fix most cases.")
+ print
+ return 0
+ else:
+ print "--- Manifest check failed. 'strict' not enabled; ignoring."
+ print
+
+ # Just return the status, as it's the last check.
+ return digestCheckFiles(myfiles, mydigests, basedir, note="src_uri", strict=strict)
+
+# parse actionmap to spawn ebuild with the appropriate args
+def spawnebuild(mydo,actionmap,mysettings,debug,alwaysdep=0,logfile=None):
+ if alwaysdep or ("noauto" not in features):
+ # process dependency first
+ if "dep" in actionmap[mydo].keys():
+ retval=spawnebuild(actionmap[mydo]["dep"],actionmap,mysettings,debug,alwaysdep=alwaysdep,logfile=logfile)
+ if retval:
+ return retval
+ # spawn ebuild.sh
+ mycommand = EBUILD_SH_BINARY + " "
+ if selinux_enabled and ("sesandbox" in features) and (mydo in ["unpack","compile","test","install"]):
+ con=selinux.getcontext()
+ con=string.replace(con,mysettings["PORTAGE_T"],mysettings["PORTAGE_SANDBOX_T"])
+ selinux.setexec(con)
+ retval=spawn(mycommand + mydo,mysettings,debug=debug,
+ free=actionmap[mydo]["args"][0],
+ droppriv=actionmap[mydo]["args"][1],logfile=logfile)
+ selinux.setexec(None)
+ else:
+ retval=spawn(mycommand + mydo,mysettings, debug=debug,
+ free=actionmap[mydo]["args"][0],
+ droppriv=actionmap[mydo]["args"][1],logfile=logfile)
+ return retval
+
+def doebuild(myebuild,mydo,myroot,mysettings,debug=0,listonly=0,fetchonly=0,cleanup=0,dbkey=None,use_cache=1,fetchall=0,tree="porttree"):
+ global db
+
+ ebuild_path = os.path.abspath(myebuild)
+ pkg_dir = os.path.dirname(ebuild_path)
+
+ if mysettings.configdict["pkg"].has_key("CATEGORY"):
+ cat = mysettings.configdict["pkg"]["CATEGORY"]
+ else:
+ cat = os.path.basename(os.path.normpath(pkg_dir+"/.."))
+ mypv = os.path.basename(ebuild_path)[:-7]
+ mycpv = cat+"/"+mypv
+
+ mysplit=pkgsplit(mypv,silent=0)
+ if mysplit==None:
+ writemsg("!!! Error: PF is null '%s'; exiting.\n" % mypv)
+ return 1
+
+ if mydo != "depend":
+ # XXX: We're doing a little hack here to curtain the gvisible locking
+ # XXX: that creates a deadlock... Really need to isolate that.
+ mysettings.reset(use_cache=use_cache)
+ mysettings.setcpv(mycpv,use_cache=use_cache)
+
+ validcommands = ["help","clean","prerm","postrm","preinst","postinst",
+ "config","setup","depend","fetch","digest",
+ "unpack","compile","test","install","rpm","qmerge","merge",
+ "package","unmerge", "manifest"]
+
+ if mydo not in validcommands:
+ validcommands.sort()
+ writemsg("!!! doebuild: '%s' is not one of the following valid commands:" % mydo)
+ for vcount in range(len(validcommands)):
+ if vcount%6 == 0:
+ writemsg("\n!!! ")
+ writemsg(string.ljust(validcommands[vcount], 11))
+ writemsg("\n")
+ return 1
+
+ if not os.path.exists(myebuild):
+ writemsg("!!! doebuild: "+str(myebuild)+" not found for "+str(mydo)+"\n")
+ return 1
+
+ if debug: # Otherwise it overrides emerge's settings.
+ # We have no other way to set debug... debug can't be passed in
+ # due to how it's coded... Don't overwrite this so we can use it.
+ mysettings["PORTAGE_DEBUG"]=str(debug)
+
+ mysettings["ROOT"] = myroot
+ mysettings["STARTDIR"] = getcwd()
+
+ mysettings["EBUILD"] = ebuild_path
+ mysettings["O"] = pkg_dir
+ mysettings["CATEGORY"] = cat
+ mysettings["FILESDIR"] = pkg_dir+"/files"
+ mysettings["PF"] = mypv
+
+ mysettings["ECLASSDIR"] = mysettings["PORTDIR"]+"/eclass"
+ mysettings["SANDBOX_LOG"] = mycpv.replace("/", "_-_")
+
+ mysettings["PROFILE_PATHS"] = string.join(mysettings.profiles,"\n")+"\n"+CUSTOM_PROFILE_PATH
+ mysettings["P"] = mysplit[0]+"-"+mysplit[1]
+ mysettings["PN"] = mysplit[0]
+ mysettings["PV"] = mysplit[1]
+ mysettings["PR"] = mysplit[2]
+
+ if mydo != "depend":
+ try:
+ mysettings["INHERITED"], mysettings["RESTRICT"] = db[root][tree].dbapi.aux_get( \
+ mycpv,["INHERITED","RESTRICT"])
+ mysettings["PORTAGE_RESTRICT"]=string.join(flatten(portage_dep.use_reduce(portage_dep.paren_reduce( \
+ mysettings["RESTRICT"]), uselist=mysettings["USE"].split())),' ')
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+ if mysplit[2] == "r0":
+ mysettings["PVR"]=mysplit[1]
+ else:
+ mysettings["PVR"]=mysplit[1]+"-"+mysplit[2]
+
+ mysettings["SLOT"]=""
+
+ if mysettings.has_key("PATH"):
+ mysplit=string.split(mysettings["PATH"],":")
+ else:
+ mysplit=[]
+ if PORTAGE_BIN_PATH not in mysplit:
+ mysettings["PATH"]=PORTAGE_BIN_PATH+":"+mysettings["PATH"]
+
+
+ mysettings["BUILD_PREFIX"] = mysettings["PORTAGE_TMPDIR"]+"/portage"
+ mysettings["HOME"] = mysettings["BUILD_PREFIX"]+"/homedir"
+ mysettings["PKG_TMPDIR"] = mysettings["PORTAGE_TMPDIR"]+"/portage-pkg"
+ mysettings["BUILDDIR"] = mysettings["BUILD_PREFIX"]+"/"+mysettings["PF"]
+
+ mysettings["PORTAGE_BASHRC"] = EBUILD_SH_ENV_FILE
+
+ #set up KV variable -- DEP SPEEDUP :: Don't waste time. Keep var persistent.
+ if (mydo!="depend") or not mysettings.has_key("KV"):
+ mykv,err1=ExtractKernelVersion(root+"usr/src/linux")
+ if mykv:
+ # Regular source tree
+ mysettings["KV"]=mykv
+ else:
+ mysettings["KV"]=""
+
+ if (mydo!="depend") or not mysettings.has_key("KVERS"):
+ myso=os.uname()[2]
+ mysettings["KVERS"]=myso[1]
+
+
+ # get possible slot information from the deps file
+ if mydo=="depend":
+ if mysettings.has_key("PORTAGE_DEBUG") and mysettings["PORTAGE_DEBUG"]=="1":
+ # XXX: This needs to use a FD for saving the output into a file.
+ # XXX: Set this up through spawn
+ pass
+ writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
+ if dbkey:
+ mysettings["dbkey"] = dbkey
+ else:
+ mysettings["dbkey"] = mysettings.depcachedir+"/aux_db_key_temp"
+
+ retval = spawn(EBUILD_SH_BINARY+" depend",mysettings)
+ return retval
+
+ logfile=None
+ # Build directory creation isn't required for any of these.
+ if mydo not in ["fetch","digest","manifest"]:
+
+ if not os.path.exists(mysettings["BUILD_PREFIX"]):
+ os.makedirs(mysettings["BUILD_PREFIX"])
+ if (os.getuid() == 0):
+ os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
+ os.chmod(mysettings["BUILD_PREFIX"],00775)
+
+ # Should be ok again to set $T, as sandbox does not depend on it
+ mysettings["T"]=mysettings["BUILDDIR"]+"/temp"
+ if cleanup or mydo=="clean":
+ if os.path.exists(mysettings["T"]):
+ shutil.rmtree(mysettings["T"])
+ if not os.path.exists(mysettings["T"]):
+ os.makedirs(mysettings["T"])
+ if (os.getuid() == 0):
+ os.chown(mysettings["T"],portage_uid,portage_gid)
+ os.chmod(mysettings["T"],02770)
+
+ try: # XXX: negative RESTRICT
+ if not (("nouserpriv" in string.split(mysettings["PORTAGE_RESTRICT"])) or \
+ ("userpriv" in string.split(mysettings["PORTAGE_RESTRICT"]))):
+ if ("userpriv" in features) and (portage_uid and portage_gid):
+ if (secpass==2):
+ if os.path.exists(mysettings["HOME"]):
+ # XXX: Potentially bad, but held down by HOME replacement above.
+ spawn("rm -Rf "+mysettings["HOME"],mysettings, free=1)
+ if not os.path.exists(mysettings["HOME"]):
+ os.makedirs(mysettings["HOME"])
+ elif ("userpriv" in features):
+ print "!!! Disabling userpriv from features... Portage UID/GID not valid."
+ del features[features.index("userpriv")]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Couldn't empty HOME:",mysettings["HOME"]
+ print "!!!",e
+
+ try:
+ # no reason to check for depend since depend returns above.
+ if not os.path.exists(mysettings["BUILD_PREFIX"]):
+ os.makedirs(mysettings["BUILD_PREFIX"])
+ if (os.getuid() == 0):
+ os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
+ if not os.path.exists(mysettings["BUILDDIR"]):
+ os.makedirs(mysettings["BUILDDIR"])
+ if (os.getuid() == 0):
+ os.chown(mysettings["BUILDDIR"],portage_uid,portage_gid)
+ except OSError, e:
+ print "!!! File system problem. (ReadOnly? Out of space?)"
+ print "!!! Perhaps: rm -Rf",mysettings["BUILD_PREFIX"]
+ print "!!!",str(e)
+ return 1
+
+ try:
+ if not os.path.exists(mysettings["HOME"]):
+ os.makedirs(mysettings["HOME"])
+ if (os.getuid() == 0):
+ os.chown(mysettings["HOME"],portage_uid,portage_gid)
+ os.chmod(mysettings["HOME"],02770)
+ except OSError, e:
+ print "!!! File system problem. (ReadOnly? Out of space?)"
+ print "!!! Failed to create fake home directory in BUILDDIR"
+ print "!!!",str(e)
+ return 1
+
+ try:
+ if ("ccache" in features):
+ if (not mysettings.has_key("CCACHE_DIR")) or (mysettings["CCACHE_DIR"]==""):
+ mysettings["CCACHE_DIR"]=mysettings["PORTAGE_TMPDIR"]+"/ccache"
+ if not os.path.exists(mysettings["CCACHE_DIR"]):
+ os.makedirs(mysettings["CCACHE_DIR"])
+ mystat = os.stat(mysettings["CCACHE_DIR"])
+ if ("userpriv" in features):
+ if mystat[stat.ST_UID] != portage_gid or ((mystat[stat.ST_MODE]&02070)!=02070):
+ writemsg("* Adjusting permissions on ccache in %s\n" % mysettings["CCACHE_DIR"])
+ spawn("chgrp -R "+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chown "+str(portage_uid)+":"+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chmod -R ug+rw "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("find "+mysettings["CCACHE_DIR"]+" -type d -exec chmod g+s \{\} \;", mysettings, free=1)
+ else:
+ if mystat[stat.ST_UID] != 0 or ((mystat[stat.ST_MODE]&02070)!=02070):
+ writemsg("* Adjusting permissions on ccache in %s\n" % mysettings["CCACHE_DIR"])
+ spawn("chgrp -R "+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chown 0:"+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chmod -R ug+rw "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("find "+mysettings["CCACHE_DIR"]+" -type d -exec chmod g+s \{\} \;", mysettings, free=1)
+ except OSError, e:
+ print "!!! File system problem. (ReadOnly? Out of space?)"
+ print "!!! Perhaps: rm -Rf",mysettings["BUILD_PREFIX"]
+ print "!!!",str(e)
+ return 1
+
+ #try:
+ # mystat=os.stat(mysettings["CCACHE_DIR"])
+ # if (mystat[stat.ST_GID]!=portage_gid) or ((mystat[stat.ST_MODE]&02070)!=02070):
+ # print "*** Adjusting ccache permissions for portage user..."
+ # os.chown(mysettings["CCACHE_DIR"],portage_uid,portage_gid)
+ # os.chmod(mysettings["CCACHE_DIR"],02770)
+ # spawn("chown -R "+str(portage_uid)+":"+str(portage_gid)+" "+mysettings["CCACHE_DIR"],mysettings, free=1)
+ # spawn("chmod -R g+rw "+mysettings["CCACHE_DIR"],mysettings, free=1)
+ #except SystemExit, e:
+ # raise
+ #except:
+ # pass
+
+ if "distcc" in features:
+ try:
+ if (not mysettings.has_key("DISTCC_DIR")) or (mysettings["DISTCC_DIR"]==""):
+ mysettings["DISTCC_DIR"]=mysettings["PORTAGE_TMPDIR"]+"/portage/.distcc"
+ if not os.path.exists(mysettings["DISTCC_DIR"]):
+ os.makedirs(mysettings["DISTCC_DIR"])
+ os.chown(mysettings["DISTCC_DIR"],portage_uid,portage_gid)
+ os.chmod(mysettings["DISTCC_DIR"],02775)
+ for x in ("/lock", "/state"):
+ if not os.path.exists(mysettings["DISTCC_DIR"]+x):
+ os.mkdir(mysettings["DISTCC_DIR"]+x)
+ os.chown(mysettings["DISTCC_DIR"]+x,portage_uid,portage_gid)
+ os.chmod(mysettings["DISTCC_DIR"]+x,02775)
+ except OSError, e:
+ writemsg("\n!!! File system problem when setting DISTCC_DIR directory permissions.\n")
+ writemsg( "!!! DISTCC_DIR="+str(mysettings["DISTCC_DIR"]+"\n"))
+ writemsg( "!!! "+str(e)+"\n\n")
+ time.sleep(5)
+ features.remove("distcc")
+ mysettings["DISTCC_DIR"]=""
+
+ mysettings["WORKDIR"]=mysettings["BUILDDIR"]+"/work"
+ mysettings["D"]=mysettings["BUILDDIR"]+"/image/"
+
+ if mysettings.has_key("PORT_LOGDIR"):
+ if os.access(mysettings["PORT_LOGDIR"]+"/",os.W_OK):
+ try:
+ os.chown(mysettings["PORT_LOGDIR"],portage_uid,portage_gid)
+ os.chmod(mysettings["PORT_LOGDIR"],02770)
+ if not mysettings.has_key("LOG_PF") or (mysettings["LOG_PF"] != mysettings["PF"]):
+ mysettings["LOG_PF"]=mysettings["PF"]
+ mysettings["LOG_COUNTER"]=str(db[myroot]["vartree"].dbapi.get_counter_tick_core("/"))
+ logfile="%s/%s-%s.log" % (mysettings["PORT_LOGDIR"],mysettings["LOG_COUNTER"],mysettings["LOG_PF"])
+ except ValueError, e:
+ mysettings["PORT_LOGDIR"]=""
+ print "!!! Unable to chown/chmod PORT_LOGDIR. Disabling logging."
+ print "!!!",e
+ else:
+ print "!!! Cannot create log... No write access / Does not exist"
+ print "!!! PORT_LOGDIR:",mysettings["PORT_LOGDIR"]
+ mysettings["PORT_LOGDIR"]=""
+
+ if mydo=="unmerge":
+ return unmerge(mysettings["CATEGORY"],mysettings["PF"],myroot,mysettings)
+
+ # if any of these are being called, handle them -- running them out of the sandbox -- and stop now.
+ if mydo=="clean":
+ logfile=None
+ if mydo in ["help","clean","setup"]:
+ return spawn(EBUILD_SH_BINARY+" "+mydo,mysettings,debug=debug,free=1,logfile=logfile)
+ elif mydo in ["prerm","postrm","preinst","postinst","config"]:
+ mysettings.load_infodir(pkg_dir)
+ return spawn(EBUILD_SH_BINARY+" "+mydo,mysettings,debug=debug,free=1,logfile=logfile)
+
+ try:
+ mysettings["SLOT"],mysettings["RESTRICT"] = db["/"]["porttree"].dbapi.aux_get(mycpv,["SLOT","RESTRICT"])
+ except (IOError,KeyError):
+ print red("doebuild():")+" aux_get() error reading "+mycpv+"; aborting."
+ sys.exit(1)
+
+ newuris, alist = db["/"]["porttree"].dbapi.getfetchlist(mycpv,mysettings=mysettings)
+ alluris, aalist = db["/"]["porttree"].dbapi.getfetchlist(mycpv,mysettings=mysettings,all=1)
+ mysettings["A"]=string.join(alist," ")
+ mysettings["AA"]=string.join(aalist," ")
+ if ("mirror" in features) or fetchall:
+ fetchme=alluris[:]
+ checkme=aalist[:]
+ elif mydo=="digest":
+ fetchme=alluris[:]
+ checkme=aalist[:]
+ digestfn=mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+ if os.path.exists(digestfn):
+ mydigests=digestParseFile(digestfn)
+ if mydigests:
+ for x in mydigests:
+ while x in checkme:
+ i = checkme.index(x)
+ del fetchme[i]
+ del checkme[i]
+ else:
+ fetchme=newuris[:]
+ checkme=alist[:]
+
+ try:
+ if not os.path.exists(mysettings["DISTDIR"]):
+ os.makedirs(mysettings["DISTDIR"])
+ if not os.path.exists(mysettings["DISTDIR"]+"/cvs-src"):
+ os.makedirs(mysettings["DISTDIR"]+"/cvs-src")
+ except OSError, e:
+ print "!!! File system problem. (Bad Symlink?)"
+ print "!!! Fetching may fail:",str(e)
+
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/cvs-src")
+ if ((mystat[stat.ST_GID]!=portage_gid) or ((mystat[stat.ST_MODE]&02770)!=02770)) and not listonly:
+ print "*** Adjusting cvs-src permissions for portage user..."
+ os.chown(mysettings["DISTDIR"]+"/cvs-src",0,portage_gid)
+ os.chmod(mysettings["DISTDIR"]+"/cvs-src",02770)
+ spawn("chgrp -R "+str(portage_gid)+" "+mysettings["DISTDIR"]+"/cvs-src", free=1)
+ spawn("chmod -R g+rw "+mysettings["DISTDIR"]+"/cvs-src", free=1)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+ if mydo!="manifest" and not fetch(fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
+ return 1
+
+ if mydo=="fetch" and listonly:
+ return 0
+
+ if "digest" in features:
+ #generate digest if it doesn't exist.
+ if mydo=="digest":
+ return (not digestgen(aalist,mysettings,overwrite=1))
+ else:
+ digestgen(aalist,mysettings,overwrite=0)
+ elif mydo=="digest":
+ #since we are calling "digest" directly, recreate the digest even if it already exists
+ return (not digestgen(aalist,mysettings,overwrite=1))
+ if mydo=="manifest":
+ return (not digestgen(aalist,mysettings,overwrite=1,manifestonly=1))
+
+ if not digestcheck(checkme, mysettings, ("strict" in features)):
+ return 1
+
+ if mydo=="fetch":
+ return 0
+
+ #initial dep checks complete; time to process main commands
+
+ nosandbox=(("userpriv" in features) and ("usersandbox" not in features) and \
+ ("userpriv" not in mysettings["RESTRICT"]) and ("nouserpriv" not in mysettings["RESTRICT"]))
+ if nosandbox and ("userpriv" not in features or "userpriv" in mysettings["RESTRICT"] or \
+ "nouserpriv" in mysettings["RESTRICT"]):
+ nosandbox = ("sandbox" not in features and "usersandbox" not in features)
+ actionmap={
+ "depend": { "args":(0,1)}, # sandbox / portage
+ "setup": { "args":(1,0)}, # without / root
+ "unpack": {"dep":"setup", "args":(0,1)}, # sandbox / portage
+ "compile": {"dep":"unpack", "args":(nosandbox,1)}, # optional / portage
+ "test": {"dep":"compile", "args":(nosandbox,1)}, # optional / portage
+ "install": {"dep":"test", "args":(0,0)}, # sandbox / root
+ "rpm": {"dep":"install", "args":(0,0)}, # sandbox / root
+ "package": {"dep":"install", "args":(0,0)}, # sandbox / root
+ }
+
+ if mydo in actionmap.keys():
+ if mydo=="package":
+ for x in ["","/"+mysettings["CATEGORY"],"/All"]:
+ if not os.path.exists(mysettings["PKGDIR"]+x):
+ os.makedirs(mysettings["PKGDIR"]+x)
+ # REBUILD CODE FOR TBZ2 --- XXXX
+ return spawnebuild(mydo,actionmap,mysettings,debug,logfile=logfile)
+ elif mydo=="qmerge":
+ #check to ensure install was run. this *only* pops up when users forget it and are using ebuild
+ if not os.path.exists(mysettings["BUILDDIR"]+"/.installed"):
+ print "!!! mydo=qmerge, but install phase hasn't been ran"
+ sys.exit(1)
+ #qmerge is specifically not supposed to do a runtime dep check
+ return merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["BUILDDIR"]+"/build-info",myroot,mysettings)
+ elif mydo=="merge":
+ retval=spawnebuild("install",actionmap,mysettings,debug,alwaysdep=1,logfile=logfile)
+ if retval:
+ return retval
+ return merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["BUILDDIR"]+"/build-info",myroot,mysettings,myebuild=mysettings["EBUILD"])
+ else:
+ print "!!! Unknown mydo:",mydo
+ sys.exit(1)
+
+expandcache={}
+
+def movefile(src,dest,newmtime=None,sstat=None,mysettings=None):
+ """moves a file from src to dest, preserving all permissions and attributes; mtime will
+ be preserved even when moving across filesystems. Returns true on success and false on
+ failure. Move is atomic."""
+ #print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"
+ global lchown
+
+ try:
+ if not sstat:
+ sstat=os.lstat(src)
+ if bsd_chflags:
+ sflags=bsd_chflags.lgetflags(src)
+ if sflags < 0:
+ # Problem getting flags...
+ writemsg("!!! Couldn't get flags for "+dest+"\n")
+ return None
+
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Stating source file failed... movefile()"
+ print "!!!",e
+ return None
+
+ destexists=1
+ try:
+ dstat=os.lstat(dest)
+ except SystemExit, e:
+ raise
+ except:
+ dstat=os.lstat(os.path.dirname(dest))
+ destexists=0
+
+ if bsd_chflags:
+ # Check that we can actually unset schg etc flags...
+ # Clear the flags on source and destination; we'll reinstate them after merging
+ if(destexists):
+ if bsd_chflags.lchflags(dest, 0) < 0:
+ writemsg("!!! Couldn't clear flags on file being merged: \n ")
+ # We might have an immutable flag on the parent dir; save and clear.
+ pflags=bsd_chflags.lgetflags(os.path.dirname(dest))
+ bsd_chflags.lchflags(os.path.dirname(dest), 0)
+
+ # Don't bother checking the return value here; if it fails then the next line will catch it.
+ bsd_chflags.lchflags(src, 0)
+
+ if bsd_chflags.lhasproblems(src)>0 or (destexists and bsd_chflags.lhasproblems(dest)>0) or bsd_chflags.lhasproblems(os.path.dirname(dest))>0:
+ # This is bad: we can't merge the file with these flags set.
+ writemsg("!!! Can't merge file "+dest+" because of flags set\n")
+ return None
+
+ if destexists:
+ if stat.S_ISLNK(dstat[stat.ST_MODE]):
+ try:
+ os.unlink(dest)
+ destexists=0
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+ if stat.S_ISLNK(sstat[stat.ST_MODE]):
+ try:
+ target=os.readlink(src)
+ if mysettings and mysettings["D"]:
+ if target.find(mysettings["D"])==0:
+ target=target[len(mysettings["D"]):]
+ if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
+ os.unlink(dest)
+ if selinux_enabled:
+ sid = selinux.get_lsid(src)
+ selinux.secure_symlink(target,dest,sid)
+ else:
+ os.symlink(target,dest)
+ lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+ if bsd_chflags:
+ # Restore the flags we saved before moving
+ if bsd_chflags.lchflags(dest, sflags) < 0 or bsd_chflags.lchflags(os.path.dirname(dest), pflags) < 0:
+ writemsg("!!! Couldn't restore flags ("+str(flags)+") on " + dest+":\n")
+ writemsg("!!! %s\n" % str(e))
+ return None
+ return os.lstat(dest)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! failed to properly create symlink:"
+ print "!!!",dest,"->",target
+ print "!!!",e
+ return None
+
+ renamefailed=1
+ if sstat[stat.ST_DEV]==dstat[stat.ST_DEV] or selinux_enabled:
+ try:
+ if selinux_enabled:
+ ret=selinux.secure_rename(src,dest)
+ else:
+ ret=os.rename(src,dest)
+ renamefailed=0
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ import errno
+ if e[0]!=errno.EXDEV:
+ # Some random error.
+ print "!!! Failed to move",src,"to",dest
+ print "!!!",e
+ return None
+ # Invalid cross-device-link 'bind' mounted or actually Cross-Device
+ if renamefailed:
+ didcopy=0
+ if stat.S_ISREG(sstat[stat.ST_MODE]):
+ try: # For safety copy then move it over.
+ if selinux_enabled:
+ selinux.secure_copy(src,dest+"#new")
+ selinux.secure_rename(dest+"#new",dest)
+ else:
+ shutil.copyfile(src,dest+"#new")
+ os.rename(dest+"#new",dest)
+ didcopy=1
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print '!!! copy',src,'->',dest,'failed.'
+ print "!!!",e
+ return None
+ else:
+ #we don't yet handle special, so we need to fall back to /bin/mv
+ if selinux_enabled:
+ a=commands.getstatusoutput(MOVE_BINARY+" -c -f "+"'"+src+"' '"+dest+"'")
+ else:
+ a=commands.getstatusoutput(MOVE_BINARY+" -f "+"'"+src+"' '"+dest+"'")
+ if a[0]!=0:
+ print "!!! Failed to move special file:"
+ print "!!! '"+src+"' to '"+dest+"'"
+ print "!!!",a
+ return None # failure
+ try:
+ if didcopy:
+ lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+ os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
+ os.unlink(src)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Failed to chown/chmod/unlink in movefile()"
+ print "!!!",dest
+ print "!!!",e
+ return None
+
+ if newmtime:
+ os.utime(dest,(newmtime,newmtime))
+ else:
+ os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
+ newmtime=sstat[stat.ST_MTIME]
+
+ if bsd_chflags:
+ # Restore the flags we saved before moving
+ if bsd_chflags.lchflags(dest, sflags) < 0 or bsd_chflags.lchflags(os.path.dirname(dest), pflags) < 0:
+ writemsg("!!! Couldn't restore flags ("+str(sflags)+") on " + dest+":\n")
+ return None
+
+ return newmtime
+
+def merge(mycat,mypkg,pkgloc,infloc,myroot,mysettings,myebuild=None):
+ mylink=dblink(mycat,mypkg,myroot,mysettings)
+ return mylink.merge(pkgloc,infloc,myroot,myebuild)
+
+def unmerge(cat,pkg,myroot,mysettings,mytrimworld=1):
+ mylink=dblink(cat,pkg,myroot,mysettings)
+ if mylink.exists():
+ mylink.unmerge(trimworld=mytrimworld,cleanup=1)
+ mylink.delete()
+
+def relparse(myver):
+ "converts last version part into three components"
+ number=0
+ suffix=0
+ endtype=0
+ endnumber=0
+
+ mynewver=string.split(myver,"_")
+ myver=mynewver[0]
+
+ #normal number or number with letter at end
+ divider=len(myver)-1
+ if myver[divider:] not in "1234567890":
+ #letter at end
+ suffix=ord(myver[divider:])
+ number=string.atof(myver[0:divider])
+ else:
+ number=string.atof(myver)
+
+ if len(mynewver)==2:
+ #an endversion
+ for x in endversion_keys:
+ elen=len(x)
+ if mynewver[1][:elen] == x:
+ match=1
+ endtype=endversion[x]
+ try:
+ endnumber=string.atof(mynewver[1][elen:])
+ except SystemExit, e:
+ raise
+ except:
+ endnumber=0
+ break
+ return [number,suffix,endtype,endnumber]
+
+#returns 1 if valid version string, else 0
+# valid string in format: <v1>.<v2>...<vx>[a-z,_{endversion}[vy]]
+# ververify doesn't do package rev.
+
+vercache={}
+def ververify(myorigval,silent=1):
+ try:
+ return vercache[myorigval]
+ except KeyError:
+ pass
+ if len(myorigval)==0:
+ if not silent:
+ print "!!! Name error: package contains empty \"-\" part."
+ return 0
+ myval=string.split(myorigval,'.')
+ if len(myval)==0:
+ if not silent:
+ print "!!! Name error: empty version string."
+ vercache[myorigval]=0
+ return 0
+ #all but the last version must be a numeric
+ for x in myval[:-1]:
+ if not len(x):
+ if not silent:
+ print "!!! Name error in",myorigval+": two decimal points in a row"
+ vercache[myorigval]=0
+ return 0
+ try:
+ foo=int(x)
+ except SystemExit, e:
+ raise
+ except:
+ if not silent:
+ print "!!! Name error in",myorigval+": \""+x+"\" is not a valid version component."
+ vercache[myorigval]=0
+ return 0
+ if not len(myval[-1]):
+ if not silent:
+ print "!!! Name error in",myorigval+": two decimal points in a row"
+ vercache[myorigval]=0
+ return 0
+ try:
+ foo=int(myval[-1])
+ vercache[myorigval]=1
+ return 1
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ #ok, our last component is not a plain number or blank, let's continue
+ if myval[-1][-1] in string.lowercase:
+ try:
+ foo=int(myval[-1][:-1])
+ vercache[myorigval]=1
+ return 1
+ # 1a, 2.0b, etc.
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ #ok, maybe we have a 1_alpha or 1_beta2; let's see
+ #ep="endpart"
+ ep=string.split(myval[-1],"_")
+ if len(ep)!=2:
+ if not silent:
+ print "!!! Name error in",myorigval
+ vercache[myorigval]=0
+ return 0
+ try:
+ foo=int(ep[0][-1])
+ chk=ep[0]
+ except SystemExit, e:
+ raise
+ except:
+ # because it's ok last char is not numeric. example: foo-1.0.0a_pre1
+ chk=ep[0][:-1]
+
+ try:
+ foo=int(chk)
+ except SystemExit, e:
+ raise
+ except:
+ #this needs to be numeric or numeric+single letter,
+ #i.e. the "1" in "1_alpha" or "1a_alpha"
+ if not silent:
+ print "!!! Name error in",myorigval+": characters before _ must be numeric or numeric+single letter"
+ vercache[myorigval]=0
+ return 0
+ for mye in endversion_keys:
+ if ep[1][0:len(mye)]==mye:
+ if len(mye)==len(ep[1]):
+ #no trailing numeric; ok
+ vercache[myorigval]=1
+ return 1
+ else:
+ try:
+ foo=int(ep[1][len(mye):])
+ vercache[myorigval]=1
+ return 1
+ except SystemExit, e:
+ raise
+ except:
+ #if no endversions work, *then* we return 0
+ pass
+ if not silent:
+ print "!!! Name error in",myorigval
+ vercache[myorigval]=0
+ return 0
+
+def isvalidatom(atom):
+ mycpv_cps = catpkgsplit(dep_getcpv(atom))
+ operator = get_operator(atom)
+ if operator:
+ if mycpv_cps and mycpv_cps[0] != "null":
+ # >=cat/pkg-1.0
+ return 1
+ else:
+ # >=cat/pkg or >=pkg-1.0 (no category)
+ return 0
+ if mycpv_cps:
+ # cat/pkg-1.0
+ return 0
+
+ if (len(string.split(atom, '/'))==2):
+ # cat/pkg
+ return 1
+ else:
+ return 0
+
+def isjustname(mypkg):
+ myparts=string.split(mypkg,'-')
+ for x in myparts:
+ if ververify(x):
+ return 0
+ return 1
+
+iscache={}
+def isspecific(mypkg):
+ "now supports packages with no category"
+ try:
+ return iscache[mypkg]
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ mysplit=string.split(mypkg,"/")
+ if not isjustname(mysplit[-1]):
+ iscache[mypkg]=1
+ return 1
+ iscache[mypkg]=0
+ return 0
+
+# This function can be used as a package verification function, i.e.
+# "pkgsplit("foo-1.2-1") will return None if foo-1.2-1 isn't a valid
+# package (with version) name. If it is a valid name, pkgsplit will
+# return a list containing: [ pkgname, pkgversion(norev), pkgrev ].
+# For foo-1.2-1, this list would be [ "foo", "1.2", "1" ]. For
+# Mesa-3.0, this list would be [ "Mesa", "3.0", "0" ].
+pkgcache={}
+
+def pkgsplit(mypkg,silent=1):
+ try:
+ if not pkgcache[mypkg]:
+ return None
+ return pkgcache[mypkg][:]
+ except KeyError:
+ pass
+ myparts=string.split(mypkg,'-')
+ if len(myparts)<2:
+ if not silent:
+ print "!!! Name error in",mypkg+": missing a version or name part."
+ pkgcache[mypkg]=None
+ return None
+ for x in myparts:
+ if len(x)==0:
+ if not silent:
+ print "!!! Name error in",mypkg+": empty \"-\" part."
+ pkgcache[mypkg]=None
+ return None
+ #verify rev
+ revok=0
+ myrev=myparts[-1]
+ if len(myrev) and myrev[0]=="r":
+ try:
+ int(myrev[1:])
+ revok=1
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ if revok:
+ if ververify(myparts[-2]):
+ if len(myparts)==2:
+ pkgcache[mypkg]=None
+ return None
+ else:
+ for x in myparts[:-2]:
+ if ververify(x):
+ pkgcache[mypkg]=None
+ return None
+ #names can't have versiony looking parts
+ myval=[string.join(myparts[:-2],"-"),myparts[-2],myparts[-1]]
+ pkgcache[mypkg]=myval
+ return myval
+ else:
+ pkgcache[mypkg]=None
+ return None
+
+ elif ververify(myparts[-1],silent=silent):
+ if len(myparts)==1:
+ if not silent:
+ print "!!! Name error in",mypkg+": missing name part."
+ pkgcache[mypkg]=None
+ return None
+ else:
+ for x in myparts[:-1]:
+ if ververify(x):
+ if not silent:
+ print "!!! Name error in",mypkg+": multiple version parts."
+ pkgcache[mypkg]=None
+ return None
+ myval=[string.join(myparts[:-1],"-"),myparts[-1],"r0"]
+ pkgcache[mypkg]=myval[:]
+ return myval
+ else:
+ pkgcache[mypkg]=None
+ return None
+
+def getCPFromCPV(mycpv):
+ """Calls pkgsplit on a cpv and returns only the cp."""
+ return pkgsplit(mycpv)[0]
+
+catcache={}
+def catpkgsplit(mydata,silent=1):
+ "returns [cat, pkgname, version, rev ]"
+ try:
+ if not catcache[mydata]:
+ return None
+ return catcache[mydata][:]
+ except KeyError:
+ pass
+ mysplit=mydata.split("/")
+ p_split=None
+ if len(mysplit)==1:
+ retval=["null"]
+ p_split=pkgsplit(mydata,silent=silent)
+ elif len(mysplit)==2:
+ retval=[mysplit[0]]
+ p_split=pkgsplit(mysplit[1],silent=silent)
+ if not p_split:
+ catcache[mydata]=None
+ return None
+ retval.extend(p_split)
+ catcache[mydata]=retval
+ return retval
+
+# vercmp:
+# This takes two version strings and returns an integer to tell you whether
+# the versions are the same, val1>val2 or val2>val1.
+vcmpcache={}
+def vercmp(val1,val2):
+ if val1==val2:
+ #quick short-circuit
+ return 0
+ valkey=val1+" "+val2
+ try:
+ return vcmpcache[valkey]
+ try:
+ return -vcmpcache[val2+" "+val1]
+ except KeyError:
+ pass
+ except KeyError:
+ pass
+
+ # consider 1_p2 vc 1.1
+ # after expansion will become (1_p2,0) vc (1,1)
+ # then 1_p2 is compared with 1 before 0 is compared with 1
+ # to solve the bug we need to convert it to (1,0_p2)
+ # by splitting _prepart part and adding it back _after_expansion
+ val1_prepart = val2_prepart = ''
+ if val1.count('_'):
+ val1, val1_prepart = val1.split('_', 1)
+ if val2.count('_'):
+ val2, val2_prepart = val2.split('_', 1)
+
+ # replace '-' by '.'
+ # FIXME: Is it needed? can val1/2 contain '-'?
+ val1=string.split(val1,'-')
+ if len(val1)==2:
+ val1[0]=val1[0]+"."+val1[1]
+ val2=string.split(val2,'-')
+ if len(val2)==2:
+ val2[0]=val2[0]+"."+val2[1]
+
+ val1=string.split(val1[0],'.')
+ val2=string.split(val2[0],'.')
+
+ #add back decimal point so that .03 does not become "3" !
+ for x in range(1,len(val1)):
+ if val1[x][0] == '0' :
+ val1[x]='.' + val1[x]
+ for x in range(1,len(val2)):
+ if val2[x][0] == '0' :
+ val2[x]='.' + val2[x]
+
+ # extend version numbers
+ if len(val2)<len(val1):
+ val2.extend(["0"]*(len(val1)-len(val2)))
+ elif len(val1)<len(val2):
+ val1.extend(["0"]*(len(val2)-len(val1)))
+
+ # add back _prepart tails
+ if val1_prepart:
+ val1[-1] += '_' + val1_prepart
+ if val2_prepart:
+ val2[-1] += '_' + val2_prepart
+ #The above code will extend version numbers out so they
+ #have the same number of digits.
+ for x in range(0,len(val1)):
+ cmp1=relparse(val1[x])
+ cmp2=relparse(val2[x])
+ for y in range(0,4):
+ myret=cmp1[y]-cmp2[y]
+ if myret != 0:
+ vcmpcache[valkey]=myret
+ return myret
+ vcmpcache[valkey]=0
+ return 0
+
+
+def pkgcmp(pkg1,pkg2):
+ """if returnval is less than zero, then pkg2 is newer than pkg1, zero if equal and positive if older."""
+ if pkg1[0] != pkg2[0]:
+ return None
+ mycmp=vercmp(pkg1[1],pkg2[1])
+ if mycmp>0:
+ return 1
+ if mycmp<0:
+ return -1
+ r1=int(pkg1[2][1:])
+ r2=int(pkg2[2][1:])
+ if r1>r2:
+ return 1
+ if r2>r1:
+ return -1
+ return 0
+
+def dep_parenreduce(mysplit,mypos=0):
+ "Accepts a list of strings, and converts '(' and ')' surrounded items to sub-lists"
+ while (mypos<len(mysplit)):
+ if (mysplit[mypos]=="("):
+ firstpos=mypos
+ mypos=mypos+1
+ while (mypos<len(mysplit)):
+ if mysplit[mypos]==")":
+ mysplit[firstpos:mypos+1]=[mysplit[firstpos+1:mypos]]
+ mypos=firstpos
+ break
+ elif mysplit[mypos]=="(":
+ #recurse
+ mysplit=dep_parenreduce(mysplit,mypos=mypos)
+ mypos=mypos+1
+ mypos=mypos+1
+ return mysplit
+
+def dep_opconvert(mysplit,myuse,mysettings):
+ "Does dependency operator conversion"
+
+ #check_config_instance(mysettings)
+
+ mypos=0
+ newsplit=[]
+ while mypos<len(mysplit):
+ if type(mysplit[mypos])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos],myuse,mysettings))
+ mypos += 1
+ elif mysplit[mypos]==")":
+ #mismatched paren, error
+ return None
+ elif mysplit[mypos]=="||":
+ if ((mypos+1)>=len(mysplit)) or (type(mysplit[mypos+1])!=types.ListType):
+ # || must be followed by paren'd list
+ return None
+ try:
+ mynew=dep_opconvert(mysplit[mypos+1],myuse,mysettings)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Unable to satisfy OR dependency:",string.join(mysplit," || ")
+ raise e
+ mynew[0:0]=["||"]
+ newsplit.append(mynew)
+ mypos += 2
+ elif mysplit[mypos][-1]=="?":
+ #uses clause, i.e "gnome? ( foo bar )"
+ #this is a quick and dirty hack so that repoman can enable all USE vars:
+ if (len(myuse)==1) and (myuse[0]=="*") and mysettings:
+ # enable it even if it's ! (for repoman) but kill it if it's
+ # an arch variable that isn't for this arch. XXX Sparc64?
+ k=mysplit[mypos][:-1]
+ if k[0]=="!":
+ k=k[1:]
+ if k not in archlist and k not in mysettings.usemask:
+ enabled=1
+ elif k in archlist:
+ if k==mysettings["ARCH"]:
+ if mysplit[mypos][0]=="!":
+ enabled=0
+ else:
+ enabled=1
+ elif mysplit[mypos][0]=="!":
+ enabled=1
+ else:
+ enabled=0
+ else:
+ enabled=0
+ else:
+ if mysplit[mypos][0]=="!":
+ myusevar=mysplit[mypos][1:-1]
+ if myusevar in myuse:
+ enabled=0
+ else:
+ enabled=1
+ else:
+ myusevar=mysplit[mypos][:-1]
+ if myusevar in myuse:
+ enabled=1
+ else:
+ enabled=0
+ if (mypos+2<len(mysplit)) and (mysplit[mypos+2]==":"):
+ #colon mode
+ if enabled:
+ #choose the first option
+ if type(mysplit[mypos+1])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos+1],myuse,mysettings))
+ else:
+ newsplit.append(mysplit[mypos+1])
+ else:
+ #choose the alternate option
+ if type(mysplit[mypos+1])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos+3],myuse,mysettings))
+ else:
+ newsplit.append(mysplit[mypos+3])
+ mypos += 4
+ else:
+ #normal use mode
+ if enabled:
+ if type(mysplit[mypos+1])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos+1],myuse,mysettings))
+ else:
+ newsplit.append(mysplit[mypos+1])
+ #otherwise, continue.
+ mypos += 2
+ else:
+ #normal item
+ newsplit.append(mysplit[mypos])
+ mypos += 1
+ return newsplit
+
+def dep_virtual(mysplit, mysettings):
+ "Does virtual dependency conversion"
+
+
+
+ newsplit=[]
+ for x in mysplit:
+ if type(x)==types.ListType:
+ newsplit.append(dep_virtual(x, mysettings))
+ else:
+ mykey=dep_getkey(x)
+ if mysettings.virtuals.has_key(mykey):
+ if len(mysettings.virtuals[mykey])==1:
+ a=string.replace(x, mykey, mysettings.virtuals[mykey][0])
+ else:
+ if x[0]=="!":
+ # blocker needs "and" not "or(||)".
+ a=[]
+ else:
+ a=['||']
+ for y in mysettings.virtuals[mykey]:
+ a.append(string.replace(x, mykey, y))
+ newsplit.append(a)
+ else:
+ newsplit.append(x)
+ return newsplit
+
+def dep_eval(deplist):
+ if len(deplist)==0:
+ return 1
+ if deplist[0]=="||":
+ #or list; we just need one "1"
+ for x in deplist[1:]:
+ if type(x)==types.ListType:
+ if dep_eval(x)==1:
+ return 1
+ elif x==1:
+ return 1
+ return 0
+ else:
+ for x in deplist:
+ if type(x)==types.ListType:
+ if dep_eval(x)==0:
+ return 0
+ elif x==0 or x==2:
+ return 0
+ return 1
+
+def dep_zapdeps(unreduced,reduced,vardbapi=None,use_binaries=0):
+ """Takes an unreduced and reduced deplist and removes satisfied dependencies.
+ Returned deplist contains steps that must be taken to satisfy dependencies."""
+ writemsg("ZapDeps -- %s\n" % (use_binaries), 2)
+ if unreduced==[] or unreduced==['||'] :
+ return []
+ if unreduced[0]=="||":
+ if dep_eval(reduced):
+ #deps satisfied, return empty list.
+ return []
+ else:
+ #try to find an installed dep.
+ ### We use fakedb when --update now, so we can't use local vardbapi here.
+ ### This should be fixed in the feature.
+ ### see bug 45468.
+ ##if vardbapi:
+ ## mydbapi=vardbapi
+ ##else:
+ ## mydbapi=db[root]["vartree"].dbapi
+ mydbapi=db[root]["vartree"].dbapi
+
+ if db["/"].has_key("porttree"):
+ myportapi=db["/"]["porttree"].dbapi
+ else:
+ myportapi=None
+
+ if use_binaries and db["/"].has_key("bintree"):
+ mybinapi=db["/"]["bintree"].dbapi
+ writemsg("Using bintree...\n",2)
+ else:
+ mybinapi=None
+
+ x=1
+ candidate=[]
+ while x<len(reduced):
+ writemsg("x: %s, reduced[x]: %s\n" % (x,reduced[x]), 2)
+ if (type(reduced[x])==types.ListType):
+ newcand = dep_zapdeps(unreduced[x], reduced[x], vardbapi=vardbapi, use_binaries=use_binaries)
+ candidate.append(newcand)
+ else:
+ if (reduced[x]==False):
+ candidate.append([unreduced[x]])
+ else:
+ candidate.append([])
+ x+=1
+
+ #use installed and no-masked package(s) in portage.
+ for x in candidate:
+ match=1
+ for pkg in x:
+ if not mydbapi.match(pkg):
+ match=0
+ break
+ if myportapi:
+ if not myportapi.match(pkg):
+ match=0
+ break
+ if match:
+ writemsg("Installed match: %s\n" % (x), 2)
+ return x
+
+ # Use binary packages if available.
+ if mybinapi:
+ for x in candidate:
+ match=1
+ for pkg in x:
+ if not mybinapi.match(pkg):
+ match=0
+ break
+ else:
+ writemsg("Binary match: %s\n" % (pkg), 2)
+ if match:
+ writemsg("Binary match final: %s\n" % (x), 2)
+ return x
+
+ #use no-masked package(s) in portage tree
+ if myportapi:
+ for x in candidate:
+ match=1
+ for pkg in x:
+ if not myportapi.match(pkg):
+ match=0
+ break
+ if match:
+ writemsg("Porttree match: %s\n" % (x), 2)
+ return x
+
+ #none of the no-masked pkg, use the first one
+ writemsg("Last resort candidate: %s\n" % (candidate[0]), 2)
+ return candidate[0]
+ else:
+ if dep_eval(reduced):
+ #deps satisfied, return empty list.
+ return []
+ else:
+ returnme=[]
+ x=0
+ while x<len(reduced):
+ if type(reduced[x])==types.ListType:
+ returnme+=dep_zapdeps(unreduced[x],reduced[x], vardbapi=vardbapi, use_binaries=use_binaries)
+ else:
+ if reduced[x]==False:
+ returnme.append(unreduced[x])
+ x += 1
+ return returnme
+
+def dep_getkey(mydep):
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ if mydep[0]=="!":
+ mydep=mydep[1:]
+ if mydep[:2] in [ ">=", "<=" ]:
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~":
+ mydep=mydep[1:]
+ if isspecific(mydep):
+ mysplit=catpkgsplit(mydep)
+ if not mysplit:
+ return mydep
+ return mysplit[0]+"/"+mysplit[1]
+ else:
+ return mydep
+
+def dep_getcpv(mydep):
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ if mydep[0]=="!":
+ mydep=mydep[1:]
+ if mydep[:2] in [ ">=", "<=" ]:
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~":
+ mydep=mydep[1:]
+ return mydep
+
+def cpv_getkey(mycpv):
+ myslash=mycpv.split("/")
+ mysplit=pkgsplit(myslash[-1])
+ mylen=len(myslash)
+ if mylen==2:
+ return myslash[0]+"/"+mysplit[0]
+ elif mylen==1:
+ return mysplit[0]
+ else:
+ return mysplit
+
+def key_expand(mykey,mydb=None,use_cache=1):
+ mysplit=mykey.split("/")
+ if len(mysplit)==1:
+ if mydb and type(mydb)==types.InstanceType:
+ for x in settings.categories:
+ if mydb.cp_list(x+"/"+mykey,use_cache=use_cache):
+ return x+"/"+mykey
+ if virts_p.has_key(mykey):
+ return(virts_p[mykey][0])
+ return "null/"+mykey
+ elif mydb:
+ if type(mydb)==types.InstanceType:
+ if (not mydb.cp_list(mykey,use_cache=use_cache)) and virts and virts.has_key(mykey):
+ return virts[mykey][0]
+ return mykey
+
+def cpv_expand(mycpv,mydb=None,use_cache=1):
+ """Given a string (packagename or virtual) expand it into a valid
+ cat/package string. Virtuals use the mydb to determine which provided
+ virtual is a valid choice and defaults to the first element when there
+ are no installed/available candidates."""
+ myslash=mycpv.split("/")
+ mysplit=pkgsplit(myslash[-1])
+ if len(myslash)>2:
+ # this is illegal case.
+ mysplit=[]
+ mykey=mycpv
+ elif len(myslash)==2:
+ if mysplit:
+ mykey=myslash[0]+"/"+mysplit[0]
+ else:
+ mykey=mycpv
+ if mydb:
+ writemsg("mydb.__class__: %s\n" % (mydb.__class__), 1)
+ if type(mydb)==types.InstanceType:
+ if (not mydb.cp_list(mykey,use_cache=use_cache)) and virts and virts.has_key(mykey):
+ writemsg("virts[%s]: %s\n" % (str(mykey),virts[mykey]), 1)
+ mykey_orig = mykey[:]
+ for vkey in virts[mykey]:
+ if mydb.cp_list(vkey,use_cache=use_cache):
+ mykey = vkey
+ writemsg("virts chosen: %s\n" % (mykey), 1)
+ break
+ if mykey == mykey_orig:
+ mykey=virts[mykey][0]
+ writemsg("virts defaulted: %s\n" % (mykey), 1)
+ #we only perform virtual expansion if we are passed a dbapi
+ else:
+ #specific cpv, no category, ie. "foo-1.0"
+ if mysplit:
+ myp=mysplit[0]
+ else:
+ # "foo" ?
+ myp=mycpv
+ mykey=None
+ matches=[]
+ if mydb:
+ for x in settings.categories:
+ if mydb.cp_list(x+"/"+myp,use_cache=use_cache):
+ matches.append(x+"/"+myp)
+ if (len(matches)>1):
+ raise ValueError, matches
+ elif matches:
+ mykey=matches[0]
+
+ if not mykey and type(mydb)!=types.ListType:
+ if virts_p.has_key(myp):
+ mykey=virts_p[myp][0]
+ #again, we only perform virtual expansion if we have a dbapi (not a list)
+ if not mykey:
+ mykey="null/"+myp
+ if mysplit:
+ if mysplit[2]=="r0":
+ return mykey+"-"+mysplit[1]
+ else:
+ return mykey+"-"+mysplit[1]+"-"+mysplit[2]
+ else:
+ return mykey
+
+def dep_transform(mydep,oldkey,newkey):
+ origdep=mydep
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ prefix=""
+ postfix=""
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ postfix="*"
+ if mydep[:2] in [ ">=", "<=" ]:
+ prefix=mydep[:2]
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~!":
+ prefix=mydep[:1]
+ mydep=mydep[1:]
+ if mydep==oldkey:
+ return prefix+newkey+postfix
+ else:
+ return origdep
+
+def dep_expand(mydep,mydb=None,use_cache=1):
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ prefix=""
+ postfix=""
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ postfix="*"
+ if mydep[:2] in [ ">=", "<=" ]:
+ prefix=mydep[:2]
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~!":
+ prefix=mydep[:1]
+ mydep=mydep[1:]
+ return prefix+cpv_expand(mydep,mydb=mydb,use_cache=use_cache)+postfix
+
+def dep_check(depstring,mydbapi,mysettings,use="yes",mode=None,myuse=None,use_cache=1,use_binaries=0):
+ """Takes a depend string and parses the condition."""
+
+ #check_config_instance(mysettings)
+
+ if use=="all":
+ #enable everything (for repoman)
+ myusesplit=["*"]
+ elif use=="yes":
+ if myuse==None:
+ #default behavior
+ myusesplit = string.split(mysettings["USE"])
+ else:
+ myusesplit = myuse
+ # We've been given useflags to use.
+ #print "USE FLAGS PASSED IN."
+ #print myuse
+ #if "bindist" in myusesplit:
+ # print "BINDIST is set!"
+ #else:
+ # print "BINDIST NOT set."
+ else:
+ #we are being run by autouse(), don't consult USE vars yet.
+ # WE ALSO CANNOT USE SETTINGS
+ myusesplit=[]
+
+ #convert parenthesis to sublists
+ mysplit = portage_dep.paren_reduce(depstring)
+
+ if mysettings:
+ # XXX: use="all" is only used by repoman. Why would repoman checks want
+ # profile-masked USE flags to be enabled?
+ #if use=="all":
+ # mymasks=archlist[:]
+ #else:
+ mymasks=mysettings.usemask+archlist[:]
+
+ while mysettings["ARCH"] in mymasks:
+ del mymasks[mymasks.index(mysettings["ARCH"])]
+ mysplit = portage_dep.use_reduce(mysplit,uselist=myusesplit,masklist=mymasks,matchall=(use=="all"),excludeall=[mysettings["ARCH"]])
+ else:
+ mysplit = portage_dep.use_reduce(mysplit,uselist=myusesplit,matchall=(use=="all"))
+
+ # Do the || conversions
+ mysplit=portage_dep.dep_opconvert(mysplit)
+
+ #convert virtual dependencies to normal packages.
+ mysplit=dep_virtual(mysplit, mysettings)
+ #if mysplit==None, then we have a parse error (paren mismatch or misplaced ||)
+ #up until here, we haven't needed to look at the database tree
+
+ if mysplit==None:
+ return [0,"Parse Error (parentheses mismatch?)"]
+ elif mysplit==[]:
+ #dependencies were reduced to nothing
+ return [1,[]]
+ mysplit2=mysplit[:]
+ mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache)
+ if mysplit2==None:
+ return [0,"Invalid token"]
+
+ writemsg("\n\n\n", 1)
+ writemsg("mysplit: %s\n" % (mysplit), 1)
+ writemsg("mysplit2: %s\n" % (mysplit2), 1)
+ myeval=dep_eval(mysplit2)
+ writemsg("myeval: %s\n" % (myeval), 1)
+
+ if myeval:
+ return [1,[]]
+ else:
+ myzaps = dep_zapdeps(mysplit,mysplit2,vardbapi=mydbapi,use_binaries=use_binaries)
+ mylist = flatten(myzaps)
+ writemsg("myzaps: %s\n" % (myzaps), 1)
+ writemsg("mylist: %s\n" % (mylist), 1)
+ #remove duplicates
+ mydict={}
+ for x in mylist:
+ mydict[x]=1
+ writemsg("mydict: %s\n" % (mydict), 1)
+ return [1,mydict.keys()]
+
+def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
+ "Reduces the deplist to ones and zeros"
+ mypos=0
+ deplist=mydeplist[:]
+ while mypos<len(deplist):
+ if type(deplist[mypos])==types.ListType:
+ #recurse
+ deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache)
+ elif deplist[mypos]=="||":
+ pass
+ else:
+ mykey = dep_getkey(deplist[mypos])
+ if mysettings and mysettings.pprovideddict.has_key(mykey) and \
+ match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
+ deplist[mypos]=True
+ else:
+ if mode:
+ mydep=mydbapi.xmatch(mode,deplist[mypos])
+ else:
+ mydep=mydbapi.match(deplist[mypos],use_cache=use_cache)
+ if mydep!=None:
+ tmp=(len(mydep)>=1)
+ if deplist[mypos][0]=="!":
+ #tmp=not tmp
+ # This is ad-hoc code. We should rewrite this later.. (See #52377)
+ # The reason is that portage uses fakedb when --update option now.
+ # So portage considers that a block package doesn't exist even if it exists.
+ # Then, #52377 happens.
+ # ==== start
+ # emerge checks if it's block or not, so we can always set tmp=False.
+ # but it's not clean..
+ tmp=False
+ # ==== end
+ deplist[mypos]=tmp
+ else:
+ #encountered invalid string
+ return None
+ mypos=mypos+1
+ return deplist
+
+def getmaskingreason(mycpv):
+ global portdb
+ mysplit = catpkgsplit(mycpv)
+ if not mysplit:
+ raise ValueError("invalid CPV: %s" % mycpv)
+ if not portdb.cpv_exists(mycpv):
+ raise KeyError("CPV %s does not exist" % mycpv)
+ mycp=mysplit[0]+"/"+mysplit[1]
+
+ if settings.pmaskdict.has_key(mycp):
+ for x in settings.pmaskdict[mycp]:
+ if mycpv in portdb.xmatch("match-all", x):
+ pmaskfile = open(settings["PORTDIR"]+"/profiles/package.mask")
+ comment = ""
+ l = "\n"
+ while len(l) > 0:
+ l = pmaskfile.readline()
+ if len(l) == 0:
+ pmaskfile.close()
+ return None
+ if l[0] == "#":
+ comment += l
+ elif l == "\n":
+ comment = ""
+ elif l.strip() == x:
+ pmaskfile.close()
+ return comment
+ pmaskfile.close()
+ return None
+
+def getmaskingstatus(mycpv):
+ global portdb
+ mysplit = catpkgsplit(mycpv)
+ if not mysplit:
+ raise ValueError("invalid CPV: %s" % mycpv)
+ if not portdb.cpv_exists(mycpv):
+ raise KeyError("CPV %s does not exist" % mycpv)
+ mycp=mysplit[0]+"/"+mysplit[1]
+
+ rValue = []
+
+ # profile checking
+ revmaskdict=settings.prevmaskdict
+ if revmaskdict.has_key(mycp):
+ for x in revmaskdict[mycp]:
+ if x[0]=="*":
+ myatom = x[1:]
+ else:
+ myatom = x
+ if not match_to_list(mycpv, [myatom]):
+ rValue.append("profile")
+ break
+
+ # package.mask checking
+ maskdict=settings.pmaskdict
+ unmaskdict=settings.punmaskdict
+ if maskdict.has_key(mycp):
+ for x in maskdict[mycp]:
+ if mycpv in portdb.xmatch("match-all", x):
+ unmask=0
+ if unmaskdict.has_key(mycp):
+ for z in unmaskdict[mycp]:
+ if mycpv in portdb.xmatch("match-all",z):
+ unmask=1
+ break
+ if unmask==0:
+ rValue.append("package.mask")
+
+ # keywords checking
+ mygroups = portdb.aux_get(mycpv, ["KEYWORDS"])[0].split()
+ pgroups=groups[:]
+ myarch = settings["ARCH"]
+ pkgdict = settings.pkeywordsdict
+
+ cp = dep_getkey(mycpv)
+ if pkgdict.has_key(cp):
+ matches = match_to_list(mycpv, pkgdict[cp].keys())
+ for match in matches:
+ pgroups.extend(pkgdict[cp][match])
+
+ kmask = "missing"
+
+ for keyword in pgroups:
+ if keyword in mygroups:
+ kmask=None
+
+ if kmask:
+ fallback = None
+ for gp in mygroups:
+ if gp=="*":
+ kmask=None
+ break
+ elif gp=="-*":
+ fallback="-*"
+ elif gp=="-"+myarch:
+ kmask="-"+myarch
+ break
+ elif gp=="~"+myarch:
+ kmask="~"+myarch
+ break
+ if kmask == "missing" and fallback:
+ kmask = fallback
+
+ if kmask:
+ rValue.append(kmask+" keyword")
+ return rValue
+
+def fixdbentries(old_value, new_value, dbdir):
+ """python replacement for the fixdbentries script, replaces old_value
+ with new_value for package names in files in dbdir."""
+ for myfile in [f for f in os.listdir(dbdir) if not f == "CONTENTS"]:
+ f = open(dbdir+"/"+myfile, "r")
+ mycontent = f.read()
+ f.close()
+ if not mycontent.count(old_value):
+ continue
+ old_value = re.escape(old_value);
+ mycontent = re.sub(old_value+"$", new_value, mycontent)
+ mycontent = re.sub(old_value+"(\\s)", new_value+"\\1", mycontent)
+ mycontent = re.sub(old_value+"(-[^a-zA-Z])", new_value+"\\1", mycontent)
+ mycontent = re.sub(old_value+"([^a-zA-Z0-9-])", new_value+"\\1", mycontent)
+ f = open(dbdir+"/"+myfile, "w")
+ f.write(mycontent)
+ f.close()
+
+class packagetree:
+ def __init__(self,virtual,clone=None):
+ if clone:
+ self.tree=clone.tree.copy()
+ self.populated=clone.populated
+ self.virtual=clone.virtual
+ self.dbapi=None
+ else:
+ self.tree={}
+ self.populated=0
+ self.virtual=virtual
+ self.dbapi=None
+
+ def resolve_key(self,mykey):
+ return key_expand(mykey,mydb=self.dbapi)
+
+ def dep_nomatch(self,mypkgdep):
+ mykey=dep_getkey(mypkgdep)
+ nolist=self.dbapi.cp_list(mykey)
+ mymatch=self.dbapi.match(mypkgdep)
+ if not mymatch:
+ return nolist
+ for x in mymatch:
+ if x in nolist:
+ nolist.remove(x)
+ return nolist
+
+ def depcheck(self,mycheck,use="yes",myusesplit=None):
+ return dep_check(mycheck,self.dbapi,use=use,myuse=myusesplit)
+
+ def populate(self):
+ "populates the tree with values"
+ populated=1
+ pass
+
+def best(mymatches):
+ "accepts None arguments; assumes matches are valid."
+ global bestcount
+ if mymatches==None:
+ return ""
+ if not len(mymatches):
+ return ""
+ bestmatch=mymatches[0]
+ p2=catpkgsplit(bestmatch)[1:]
+ for x in mymatches[1:]:
+ p1=catpkgsplit(x)[1:]
+ if pkgcmp(p1,p2)>0:
+ bestmatch=x
+ p2=catpkgsplit(bestmatch)[1:]
+ return bestmatch
+
+def match_to_list(mypkg,mylist):
+ """(pkgname,list)
+ Searches list for entries that matches the package.
+ """
+ matches=[]
+ for x in mylist:
+ if match_from_list(x,[mypkg]):
+ if x not in matches:
+ matches.append(x)
+ return matches
+
+def best_match_to_list(mypkg,mylist):
+ """(pkgname,list)
+ Returns the most specific entry (assumed to be the longest one)
+ that matches the package given.
+ """
+ # XXX Assumption is wrong sometimes.
+ maxlen = 0
+ bestm = None
+ for x in match_to_list(mypkg,mylist):
+ if len(x) > maxlen:
+ maxlen = len(x)
+ bestm = x
+ return bestm
+
+def catsplit(mydep):
+ return mydep.split("/", 1)
+
+def get_operator(mydep):
+ """
+ returns '~', '=', '>', '<', '=*', '>=', or '<='
+ """
+ if mydep[0] == "~":
+ operator = "~"
+ elif mydep[0] == "=":
+ if mydep[-1] == "*":
+ operator = "=*"
+ else:
+ operator = "="
+ elif mydep[0] in "><":
+ if len(mydep) > 1 and mydep[1] == "=":
+ operator = mydep[0:2]
+ else:
+ operator = mydep[0]
+ else:
+ operator = None
+
+ return operator
+
+
+def match_from_list(mydep,candidate_list):
+ if mydep[0] == "!":
+ mydep = mydep[1:]
+
+ mycpv = dep_getcpv(mydep)
+ mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
+
+ if not mycpv_cps:
+ cat,pkg = catsplit(mycpv)
+ ver = None
+ rev = None
+ else:
+ cat,pkg,ver,rev = mycpv_cps
+ if mydep == mycpv:
+ raise KeyError, "Specific key requires an operator (%s) (try adding an '=')" % (mydep)
+
+ if ver and rev:
+ operator = get_operator(mydep)
+ if not operator:
+ writemsg("!!! Invalid atom: %s\n" % mydep)
+ return []
+ else:
+ operator = None
+
+ mylist = []
+
+ if operator == None:
+ for x in candidate_list:
+ xs = pkgsplit(x)
+ if xs == None:
+ if x != mycpv:
+ continue
+ elif xs[0] != mycpv:
+ continue
+ mylist.append(x)
+
+ elif operator == "=": # Exact match
+ if mycpv in candidate_list:
+ mylist = [mycpv]
+
+ elif operator == "=*": # glob match
+ # The old verion ignored _tag suffixes... This one doesn't.
+ for x in candidate_list:
+ if x[0:len(mycpv)] == mycpv:
+ mylist.append(x)
+
+ elif operator == "~": # version, any revision, match
+ for x in candidate_list:
+ xs = catpkgsplit(x)
+ if xs[0:2] != mycpv_cps[0:2]:
+ continue
+ if xs[2] != ver:
+ continue
+ mylist.append(x)
+
+ elif operator in [">", ">=", "<", "<="]:
+ for x in candidate_list:
+ try:
+ result = pkgcmp(pkgsplit(x), [cat+"/"+pkg,ver,rev])
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("\nInvalid package name: %s\n" % x)
+ sys.exit(73)
+ if result == None:
+ continue
+ elif operator == ">":
+ if result > 0:
+ mylist.append(x)
+ elif operator == ">=":
+ if result >= 0:
+ mylist.append(x)
+ elif operator == "<":
+ if result < 0:
+ mylist.append(x)
+ elif operator == "<=":
+ if result <= 0:
+ mylist.append(x)
+ else:
+ raise KeyError, "Unknown operator: %s" % mydep
+ else:
+ raise KeyError, "Unknown operator: %s" % mydep
+
+
+ return mylist
+
+
+def match_from_list_original(mydep,mylist):
+ """(dep,list)
+ Reduces the list down to those that fit the dep
+ """
+ mycpv=dep_getcpv(mydep)
+ if isspecific(mycpv):
+ cp_key=catpkgsplit(mycpv)
+ if cp_key==None:
+ return []
+ else:
+ cp_key=None
+ #Otherwise, this is a special call; we can only select out of the ebuilds specified in the specified mylist
+ if (mydep[0]=="="):
+ if cp_key==None:
+ return []
+ if mydep[-1]=="*":
+ #example: "=sys-apps/foo-1.0*"
+ try:
+ #now, we grab the version of our dependency...
+ mynewsplit=string.split(cp_key[2],'.')
+ #split it...
+ mynewsplit[-1]=`int(mynewsplit[-1])+1`
+ #and increment the last digit of the version by one.
+ #We don't need to worry about _pre and friends because they're not supported with '*' deps.
+ new_v=string.join(mynewsplit,".")+"_alpha0"
+ #new_v will be used later in the code when we do our comparisons using pkgcmp()
+ except SystemExit, e:
+ raise
+ except:
+ #erp, error.
+ return []
+ mynodes=[]
+ cmp1=cp_key[1:]
+ cmp1[1]=cmp1[1]+"_alpha0"
+ cmp2=[cp_key[1],new_v,"r0"]
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #hrm, invalid entry. Continue.
+ continue
+ #skip entries in our list that do not have matching categories
+ if cp_key[0]!=cp_x[0]:
+ continue
+ # ok, categories match. Continue to next step.
+ if ((pkgcmp(cp_x[1:],cmp1)>=0) and (pkgcmp(cp_x[1:],cmp2)<0)):
+ # entry is >= the version in specified in our dependency, and <= the version in our dep + 1; add it:
+ mynodes.append(x)
+ return mynodes
+ else:
+ # Does our stripped key appear literally in our list? If so, we have a match; if not, we don't.
+ if mycpv in mylist:
+ return [mycpv]
+ else:
+ return []
+ elif (mydep[0]==">") or (mydep[0]=="<"):
+ if cp_key==None:
+ return []
+ if (len(mydep)>1) and (mydep[1]=="="):
+ cmpstr=mydep[0:2]
+ else:
+ cmpstr=mydep[0]
+ mynodes=[]
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #invalid entry; continue.
+ continue
+ if cp_key[0]!=cp_x[0]:
+ continue
+ if eval("pkgcmp(cp_x[1:],cp_key[1:])"+cmpstr+"0"):
+ mynodes.append(x)
+ return mynodes
+ elif mydep[0]=="~":
+ if cp_key==None:
+ return []
+ myrev=-1
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #invalid entry; continue
+ continue
+ if cp_key[0]!=cp_x[0]:
+ continue
+ if cp_key[2]!=cp_x[2]:
+ #if version doesn't match, skip it
+ continue
+ myint = int(cp_x[3][1:])
+ if myint > myrev:
+ myrev = myint
+ mymatch = x
+ if myrev == -1:
+ return []
+ else:
+ return [mymatch]
+ elif cp_key==None:
+ if mydep[0]=="!":
+ return []
+ #we check ! deps in emerge itself, so always returning [] is correct.
+ mynodes=[]
+ cp_key=mycpv.split("/")
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #invalid entry; continue
+ continue
+ if cp_key[0]!=cp_x[0]:
+ continue
+ if cp_key[1]!=cp_x[1]:
+ continue
+ mynodes.append(x)
+ return mynodes
+ else:
+ return []
+
+
+class portagetree:
+ def __init__(self,root="/",virtual=None,clone=None):
+ global portdb
+ if clone:
+ self.root=clone.root
+ self.portroot=clone.portroot
+ self.pkglines=clone.pkglines
+ else:
+ self.root=root
+ self.portroot=settings["PORTDIR"]
+ self.virtual=virtual
+ self.dbapi=portdb
+
+ def dep_bestmatch(self,mydep):
+ "compatibility method"
+ mymatch=self.dbapi.xmatch("bestmatch-visible",mydep)
+ if mymatch==None:
+ return ""
+ return mymatch
+
+ def dep_match(self,mydep):
+ "compatibility method"
+ mymatch=self.dbapi.xmatch("match-visible",mydep)
+ if mymatch==None:
+ return []
+ return mymatch
+
+ def exists_specific(self,cpv):
+ return self.dbapi.cpv_exists(cpv)
+
+ def getallnodes(self):
+ """new behavior: these are all *unmasked* nodes. There may or may not be available
+ masked package for nodes in this nodes list."""
+ return self.dbapi.cp_all()
+
+ def getname(self,pkgname):
+ "returns file location for this particular package (DEPRECATED)"
+ if not pkgname:
+ return ""
+ mysplit=string.split(pkgname,"/")
+ psplit=pkgsplit(mysplit[1])
+ return self.portroot+"/"+mysplit[0]+"/"+psplit[0]+"/"+mysplit[1]+".ebuild"
+
+ def resolve_specific(self,myspec):
+ cps=catpkgsplit(myspec)
+ if not cps:
+ return None
+ mykey=key_expand(cps[0]+"/"+cps[1],mydb=self.dbapi)
+ mykey=mykey+"-"+cps[2]
+ if cps[3]!="r0":
+ mykey=mykey+"-"+cps[3]
+ return mykey
+
+ def depcheck(self,mycheck,use="yes",myusesplit=None):
+ return dep_check(mycheck,self.dbapi,use=use,myuse=myusesplit)
+
+ def getslot(self,mycatpkg):
+ "Get a slot for a catpkg; assume it exists."
+ myslot = ""
+ try:
+ myslot=self.dbapi.aux_get(mycatpkg,["SLOT"])[0]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+ return myslot
+
+
+class dbapi:
+ def __init__(self):
+ pass
+
+ def close_caches(self):
+ pass
+
+ def cp_list(self,cp,use_cache=1):
+ return
+
+ def aux_get(self,mycpv,mylist):
+ "stub code for returning auxiliary db information, such as SLOT, DEPEND, etc."
+ 'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
+ 'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or [] if mycpv not found'
+ raise NotImplementedError
+
+ def match(self,origdep,use_cache=1):
+ mydep=dep_expand(origdep,mydb=self)
+ mykey=dep_getkey(mydep)
+ mycat=mykey.split("/")[0]
+ return match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+
+ def match2(self,mydep,mykey,mylist):
+ writemsg("DEPRECATED: dbapi.match2\n")
+ match_from_list(mydep,mylist)
+
+ def counter_tick(self,myroot,mycpv=None):
+ return self.counter_tick_core(myroot,incrementing=1,mycpv=mycpv)
+
+ def get_counter_tick_core(self,myroot,mycpv=None):
+ return self.counter_tick_core(myroot,incrementing=0,mycpv=mycpv)+1
+
+ def counter_tick_core(self,myroot,incrementing=1,mycpv=None):
+ "This method will grab the next COUNTER value and record it back to the global file. Returns new counter value."
+ cpath=myroot+"var/cache/edb/counter"
+ changed=0
+ min_counter = 0
+ if mycpv:
+ mysplit = pkgsplit(mycpv)
+ for x in self.match(mysplit[0],use_cache=0):
+ # fixed bug #41062
+ if x==mycpv:
+ continue
+ try:
+ old_counter = long(self.aux_get(x,["COUNTER"])[0])
+ writemsg("COUNTER '%d' '%s'\n" % (old_counter, x),1)
+ except SystemExit, e:
+ raise
+ except:
+ old_counter = 0
+ writemsg("!!! BAD COUNTER in '%s'\n" % (x))
+ if old_counter > min_counter:
+ min_counter = old_counter
+
+ # We write our new counter value to a new file that gets moved into
+ # place to avoid filesystem corruption.
+ if os.path.exists(cpath):
+ cfile=open(cpath, "r")
+ try:
+ counter=long(cfile.readline())
+ except (ValueError,OverflowError):
+ try:
+ counter=long(commands.getoutput("for FILE in $(find /"+VDB_PATH+" -type f -name COUNTER); do echo $(<${FILE}); done | sort -n | tail -n1 | tr -d '\n'"))
+ writemsg("!!! COUNTER was corrupted; resetting to value of %d\n" % counter)
+ changed=1
+ except (ValueError,OverflowError):
+ writemsg("!!! COUNTER data is corrupt in pkg db. The values need to be\n")
+ writemsg("!!! corrected/normalized so that portage can operate properly.\n")
+ writemsg("!!! A simple solution is not yet available so try #gentoo on IRC.\n")
+ sys.exit(2)
+ cfile.close()
+ else:
+ try:
+ counter=long(commands.getoutput("for FILE in $(find /"+VDB_PATH+" -type f -name COUNTER); do echo $(<${FILE}); done | sort -n | tail -n1 | tr -d '\n'"))
+ writemsg("!!! Global counter missing. Regenerated from counter files to: %s\n" % counter)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("!!! Initializing global counter.\n")
+ counter=long(0)
+ changed=1
+
+ if counter < min_counter:
+ counter = min_counter+1000
+ changed = 1
+
+ if incrementing or changed:
+
+ #increment counter
+ counter += 1
+ # update new global counter file
+ newcpath=cpath+".new"
+ newcfile=open(newcpath,"w")
+ newcfile.write(str(counter))
+ newcfile.close()
+ # now move global counter file into place
+ os.rename(newcpath,cpath)
+ return counter
+
+ def invalidentry(self, mypath):
+ if re.search("portage_lockfile$",mypath):
+ if not os.environ.has_key("PORTAGE_MASTER_PID"):
+ writemsg("Lockfile removed: %s\n" % mypath, 1)
+ portage_locks.unlockfile((mypath,None,None))
+ else:
+ # Nothing we can do about it. We're probably sandboxed.
+ pass
+ elif re.search(".*/-MERGING-(.*)",mypath):
+ if os.path.exists(mypath):
+ writemsg(red("INCOMPLETE MERGE:")+" "+mypath+"\n")
+ else:
+ writemsg("!!! Invalid db entry: %s\n" % mypath)
+
+
+
+class fakedbapi(dbapi):
+ "This is a dbapi to use for the emptytree function. It's empty, but things can be added to it."
+ def __init__(self):
+ self.cpvdict={}
+ self.cpdict={}
+
+ def cpv_exists(self,mycpv):
+ return self.cpvdict.has_key(mycpv)
+
+ def cp_list(self,mycp,use_cache=1):
+ if not self.cpdict.has_key(mycp):
+ return []
+ else:
+ return self.cpdict[mycp]
+
+ def cp_all(self):
+ returnme=[]
+ for x in self.cpdict.keys():
+ returnme.extend(self.cpdict[x])
+ return returnme
+
+ def cpv_inject(self,mycpv):
+ """Adds a cpv from the list of available packages."""
+ mycp=cpv_getkey(mycpv)
+ self.cpvdict[mycpv]=1
+ if not self.cpdict.has_key(mycp):
+ self.cpdict[mycp]=[]
+ if not mycpv in self.cpdict[mycp]:
+ self.cpdict[mycp].append(mycpv)
+
+ #def cpv_virtual(self,oldcpv,newcpv):
+ # """Maps a cpv to the list of available packages."""
+ # mycp=cpv_getkey(newcpv)
+ # self.cpvdict[newcpv]=1
+ # if not self.virtdict.has_key(mycp):
+ # self.virtdict[mycp]=[]
+ # if not mycpv in self.virtdict[mycp]:
+ # self.virtdict[mycp].append(oldcpv)
+ # cpv_remove(oldcpv)
+
+ def cpv_remove(self,mycpv):
+ """Removes a cpv from the list of available packages."""
+ mycp=cpv_getkey(mycpv)
+ if self.cpvdict.has_key(mycpv):
+ del self.cpvdict[mycpv]
+ if not self.cpdict.has_key(mycp):
+ return
+ while mycpv in self.cpdict[mycp]:
+ del self.cpdict[mycp][self.cpdict[mycp].index(mycpv)]
+ if not len(self.cpdict[mycp]):
+ del self.cpdict[mycp]
+
+class bindbapi(fakedbapi):
+ def __init__(self,mybintree=None):
+ self.bintree = mybintree
+ self.cpvdict={}
+ self.cpdict={}
+
+ def aux_get(self,mycpv,wants):
+ mysplit = string.split(mycpv,"/")
+ mylist = []
+ tbz2name = mysplit[1]+".tbz2"
+ if self.bintree and not self.bintree.isremote(mycpv):
+ tbz2 = xpak.tbz2(self.bintree.getname(mycpv))
+ for x in wants:
+ if self.bintree and self.bintree.isremote(mycpv):
+ # We use the cache for remote packages
+ if self.bintree.remotepkgs[tbz2name].has_key(x):
+ mylist.append(self.bintree.remotepkgs[tbz2name][x][:]) # [:] Copy String
+ else:
+ mylist.append("")
+ else:
+ myval = tbz2.getfile(x)
+ if myval == None:
+ myval = ""
+ else:
+ myval = string.join(myval.split(),' ')
+ mylist.append(myval)
+
+ return mylist
+
+
+cptot=0
+class vardbapi(dbapi):
+ def __init__(self,root,categories=None):
+ self.root = root[:]
+ #cache for category directory mtimes
+ self.mtdircache = {}
+ #cache for dependency checks
+ self.matchcache = {}
+ #cache for cp_list results
+ self.cpcache = {}
+ self.blockers = None
+ self.categories = copy.deepcopy(categories)
+
+ def cpv_exists(self,mykey):
+ "Tells us whether an actual ebuild exists on disk (no masking)"
+ return os.path.exists(self.root+VDB_PATH+"/"+mykey)
+
+ def cpv_counter(self,mycpv):
+ "This method will grab the COUNTER. Returns a counter value."
+ cdir=self.root+VDB_PATH+"/"+mycpv
+ cpath=self.root+VDB_PATH+"/"+mycpv+"/COUNTER"
+
+ # We write our new counter value to a new file that gets moved into
+ # place to avoid filesystem corruption on XFS (unexpected reboot.)
+ corrupted=0
+ if os.path.exists(cpath):
+ cfile=open(cpath, "r")
+ try:
+ counter=long(cfile.readline())
+ except ValueError:
+ print "portage: COUNTER for",mycpv,"was corrupted; resetting to value of 0"
+ counter=long(0)
+ corrupted=1
+ cfile.close()
+ elif os.path.exists(cdir):
+ mys = pkgsplit(mycpv)
+ myl = self.match(mys[0],use_cache=0)
+ print mys,myl
+ if len(myl) == 1:
+ try:
+ # Only one package... Counter doesn't matter.
+ myf = open(cpath, "w")
+ myf.write("1")
+ myf.flush()
+ myf.close()
+ counter = 1
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! COUNTER file is missing for "+str(mycpv)+" in /var/db.\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.pl or\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.py or\n")
+ writemsg("!!! unmerge this exact version.\n")
+ writemsg("!!! %s\n" % e)
+ sys.exit(1)
+ else:
+ writemsg("!!! COUNTER file is missing for "+str(mycpv)+" in /var/db.\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.pl or\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.py or\n")
+ writemsg("!!! remerge the package.\n")
+ sys.exit(1)
+ else:
+ counter=long(0)
+ if corrupted:
+ newcpath=cpath+".new"
+ # update new global counter file
+ newcfile=open(newcpath,"w")
+ newcfile.write(str(counter))
+ newcfile.close()
+ # now move global counter file into place
+ os.rename(newcpath,cpath)
+ return counter
+
+ def cpv_inject(self,mycpv):
+ "injects a real package into our on-disk database; assumes mycpv is valid and doesn't already exist"
+ os.makedirs(self.root+VDB_PATH+"/"+mycpv)
+ counter=db[self.root]["vartree"].dbapi.counter_tick(self.root,mycpv=mycpv)
+ # write local package counter so that emerge clean does the right thing
+ lcfile=open(self.root+VDB_PATH+"/"+mycpv+"/COUNTER","w")
+ lcfile.write(str(counter))
+ lcfile.close()
+
+ def isInjected(self,mycpv):
+ if self.cpv_exists(mycpv):
+ if os.path.exists(self.root+VDB_PATH+"/"+mycpv+"/INJECTED"):
+ return True
+ if not os.path.exists(self.root+VDB_PATH+"/"+mycpv+"/CONTENTS"):
+ return True
+ return False
+
+ def move_ent(self,mylist):
+ origcp=mylist[1]
+ newcp=mylist[2]
+ origmatches=self.match(origcp,use_cache=0)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+ mycpsplit=catpkgsplit(mycpv)
+ mynewcpv=newcp+"-"+mycpsplit[2]
+ mynewcat=newcp.split("/")[0]
+ if mycpsplit[3]!="r0":
+ mynewcpv += "-"+mycpsplit[3]
+ mycpsplit_new = catpkgsplit(mynewcpv)
+ origpath=self.root+VDB_PATH+"/"+mycpv
+ if not os.path.exists(origpath):
+ continue
+ writemsg("@")
+ if not os.path.exists(self.root+VDB_PATH+"/"+mynewcat):
+ #create the directory
+ os.makedirs(self.root+VDB_PATH+"/"+mynewcat)
+ newpath=self.root+VDB_PATH+"/"+mynewcpv
+ if os.path.exists(newpath):
+ #dest already exists; keep this puppy where it is.
+ continue
+ spawn(MOVE_BINARY+" "+origpath+" "+newpath,settings, free=1)
+
+ # We need to rename the ebuild now.
+ old_eb_path = newpath+"/"+mycpsplit[1] +"-"+mycpsplit[2]
+ new_eb_path = newpath+"/"+mycpsplit_new[1]+"-"+mycpsplit[2]
+ if mycpsplit[3] != "r0":
+ old_eb_path += "-"+mycpsplit[3]
+ new_eb_path += "-"+mycpsplit[3]
+ if os.path.exists(old_eb_path+".ebuild"):
+ os.rename(old_eb_path+".ebuild", new_eb_path+".ebuild")
+
+ catfile=open(newpath+"/CATEGORY", "w")
+ catfile.write(mynewcat+"\n")
+ catfile.close()
+
+ dbdir = self.root+VDB_PATH
+ for catdir in listdir(dbdir):
+ catdir = dbdir+"/"+catdir
+ if os.path.isdir(catdir):
+ for pkgdir in listdir(catdir):
+ pkgdir = catdir+"/"+pkgdir
+ if os.path.isdir(pkgdir):
+ fixdbentries(origcp, newcp, pkgdir)
+
+ def move_slot_ent(self,mylist):
+ pkg=mylist[1]
+ origslot=mylist[2]
+ newslot=mylist[3]
+
+ origmatches=self.match(pkg,use_cache=0)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+ origpath=self.root+VDB_PATH+"/"+mycpv
+ if not os.path.exists(origpath):
+ continue
+
+ slot=grabfile(origpath+"/SLOT");
+ if (not slot):
+ continue
+
+ if (slot[0]!=origslot):
+ continue
+
+ writemsg("s")
+ slotfile=open(origpath+"/SLOT", "w")
+ slotfile.write(newslot+"\n")
+ slotfile.close()
+
+ def cp_list(self,mycp,use_cache=1):
+ mysplit=mycp.split("/")
+ if mysplit[0] == '*':
+ mysplit[0] = mysplit[0][1:]
+ try:
+ mystat=os.stat(self.root+VDB_PATH+"/"+mysplit[0])[stat.ST_MTIME]
+ except OSError:
+ mystat=0
+ if use_cache and self.cpcache.has_key(mycp):
+ cpc=self.cpcache[mycp]
+ if cpc[0]==mystat:
+ return cpc[1]
+ list=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+
+ if (list==None):
+ return []
+ returnme=[]
+ for x in list:
+ if x[0] == '-':
+ #writemsg(red("INCOMPLETE MERGE:")+str(x[len("-MERGING-"):])+"\n")
+ continue
+ ps=pkgsplit(x)
+ if not ps:
+ self.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+ continue
+ if len(mysplit) > 1:
+ if ps[0]==mysplit[1]:
+ returnme.append(mysplit[0]+"/"+x)
+ if use_cache:
+ self.cpcache[mycp]=[mystat,returnme]
+ elif self.cpcache.has_key(mycp):
+ del self.cpcache[mycp]
+ return returnme
+
+ def cpv_all(self,use_cache=1):
+ returnme=[]
+ basepath = self.root+VDB_PATH+"/"
+
+ mycats = self.categories
+ if mycats == None:
+ # XXX: CIRCULAR DEP! This helps backwards compat. --NJ (10 Sept 2004)
+ mycats = settings.categories
+
+ for x in mycats:
+ for y in listdir(basepath+x,EmptyOnError=1):
+ subpath = x+"/"+y
+ # -MERGING- should never be a cpv, nor should files.
+ if os.path.isdir(basepath+subpath) and (pkgsplit(y) is not None):
+ returnme += [subpath]
+ return returnme
+
+ def cp_all(self,use_cache=1):
+ mylist = self.cpv_all(use_cache=use_cache)
+ d={}
+ for y in mylist:
+ if y[0] == '*':
+ y = y[1:]
+ mysplit=catpkgsplit(y)
+ if not mysplit:
+ self.invalidentry(self.root+VDB_PATH+"/"+y)
+ continue
+ d[mysplit[0]+"/"+mysplit[1]] = None
+ return d.keys()
+
+ def checkblockers(self,origdep):
+ pass
+
+ def match(self,origdep,use_cache=1):
+ "caching match function"
+ mydep=dep_expand(origdep,mydb=self,use_cache=use_cache)
+ mykey=dep_getkey(mydep)
+ mycat=mykey.split("/")[0]
+ if not use_cache:
+ if self.matchcache.has_key(mycat):
+ del self.mtdircache[mycat]
+ del self.matchcache[mycat]
+ return match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+ try:
+ curmtime=os.stat(self.root+VDB_PATH+"/"+mycat)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except:
+ curmtime=0
+
+ if not self.matchcache.has_key(mycat) or not self.mtdircache[mycat]==curmtime:
+ # clear cache entry
+ self.mtdircache[mycat]=curmtime
+ self.matchcache[mycat]={}
+ if not self.matchcache[mycat].has_key(mydep):
+ mymatch=match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+ self.matchcache[mycat][mydep]=mymatch
+ return self.matchcache[mycat][mydep][:]
+
+ def findname(self, mycpv):
+ return self.root+VDB_PATH+"/"+str(mycpv)+"/"+mycpv.split("/")[1]+".ebuild"
+
+ def aux_get(self, mycpv, wants):
+ global auxdbkeys
+ results = []
+ if not self.cpv_exists(mycpv):
+ return []
+ for x in wants:
+ myfn = self.root+VDB_PATH+"/"+str(mycpv)+"/"+str(x)
+ if os.access(myfn,os.R_OK):
+ myf = open(myfn, "r")
+ myd = myf.read()
+ myf.close()
+ myd = re.sub("[\n\r\t]+"," ",myd)
+ myd = re.sub(" +"," ",myd)
+ myd = string.strip(myd)
+ else:
+ myd = ""
+ results.append(myd)
+ return results
+
+
+class vartree(packagetree):
+ "this tree will scan a var/db/pkg database located at root (passed to init)"
+ def __init__(self,root="/",virtual=None,clone=None,categories=None):
+ if clone:
+ self.root = clone.root[:]
+ self.dbapi = copy.deepcopy(clone.dbapi)
+ self.populated = 1
+ else:
+ self.root = root[:]
+ self.dbapi = vardbapi(self.root,categories=categories)
+ self.populated = 1
+
+ def zap(self,mycpv):
+ return
+
+ def inject(self,mycpv):
+ return
+
+ def get_provide(self,mycpv):
+ myprovides=[]
+ try:
+ mylines = grabfile(self.root+VDB_PATH+"/"+mycpv+"/PROVIDE")
+ if mylines:
+ myuse = grabfile(self.root+VDB_PATH+"/"+mycpv+"/USE")
+ myuse = string.split(string.join(myuse))
+ mylines = string.join(mylines)
+ mylines = flatten(portage_dep.use_reduce(portage_dep.paren_reduce(mylines), uselist=myuse))
+ for myprovide in mylines:
+ mys = catpkgsplit(myprovide)
+ if not mys:
+ mys = string.split(myprovide, "/")
+ myprovides += [mys[0] + "/" + mys[1]]
+ return myprovides
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print
+ print "Check " + self.root+VDB_PATH+"/"+mycpv+"/PROVIDE and USE."
+ print "Possibly Invalid: " + str(mylines)
+ print "Exception: "+str(e)
+ print
+ return []
+
+ def get_all_provides(self):
+ myprovides = {}
+ for node in self.getallcpv():
+ for mykey in self.get_provide(node):
+ if myprovides.has_key(mykey):
+ myprovides[mykey] += [node]
+ else:
+ myprovides[mykey] = [node]
+ return myprovides
+
+ def dep_bestmatch(self,mydep,use_cache=1):
+ "compatibility method -- all matches, not just visible ones"
+ #mymatch=best(match(dep_expand(mydep,self.dbapi),self.dbapi))
+ mymatch=best(self.dbapi.match(dep_expand(mydep,mydb=self.dbapi),use_cache=use_cache))
+ if mymatch==None:
+ return ""
+ else:
+ return mymatch
+
+ def dep_match(self,mydep,use_cache=1):
+ "compatibility method -- we want to see all matches, not just visible ones"
+ #mymatch=match(mydep,self.dbapi)
+ mymatch=self.dbapi.match(mydep,use_cache=use_cache)
+ if mymatch==None:
+ return []
+ else:
+ return mymatch
+
+ def exists_specific(self,cpv):
+ return self.dbapi.cpv_exists(cpv)
+
+ def getallcpv(self):
+ """temporary function, probably to be renamed --- Gets a list of all
+ category/package-versions installed on the system."""
+ return self.dbapi.cpv_all()
+
+ def getallnodes(self):
+ """new behavior: these are all *unmasked* nodes. There may or may not be available
+ masked package for nodes in this nodes list."""
+ return self.dbapi.cp_all()
+
+ def exists_specific_cat(self,cpv,use_cache=1):
+ cpv=key_expand(cpv,mydb=self.dbapi,use_cache=use_cache)
+ a=catpkgsplit(cpv)
+ if not a:
+ return 0
+ mylist=listdir(self.root+VDB_PATH+"/"+a[0],EmptyOnError=1)
+ for x in mylist:
+ b=pkgsplit(x)
+ if not b:
+ self.dbapi.invalidentry(self.root+VDB_PATH+"/"+a[0]+"/"+x)
+ continue
+ if a[1]==b[0]:
+ return 1
+ return 0
+
+ def getebuildpath(self,fullpackage):
+ cat,package=fullpackage.split("/")
+ return self.root+VDB_PATH+"/"+fullpackage+"/"+package+".ebuild"
+
+ def getnode(self,mykey,use_cache=1):
+ mykey=key_expand(mykey,mydb=self.dbapi,use_cache=use_cache)
+ if not mykey:
+ return []
+ mysplit=mykey.split("/")
+ mydirlist=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+ returnme=[]
+ for x in mydirlist:
+ mypsplit=pkgsplit(x)
+ if not mypsplit:
+ self.dbapi.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+ continue
+ if mypsplit[0]==mysplit[1]:
+ appendme=[mysplit[0]+"/"+x,[mysplit[0],mypsplit[0],mypsplit[1],mypsplit[2]]]
+ returnme.append(appendme)
+ return returnme
+
+
+ def getslot(self,mycatpkg):
+ "Get a slot for a catpkg; assume it exists."
+ myslot = ""
+ try:
+ myslot=string.join(grabfile(self.root+VDB_PATH+"/"+mycatpkg+"/SLOT"))
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+ return myslot
+
+ def hasnode(self,mykey,use_cache):
+ """Does the particular node (cat/pkg key) exist?"""
+ mykey=key_expand(mykey,mydb=self.dbapi,use_cache=use_cache)
+ mysplit=mykey.split("/")
+ mydirlist=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+ for x in mydirlist:
+ mypsplit=pkgsplit(x)
+ if not mypsplit:
+ self.dbapi.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+ continue
+ if mypsplit[0]==mysplit[1]:
+ return 1
+ return 0
+
+ def populate(self):
+ self.populated=1
+
+# ----------------------------------------------------------------------------
+class eclass_cache:
+ """Maintains the cache information about eclasses used in ebuild."""
+ def __init__(self,porttree_root,settings):
+ self.porttree_root = porttree_root
+ self.settings = settings
+ self.depcachedir = self.settings.depcachedir[:]
+
+ self.dbmodule = self.settings.load_best_module("eclass_cache.dbmodule")
+
+ self.packages = {} # {"PV": {"eclass1": ["location", "_mtime_"]}}
+ self.eclasses = {} # {"Name": ["location","_mtime_"]}
+
+ # don't fool with porttree ordering unless you *ensure* that ebuild.sh's inherit
+ # ordering is *exactly* the same
+ self.porttrees=[self.porttree_root]
+ self.porttrees.extend(self.settings["PORTDIR_OVERLAY"].split())
+ #normalize the path now, so it's not required later.
+ self.porttrees = [os.path.normpath(x) for x in self.porttrees]
+ self.update_eclasses()
+
+ def close_caches(self):
+ for x in self.packages.keys():
+ for y in self.packages[x].keys():
+ try:
+ self.packages[x][y].sync()
+ self.packages[x][y].close()
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ writemsg("Exception when closing DB: %s: %s\n" % (Exception,e))
+ del self.packages[x][y]
+ del self.packages[x]
+
+ def flush_cache(self):
+ self.packages = {}
+ self.eclasses = {}
+ self.update_eclasses()
+
+ def update_eclasses(self):
+ self.eclasses = {}
+ for x in suffix_array(self.porttrees, "/eclass"):
+ if x and os.path.exists(x):
+ dirlist = listdir(x)
+ for y in dirlist:
+ if y[-len(".eclass"):]==".eclass":
+ try:
+ ys=y[:-len(".eclass")]
+ ymtime=os.stat(x+"/"+y)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except:
+ continue
+ self.eclasses[ys] = [x, ymtime]
+
+ def setup_package(self, location, cat, pkg):
+ if not self.packages.has_key(location):
+ self.packages[location] = {}
+
+ if not self.packages[location].has_key(cat):
+ try:
+ self.packages[location][cat] = self.dbmodule(self.depcachedir+"/"+location, cat+"-eclass", [], uid, portage_gid)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("\n!!! Failed to open the dbmodule for eclass caching.\n")
+ writemsg("!!! Generally these are permission problems. Caught exception follows:\n")
+ writemsg("!!! "+str(e)+"\n")
+ writemsg("!!! Dirname: "+str(self.depcachedir+"/"+location)+"\n")
+ writemsg("!!! Basename: "+str(cat+"-eclass")+"\n\n")
+ sys.exit(123)
+
+ def sync(self, location, cat, pkg):
+ if self.packages[location].has_key(cat):
+ self.packages[location][cat].sync()
+
+ def update_package(self, location, cat, pkg, eclass_list):
+ self.setup_package(location, cat, pkg)
+ if not eclass_list:
+ return 1
+
+ data = {}
+ for x in eclass_list:
+ if x not in self.eclasses:
+ writemsg("Eclass '%s' does not exist for '%s'\n" % (x, cat+"/"+pkg))
+ return 0
+ data[x] = [self.eclasses[x][0],self.eclasses[x][1]]
+
+ self.packages[location][cat][pkg] = data
+ self.sync(location,cat,pkg)
+ return 1
+
+ def is_current(self, location, cat, pkg, eclass_list):
+ self.setup_package(location, cat, pkg)
+
+ if not eclass_list:
+ return 1
+
+ if not (self.packages[location][cat].has_key(pkg) and self.packages[location][cat][pkg] and eclass_list):
+ return 0
+
+ myp = self.packages[location][cat][pkg]
+ for x in eclass_list:
+ if not (x in self.eclasses and x in myp and myp[x] == self.eclasses[x]):
+ return 0
+
+ return 1
+
+# ----------------------------------------------------------------------------
+
+auxdbkeys=[
+ 'DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
+ 'RESTRICT', 'HOMEPAGE', 'LICENSE', 'DESCRIPTION',
+ 'KEYWORDS', 'INHERITED', 'IUSE', 'CDEPEND',
+ 'PDEPEND', 'PROVIDE',
+ 'UNUSED_01', 'UNUSED_02', 'UNUSED_03', 'UNUSED_04',
+ 'UNUSED_05', 'UNUSED_06', 'UNUSED_07', 'UNUSED_08',
+ ]
+auxdbkeylen=len(auxdbkeys)
+
+def close_portdbapi_caches():
+ for i in portdbapi.portdbapi_instances:
+ i.close_caches()
+class portdbapi(dbapi):
+ """this tree will scan a portage directory located at root (passed to init)"""
+ portdbapi_instances = []
+
+ def __init__(self,porttree_root,mysettings=None):
+ portdbapi.portdbapi_instances.append(self)
+ self.lock_held = 0;
+
+ if mysettings:
+ self.mysettings = mysettings
+ else:
+ self.mysettings = config(clone=settings)
+
+ self.manifestVerifyLevel = None
+ self.manifestVerifier = None
+ self.manifestCache = {} # {location: [stat, md5]}
+ self.manifestMissingCache = []
+
+ if "gpg" in self.mysettings.features:
+ self.manifestVerifyLevel = portage_gpg.EXISTS
+ if "strict" in self.mysettings.features:
+ self.manifestVerifyLevel = portage_gpg.MARGINAL
+ self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", minimumTrust=self.manifestVerifyLevel)
+ elif "severe" in self.mysettings.features:
+ self.manifestVerifyLevel = portage_gpg.TRUSTED
+ self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", requireSignedRing=True, minimumTrust=self.manifestVerifyLevel)
+ else:
+ self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", minimumTrust=self.manifestVerifyLevel)
+
+ #self.root=settings["PORTDIR"]
+ self.porttree_root = porttree_root
+
+ self.depcachedir = self.mysettings.depcachedir[:]
+
+ self.tmpfs = self.mysettings["PORTAGE_TMPFS"]
+ if self.tmpfs and not os.path.exists(self.tmpfs):
+ self.tmpfs = None
+ if self.tmpfs and not os.access(self.tmpfs, os.W_OK):
+ self.tmpfs = None
+ if self.tmpfs and not os.access(self.tmpfs, os.R_OK):
+ self.tmpfs = None
+
+ self.eclassdb = eclass_cache(self.porttree_root, self.mysettings)
+
+ self.metadb = {}
+ self.metadbmodule = self.mysettings.load_best_module("portdbapi.metadbmodule")
+
+ self.auxdb = {}
+ self.auxdbmodule = self.mysettings.load_best_module("portdbapi.auxdbmodule")
+
+ #if the portdbapi is "frozen", then we assume that we can cache everything (that no updates to it are happening)
+ self.xcache={}
+ self.frozen=0
+
+ self.porttrees=[self.porttree_root]+self.mysettings["PORTDIR_OVERLAY"].split()
+
+ def close_caches(self):
+ for x in self.auxdb.keys():
+ for y in self.auxdb[x].keys():
+ self.auxdb[x][y].sync()
+ self.auxdb[x][y].close()
+ del self.auxdb[x][y]
+ del self.auxdb[x]
+ self.eclassdb.close_caches()
+
+ def flush_cache(self):
+ self.metadb = {}
+ self.auxdb = {}
+ self.eclassdb.flush_cache()
+
+ def finddigest(self,mycpv):
+ try:
+ mydig = self.findname2(mycpv)[0]
+ mydigs = string.split(mydig, "/")[:-1]
+ mydig = string.join(mydigs, "/")
+
+ mysplit = mycpv.split("/")
+ except SystemExit, e:
+ raise
+ except:
+ return ""
+ return mydig+"/files/digest-"+mysplit[-1]
+
+ def findname(self,mycpv):
+ return self.findname2(mycpv)[0]
+
+ def findname2(self,mycpv):
+ "returns file location for this particular package and in_overlay flag"
+ if not mycpv:
+ return "",0
+ mysplit=mycpv.split("/")
+
+ psplit=pkgsplit(mysplit[1])
+ ret=None
+ if psplit:
+ for x in self.porttrees:
+ # XXX Why are there errors here? XXX
+ try:
+ file=x+"/"+mysplit[0]+"/"+psplit[0]+"/"+mysplit[1]+".ebuild"
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print
+ print "!!! Problem with determining the name/location of an ebuild."
+ print "!!! Please report this on IRC and bugs if you are not causing it."
+ print "!!! mycpv: ",mycpv
+ print "!!! mysplit:",mysplit
+ print "!!! psplit: ",psplit
+ print "!!! error: ",e
+ print
+ sys.exit(17)
+
+ if os.access(file, os.R_OK):
+ # when found
+ ret=[file, x]
+ if ret:
+ return ret[0], ret[1]
+
+ # when not found
+ return None, 0
+
+ def aux_get(self,mycpv,mylist,strict=0,metacachedir=None,debug=0):
+ "stub code for returning auxilliary db information, such as SLOT, DEPEND, etc."
+ 'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
+ 'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or raise KeyError if error'
+ global auxdbkeys,auxdbkeylen
+
+ cat,pkg = string.split(mycpv, "/", 1)
+
+ if metacachedir:
+ if cat not in self.metadb:
+ self.metadb[cat] = self.metadbmodule(metacachedir,cat,auxdbkeys,uid,portage_gid)
+
+ myebuild, mylocation=self.findname2(mycpv)
+
+ if not myebuild:
+ writemsg("!!! aux_get(): ebuild path for '%(cpv)s' not specified:\n" % {"cpv":mycpv})
+ writemsg("!!! %s\n" % myebuild)
+ raise KeyError, "'%(cpv)s' at %(path)s" % {"cpv":mycpv,"path":myebuild}
+
+ myManifestPath = string.join(myebuild.split("/")[:-1],"/")+"/Manifest"
+ if "gpg" in self.mysettings.features:
+ try:
+ mys = portage_gpg.fileStats(myManifestPath)
+ if (myManifestPath in self.manifestCache) and \
+ (self.manifestCache[myManifestPath] == mys):
+ pass
+ elif self.manifestVerifier:
+ if not self.manifestVerifier.verify(myManifestPath):
+ # Verification failed the desired level.
+ raise portage_exception.UntrustedSignature, "Untrusted Manifest: %(manifest)s" % {"manifest":myManifestPath}
+
+ if ("severe" in self.mysettings.features) and \
+ (mys != portage_gpg.fileStats(myManifestPath)):
+ raise portage_exception.SecurityViolation, "Manifest changed: %(manifest)s" % {"manifest":myManifestPath}
+
+ except portage_exception.InvalidSignature, e:
+ if ("strict" in self.mysettings.features) or \
+ ("severe" in self.mysettings.features):
+ raise
+ writemsg("!!! INVALID MANIFEST SIGNATURE DETECTED: %(manifest)s\n" % {"manifest":myManifestPath})
+ except portage_exception.MissingSignature, e:
+ if ("severe" in self.mysettings.features):
+ raise
+ if ("strict" in self.mysettings.features):
+ if myManifestPath not in self.manifestMissingCache:
+ writemsg("!!! WARNING: Missing signature in: %(manifest)s\n" % {"manifest":myManifestPath})
+ self.manifestMissingCache.insert(0,myManifestPath)
+ except (OSError,portage_exception.FileNotFound), e:
+ if ("strict" in self.mysettings.features) or \
+ ("severe" in self.mysettings.features):
+ raise portage_exception.SecurityViolation, "Error in verification of signatures: %(errormsg)s" % {"errormsg":str(e)}
+ writemsg("!!! Manifest is missing or inaccessable: %(manifest)s\n" % {"manifest":myManifestPath})
+
+ if mylocation not in self.auxdb:
+ self.auxdb[mylocation] = {}
+
+ if not self.auxdb[mylocation].has_key(cat):
+ self.auxdb[mylocation][cat] = self.auxdbmodule(self.depcachedir+"/"+mylocation,cat,auxdbkeys,uid,portage_gid)
+
+ if os.access(myebuild, os.R_OK):
+ emtime=os.stat(myebuild)[stat.ST_MTIME]
+ else:
+ writemsg("!!! aux_get(): ebuild for '%(cpv)s' does not exist at:\n" % {"cpv":mycpv})
+ writemsg("!!! %s\n" % myebuild)
+ raise KeyError
+
+ try:
+ auxdb_is_valid = self.auxdb[mylocation][cat].has_key(pkg) and \
+ self.auxdb[mylocation][cat][pkg].has_key("_mtime_") and \
+ self.auxdb[mylocation][cat][pkg]["_mtime_"] == emtime
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ auxdb_is_valid = 0
+ writemsg("auxdb exception: [%(loc)s]: %(exception)s\n" % {"loc":mylocation+"::"+cat+"/"+pkg, "exception":str(e)})
+ if self.auxdb[mylocation][cat].has_key(pkg):
+ self.auxdb[mylocation][cat].del_key(pkg)
+ self.auxdb[mylocation][cat].sync()
+
+ writemsg("auxdb is valid: "+str(auxdb_is_valid)+" "+str(pkg)+"\n", 2)
+ doregen = not (auxdb_is_valid and self.eclassdb.is_current(mylocation,cat,pkg,self.auxdb[mylocation][cat][pkg]["INHERITED"].split()))
+
+ # when mylocation is not overlay directorys and metacachedir is set,
+ # we use cache files, which is usually on /usr/portage/metadata/cache/.
+ if doregen and mylocation==self.mysettings["PORTDIR"] and metacachedir and self.metadb[cat].has_key(pkg):
+ metadata=self.metadb[cat][pkg]
+ self.eclassdb.update_package(mylocation,cat,pkg,metadata["INHERITED"].split())
+ self.auxdb[mylocation][cat][pkg] = metadata
+ self.auxdb[mylocation][cat].sync()
+ elif doregen:
+
+ writemsg("doregen: %s %s\n" % (doregen,mycpv), 2)
+ writemsg("Generating cache entry(0) for: "+str(myebuild)+"\n",1)
+
+ if self.tmpfs:
+ mydbkey = self.tmpfs+"/aux_db_key_temp"
+ else:
+ mydbkey = self.depcachedir+"/aux_db_key_temp"
+
+ # XXX: Part of the gvisible hack/fix to prevent deadlock
+ # XXX: through doebuild. Need to isolate this somehow...
+ self.mysettings.reset()
+
+ if self.lock_held:
+ raise "Lock is already held by me?"
+ self.lock_held = 1
+ mylock = portage_locks.lockfile(mydbkey, wantnewlockfile=1)
+
+ if os.path.exists(mydbkey):
+ try:
+ os.unlink(mydbkey)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ writemsg("Uncaught handled exception: %(exception)s\n" % {"exception":str(e)})
+ raise
+
+ myret=doebuild(myebuild,"depend","/",self.mysettings,dbkey=mydbkey)
+ if myret:
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ #depend returned non-zero exit code...
+ writemsg(str(red("\naux_get():")+" (0) Error in "+mycpv+" ebuild. ("+str(myret)+")\n"
+ " Check for syntax error or corruption in the ebuild. (--debug)\n\n"))
+ raise KeyError
+
+ try:
+ mycent=open(mydbkey,"r")
+ os.unlink(mydbkey)
+ mylines=mycent.readlines()
+ mycent.close()
+ except SystemExit, e:
+ raise
+ except (IOError, OSError):
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ writemsg(str(red("\naux_get():")+" (1) Error in "+mycpv+" ebuild.\n"
+ " Check for syntax error or corruption in the ebuild. (--debug)\n\n"))
+ raise KeyError
+ except Exception, e:
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ writemsg("Uncaught handled exception: %(exception)s\n" % {"exception":str(e)})
+ raise
+
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+
+ mydata = {}
+ for x in range(0,len(mylines)):
+ if mylines[x][-1] == '\n':
+ mylines[x] = mylines[x][:-1]
+ mydata[auxdbkeys[x]] = mylines[x]
+ mydata["_mtime_"] = emtime
+
+ self.auxdb[mylocation][cat][pkg] = mydata
+ self.auxdb[mylocation][cat].sync()
+ if not self.eclassdb.update_package(mylocation, cat, pkg, mylines[auxdbkeys.index("INHERITED")].split()):
+ sys.exit(1)
+
+ #finally, we look at our internal cache entry and return the requested data.
+ mydata = self.auxdb[mylocation][cat][pkg]
+ returnme = []
+ for x in mylist:
+ if mydata.has_key(x):
+ returnme.append(mydata[x])
+ else:
+ returnme.append("")
+
+ return returnme
+
+ def getfetchlist(self,mypkg,useflags=None,mysettings=None,all=0):
+ if mysettings == None:
+ mysettings = self.mysettings
+ try:
+ myuris = self.aux_get(mypkg,["SRC_URI"])[0]
+ except (IOError,KeyError):
+ print red("getfetchlist():")+" aux_get() error reading "+mypkg+"; aborting."
+ sys.exit(1)
+
+ useflags = string.split(mysettings["USE"])
+
+ myurilist = portage_dep.paren_reduce(myuris)
+ myurilist = portage_dep.use_reduce(myurilist,uselist=useflags,matchall=all)
+ newuris = flatten(myurilist)
+
+ myfiles = []
+ for x in newuris:
+ mya = os.path.basename(x)
+ if not mya in myfiles:
+ myfiles.append(mya)
+ return [newuris, myfiles]
+
+ def getfetchsizes(self,mypkg,useflags=None,debug=0):
+ # returns a filename:size dictionnary of remaining downloads
+ mydigest=self.finddigest(mypkg)
+ mymd5s=digestParseFile(mydigest)
+ if not mymd5s:
+ if debug: print "[empty/missing/bad digest]: "+mypkg
+ return None
+ filesdict={}
+ if useflags == None:
+ myuris, myfiles = self.getfetchlist(mypkg,all=1)
+ else:
+ myuris, myfiles = self.getfetchlist(mypkg,useflags=useflags)
+ #XXX: maybe this should be improved: take partial downloads
+ # into account? check md5sums?
+ for myfile in myfiles:
+ if debug and myfile not in mymd5s.keys():
+ print "[bad digest]: missing",myfile,"for",mypkg
+ elif myfile in mymd5s.keys():
+ distfile=settings["DISTDIR"]+"/"+myfile
+ if not os.access(distfile, os.R_OK):
+ filesdict[myfile]=int(mymd5s[myfile]["size"])
+ return filesdict
+
+ def fetch_check(self, mypkg, useflags=None, mysettings=None, all=False):
+ if not useflags:
+ if mysettings:
+ useflags = mysettings["USE"].split()
+ myuri, myfiles = self.getfetchlist(mypkg, useflags=useflags, mysettings=mysettings, all=all)
+ mydigest = self.finddigest(mypkg)
+ mysums = digestParseFile(mydigest)
+
+ failures = {}
+ for x in myfiles:
+ if not mysums or x not in mysums:
+ ok = False
+ reason = "digest missing"
+ else:
+ ok,reason = portage_checksum.verify_all(self.mysettings["DISTDIR"]+"/"+x, mysums[x])
+ if not ok:
+ failures[x] = reason
+ if failures:
+ return False
+ return True
+
+ def getsize(self,mypkg,useflags=None,debug=0):
+ # returns the total size of remaining downloads
+ #
+ # we use getfetchsizes() now, so this function would be obsoleted
+ #
+ filesdict=self.getfetchsizes(mypkg,useflags=useflags,debug=debug)
+ if filesdict==None:
+ return "[empty/missing/bad digest]"
+ mysize=0
+ for myfile in filesdict.keys():
+ mysum+=filesdict[myfile]
+ return mysum
+
+ def cpv_exists(self,mykey):
+ "Tells us whether an actual ebuild exists on disk (no masking)"
+ cps2=mykey.split("/")
+ cps=catpkgsplit(mykey,silent=0)
+ if not cps:
+ #invalid cat/pkg-v
+ return 0
+ if self.findname(cps[0]+"/"+cps2[1]):
+ return 1
+ else:
+ return 0
+
+ def cp_all(self):
+ "returns a list of all keys in our tree"
+ d={}
+ for x in self.mysettings.categories:
+ for oroot in self.porttrees:
+ for y in listdir(oroot+"/"+x,EmptyOnError=1,ignorecvs=1):
+ mykey=x+"/"+y
+ d[x+"/"+y] = None
+ l = d.keys()
+ l.sort()
+ return l
+
+ def p_list(self,mycp):
+ d={}
+ for oroot in self.porttrees:
+ for x in listdir(oroot+"/"+mycp,EmptyOnError=1,ignorecvs=1):
+ if x[-7:]==".ebuild":
+ d[x[:-7]] = None
+ return d.keys()
+
+ def cp_list(self,mycp,use_cache=1):
+ mysplit=mycp.split("/")
+ d={}
+ for oroot in self.porttrees:
+ for x in listdir(oroot+"/"+mycp,EmptyOnError=1,ignorecvs=1):
+ if x[-7:]==".ebuild":
+ d[mysplit[0]+"/"+x[:-7]] = None
+ return d.keys()
+
+ def freeze(self):
+ for x in ["list-visible","bestmatch-visible","match-visible","match-all"]:
+ self.xcache[x]={}
+ self.frozen=1
+
+ def melt(self):
+ self.xcache={}
+ self.frozen=0
+
+ def xmatch(self,level,origdep,mydep=None,mykey=None,mylist=None):
+ "caching match function; very trick stuff"
+ #if no updates are being made to the tree, we can consult our xcache...
+ if self.frozen:
+ try:
+ return self.xcache[level][origdep]
+ except KeyError:
+ pass
+
+ if not mydep:
+ #this stuff only runs on first call of xmatch()
+ #create mydep, mykey from origdep
+ mydep=dep_expand(origdep,mydb=self)
+ mykey=dep_getkey(mydep)
+
+ if level=="list-visible":
+ #a list of all visible packages, not called directly (just by xmatch())
+ #myval=self.visible(self.cp_list(mykey))
+ myval=self.gvisible(self.visible(self.cp_list(mykey)))
+ elif level=="bestmatch-visible":
+ #dep match -- best match of all visible packages
+ myval=best(self.xmatch("match-visible",None,mydep=mydep,mykey=mykey))
+ #get all visible matches (from xmatch()), then choose the best one
+ elif level=="bestmatch-list":
+ #dep match -- find best match but restrict search to sublist
+ myval=best(match_from_list(mydep,mylist))
+ #no point is calling xmatch again since we're not caching list deps
+ elif level=="match-list":
+ #dep match -- find all matches but restrict search to sublist (used in 2nd half of visible())
+ myval=match_from_list(mydep,mylist)
+ elif level=="match-visible":
+ #dep match -- find all visible matches
+ myval=match_from_list(mydep,self.xmatch("list-visible",None,mydep=mydep,mykey=mykey))
+ #get all visible packages, then get the matching ones
+ elif level=="match-all":
+ #match *all* visible *and* masked packages
+ myval=match_from_list(mydep,self.cp_list(mykey))
+ else:
+ print "ERROR: xmatch doesn't handle",level,"query!"
+ raise KeyError
+ if self.frozen and (level not in ["match-list","bestmatch-list"]):
+ self.xcache[level][mydep]=myval
+ return myval
+
+ def match(self,mydep,use_cache=1):
+ return self.xmatch("match-visible",mydep)
+
+ def visible(self,mylist):
+ """two functions in one. Accepts a list of cpv values and uses the package.mask *and*
+ packages file to remove invisible entries, returning remaining items. This function assumes
+ that all entries in mylist have the same category and package name."""
+ if (mylist==None) or (len(mylist)==0):
+ return []
+ newlist=mylist[:]
+ #first, we mask out packages in the package.mask file
+ mykey=newlist[0]
+ cpv=catpkgsplit(mykey)
+ if not cpv:
+ #invalid cat/pkg-v
+ print "visible(): invalid cat/pkg-v:",mykey
+ return []
+ mycp=cpv[0]+"/"+cpv[1]
+ maskdict=self.mysettings.pmaskdict
+ unmaskdict=self.mysettings.punmaskdict
+ if maskdict.has_key(mycp):
+ for x in maskdict[mycp]:
+ mymatches=self.xmatch("match-all",x)
+ if mymatches==None:
+ #error in package.mask file; print warning and continue:
+ print "visible(): package.mask entry \""+x+"\" is invalid, ignoring..."
+ continue
+ for y in mymatches:
+ unmask=0
+ if unmaskdict.has_key(mycp):
+ for z in unmaskdict[mycp]:
+ mymatches_unmask=self.xmatch("match-all",z)
+ if y in mymatches_unmask:
+ unmask=1
+ break
+ if unmask==0:
+ try:
+ newlist.remove(y)
+ except ValueError:
+ pass
+
+ revmaskdict=self.mysettings.prevmaskdict
+ if revmaskdict.has_key(mycp):
+ for x in revmaskdict[mycp]:
+ #important: only match against the still-unmasked entries...
+ #notice how we pass "newlist" to the xmatch() call below....
+ #Without this, ~ deps in the packages files are broken.
+ mymatches=self.xmatch("match-list",x,mylist=newlist)
+ if mymatches==None:
+ #error in packages file; print warning and continue:
+ print "emerge: visible(): profile packages entry \""+x+"\" is invalid, ignoring..."
+ continue
+ pos=0
+ while pos<len(newlist):
+ if newlist[pos] not in mymatches:
+ del newlist[pos]
+ else:
+ pos += 1
+ return newlist
+
+ def gvisible(self,mylist):
+ "strip out group-masked (not in current group) entries"
+ global groups
+ if mylist==None:
+ return []
+ newlist=[]
+
+ pkgdict = self.mysettings.pkeywordsdict
+ for mycpv in mylist:
+ #we need to update this next line when we have fully integrated the new db api
+ auxerr=0
+ try:
+ myaux=db["/"]["porttree"].dbapi.aux_get(mycpv, ["KEYWORDS"])
+ except (KeyError,IOError,TypeError):
+ continue
+ if not myaux[0]:
+ # KEYWORDS=""
+ #print "!!! No KEYWORDS for "+str(mycpv)+" -- Untested Status"
+ continue
+ mygroups=myaux[0].split()
+ pgroups=groups[:]
+ match=0
+ cp = dep_getkey(mycpv)
+ if pkgdict.has_key(cp):
+ matches = match_to_list(mycpv, pkgdict[cp].keys())
+ for atom in matches:
+ pgroups.extend(pkgdict[cp][atom])
+ hasstable = False
+ hastesting = False
+ for gp in mygroups:
+ if gp=="*":
+ writemsg("--- WARNING: Package '%s' uses '*' keyword.\n" % mycpv)
+ match=1
+ break
+ elif "-"+gp in pgroups:
+ match=0
+ break
+ elif gp in pgroups:
+ match=1
+ break
+ elif gp[0] == "~":
+ hastesting = True
+ elif gp[0] != "-":
+ hasstable = True
+ if not match and ((hastesting and "~*" in pgroups) or (hasstable and "*" in pgroups)):
+ match=1
+ if match:
+ newlist.append(mycpv)
+ return newlist
+
+class binarytree(packagetree):
+ "this tree scans for a list of all packages available in PKGDIR"
+ def __init__(self,root,pkgdir,virtual=None,clone=None):
+
+ if clone:
+ # XXX This isn't cloning. It's an instance of the same thing.
+ self.root=clone.root
+ self.pkgdir=clone.pkgdir
+ self.dbapi=clone.dbapi
+ self.populated=clone.populated
+ self.tree=clone.tree
+ self.remotepkgs=clone.remotepkgs
+ self.invalids=clone.invalids
+ else:
+ self.root=root
+ #self.pkgdir=settings["PKGDIR"]
+ self.pkgdir=pkgdir
+ self.dbapi=bindbapi(self)
+ self.populated=0
+ self.tree={}
+ self.remotepkgs={}
+ self.invalids=[]
+
+ def move_ent(self,mylist):
+ if not self.populated:
+ self.populate()
+ origcp=mylist[1]
+ newcp=mylist[2]
+ mynewcat=newcp.split("/")[0]
+ origmatches=self.dbapi.cp_list(origcp)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+
+ mycpsplit=catpkgsplit(mycpv)
+ mynewcpv=newcp+"-"+mycpsplit[2]
+ if mycpsplit[3]!="r0":
+ mynewcpv += "-"+mycpsplit[3]
+ myoldpkg=mycpv.split("/")[1]
+ mynewpkg=mynewcpv.split("/")[1]
+
+ if (mynewpkg != myoldpkg) and os.path.exists(self.getname(mynewcpv)):
+ writemsg("!!! Cannot update binary: Destination exists.\n")
+ writemsg("!!! "+mycpv+" -> "+mynewcpv+"\n")
+ continue
+
+ tbz2path=self.getname(mycpv)
+ if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+ writemsg("!!! Cannot update readonly binary: "+mycpv+"\n")
+ continue
+
+ #print ">>> Updating data in:",mycpv
+ sys.stdout.write("%")
+ sys.stdout.flush()
+ mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2"
+ mytbz2=xpak.tbz2(tbz2path)
+ mytbz2.decompose(mytmpdir, cleanup=1)
+
+ fixdbentries(origcp, newcp, mytmpdir)
+
+ catfile=open(mytmpdir+"/CATEGORY", "w")
+ catfile.write(mynewcat+"\n")
+ catfile.close()
+ try:
+ os.rename(mytmpdir+"/"+string.split(mycpv,"/")[1]+".ebuild", mytmpdir+"/"+string.split(mynewcpv, "/")[1]+".ebuild")
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+ mytbz2.recompose(mytmpdir, cleanup=1)
+
+ self.dbapi.cpv_remove(mycpv)
+ if (mynewpkg != myoldpkg):
+ os.rename(tbz2path,self.getname(mynewcpv))
+ self.dbapi.cpv_inject(mynewcpv)
+ return 1
+
+ def move_slot_ent(self,mylist,mytmpdir):
+ #mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2"
+ mytmpdir=mytmpdir+"/tbz2"
+ if not self.populated:
+ self.populate()
+ pkg=mylist[1]
+ origslot=mylist[2]
+ newslot=mylist[3]
+ origmatches=self.dbapi.match(pkg)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+ mycpsplit=catpkgsplit(mycpv)
+ myoldpkg=mycpv.split("/")[1]
+ tbz2path=self.getname(mycpv)
+ if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+ writemsg("!!! Cannot update readonly binary: "+mycpv+"\n")
+ continue
+
+ #print ">>> Updating data in:",mycpv
+ mytbz2=xpak.tbz2(tbz2path)
+ mytbz2.decompose(mytmpdir, cleanup=1)
+
+ slot=grabfile(mytmpdir+"/SLOT");
+ if (not slot):
+ continue
+
+ if (slot[0]!=origslot):
+ continue
+
+ sys.stdout.write("S")
+ sys.stdout.flush()
+
+ slotfile=open(mytmpdir+"/SLOT", "w")
+ slotfile.write(newslot+"\n")
+ slotfile.close()
+ mytbz2.recompose(mytmpdir, cleanup=1)
+ return 1
+
+ def update_ents(self,mybiglist,mytmpdir):
+ #XXX mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2"
+ if not self.populated:
+ self.populate()
+ for mycpv in self.dbapi.cp_all():
+ tbz2path=self.getname(mycpv)
+ if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+ writemsg("!!! Cannot update readonly binary: "+mycpv+"\n")
+ continue
+ #print ">>> Updating binary data:",mycpv
+ writemsg("*")
+ mytbz2=xpak.tbz2(tbz2path)
+ mytbz2.decompose(mytmpdir,cleanup=1)
+ for mylist in mybiglist:
+ mylist=string.split(mylist)
+ if mylist[0] != "move":
+ continue
+ fixdbentries(mylist[1], mylist[2], mytmpdir)
+ mytbz2.recompose(mytmpdir,cleanup=1)
+ return 1
+
+ def populate(self, getbinpkgs=0,getbinpkgsonly=0):
+ "populates the binarytree"
+ if (not os.path.isdir(self.pkgdir) and not getbinpkgs):
+ return 0
+ if (not os.path.isdir(self.pkgdir+"/All") and not getbinpkgs):
+ return 0
+
+ if (not getbinpkgsonly) and os.path.exists(self.pkgdir+"/All"):
+ for mypkg in listdir(self.pkgdir+"/All"):
+ if mypkg[-5:]!=".tbz2":
+ continue
+ mytbz2=xpak.tbz2(self.pkgdir+"/All/"+mypkg)
+ mycat=mytbz2.getfile("CATEGORY")
+ if not mycat:
+ #old-style or corrupt package
+ writemsg("!!! Invalid binary package: "+mypkg+"\n")
+ self.invalids.append(mypkg)
+ continue
+ mycat=string.strip(mycat)
+ fullpkg=mycat+"/"+mypkg[:-5]
+ mykey=dep_getkey(fullpkg)
+ try:
+ # invalid tbz2's can hurt things.
+ self.dbapi.cpv_inject(fullpkg)
+ except SystemExit, e:
+ raise
+ except:
+ continue
+
+ if getbinpkgs and not settings["PORTAGE_BINHOST"]:
+ writemsg(red("!!! PORTAGE_BINHOST unset, but use is requested.\n"))
+
+ if getbinpkgs and settings["PORTAGE_BINHOST"] and not self.remotepkgs:
+ try:
+ chunk_size = long(settings["PORTAGE_BINHOST_CHUNKSIZE"])
+ if chunk_size < 8:
+ chunk_size = 8
+ except SystemExit, e:
+ raise
+ except:
+ chunk_size = 3000
+
+ writemsg(green("Fetching binary packages info...\n"))
+ self.remotepkgs = getbinpkg.dir_get_metadata(settings["PORTAGE_BINHOST"], chunk_size=chunk_size)
+ writemsg(green(" -- DONE!\n\n"))
+
+ for mypkg in self.remotepkgs.keys():
+ if not self.remotepkgs[mypkg].has_key("CATEGORY"):
+ #old-style or corrupt package
+ writemsg("!!! Invalid remote binary package: "+mypkg+"\n")
+ del self.remotepkgs[mypkg]
+ continue
+ mycat=string.strip(self.remotepkgs[mypkg]["CATEGORY"])
+ fullpkg=mycat+"/"+mypkg[:-5]
+ mykey=dep_getkey(fullpkg)
+ try:
+ # invalid tbz2's can hurt things.
+ #print "cpv_inject("+str(fullpkg)+")"
+ self.dbapi.cpv_inject(fullpkg)
+ #print " -- Injected"
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("!!! Failed to inject remote binary package:"+str(fullpkg)+"\n")
+ del self.remotepkgs[mypkg]
+ continue
+ self.populated=1
+
+ def inject(self,cpv):
+ return self.dbapi.cpv_inject(cpv)
+
+ def exists_specific(self,cpv):
+ if not self.populated:
+ self.populate()
+ return self.dbapi.match(dep_expand("="+cpv,mydb=self.dbapi))
+
+ def dep_bestmatch(self,mydep):
+ "compatibility method -- all matches, not just visible ones"
+ if not self.populated:
+ self.populate()
+ writemsg("\n\n", 1)
+ writemsg("mydep: %s\n" % mydep, 1)
+ mydep=dep_expand(mydep,mydb=self.dbapi)
+ writemsg("mydep: %s\n" % mydep, 1)
+ mykey=dep_getkey(mydep)
+ writemsg("mykey: %s\n" % mykey, 1)
+ mymatch=best(match_from_list(mydep,self.dbapi.cp_list(mykey)))
+ writemsg("mymatch: %s\n" % mymatch, 1)
+ if mymatch==None:
+ return ""
+ return mymatch
+
+ def getname(self,pkgname):
+ "returns file location for this particular package"
+ mysplit=string.split(pkgname,"/")
+ if len(mysplit)==1:
+ return self.pkgdir+"/All/"+self.resolve_specific(pkgname)+".tbz2"
+ else:
+ return self.pkgdir+"/All/"+mysplit[1]+".tbz2"
+
+ def isremote(self,pkgname):
+ "Returns true if the package is kept remotely."
+ mysplit=string.split(pkgname,"/")
+ remote = (not os.path.exists(self.getname(pkgname))) and self.remotepkgs.has_key(mysplit[1]+".tbz2")
+ return remote
+
+ def get_use(self,pkgname):
+ mysplit=string.split(pkgname,"/")
+ if self.isremote(pkgname):
+ return string.split(self.remotepkgs[mysplit[1]+".tbz2"]["USE"][:])
+ tbz2=xpak.tbz2(self.getname(pkgname))
+ return string.split(tbz2.getfile("USE"))
+
+ def gettbz2(self,pkgname):
+ "fetches the package from a remote site, if necessary."
+ print "Fetching '"+str(pkgname)+"'"
+ mysplit = string.split(pkgname,"/")
+ tbz2name = mysplit[1]+".tbz2"
+ if not self.isremote(pkgname):
+ if (tbz2name not in self.invalids):
+ return
+ else:
+ writemsg("Resuming download of this tbz2, but it is possible that it is corrupt.\n")
+ mydest = self.pkgdir+"/All/"
+ try:
+ os.makedirs(mydest, 0775)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ getbinpkg.file_get(settings["PORTAGE_BINHOST"]+"/"+tbz2name, mydest, fcmd=settings["RESUMECOMMAND"])
+ return
+
+ def getslot(self,mycatpkg):
+ "Get a slot for a catpkg; assume it exists."
+ myslot = ""
+ try:
+ myslot=self.dbapi.aux_get(mycatpkg,["SLOT"])[0]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+ return myslot
+
+class dblink:
+ "this class provides an interface to the standard text package database"
+ def __init__(self,cat,pkg,myroot,mysettings):
+ "create a dblink object for cat/pkg. This dblink entry may or may not exist"
+ self.cat = cat
+ self.pkg = pkg
+ self.mycpv = self.cat+"/"+self.pkg
+ self.mysplit = pkgsplit(self.mycpv)
+
+ self.dbroot = os.path.normpath(myroot+VDB_PATH)
+ self.dbcatdir = self.dbroot+"/"+cat
+ self.dbpkgdir = self.dbcatdir+"/"+pkg
+ self.dbtmpdir = self.dbcatdir+"/-MERGING-"+pkg
+ self.dbdir = self.dbpkgdir
+
+ self.lock_pkg = None
+ self.lock_tmp = None
+ self.lock_num = 0 # Count of the held locks on the db.
+
+ self.settings = mysettings
+ if self.settings==1:
+ raise ValueError
+
+ self.myroot=myroot
+ self.updateprotect()
+ self.contentscache=[]
+
+ def lockdb(self):
+ if self.lock_num == 0:
+ self.lock_pkg = portage_locks.lockdir(self.dbpkgdir)
+ self.lock_tmp = portage_locks.lockdir(self.dbtmpdir)
+ self.lock_num += 1
+
+ def unlockdb(self):
+ self.lock_num -= 1
+ if self.lock_num == 0:
+ portage_locks.unlockdir(self.lock_tmp)
+ portage_locks.unlockdir(self.lock_pkg)
+
+ def getpath(self):
+ "return path to location of db information (for >>> informational display)"
+ return self.dbdir
+
+ def exists(self):
+ "does the db entry exist? boolean."
+ return os.path.exists(self.dbdir)
+
+ def create(self):
+ "create the skeleton db directory structure. No contents, virtuals, provides or anything. Also will create /var/db/pkg if necessary."
+ # XXXXX Delete this eventually
+ raise Exception, "This is bad. Don't use it."
+ if not os.path.exists(self.dbdir):
+ os.makedirs(self.dbdir)
+
+ def delete(self):
+ "erase this db entry completely"
+ if not os.path.exists(self.dbdir):
+ return
+ try:
+ for x in listdir(self.dbdir):
+ os.unlink(self.dbdir+"/"+x)
+ os.rmdir(self.dbdir)
+ except OSError, e:
+ print "!!! Unable to remove db entry for this package."
+ print "!!! It is possible that a directory is in this one. Portage will still"
+ print "!!! register this package as installed as long as this directory exists."
+ print "!!! You may delete this directory with 'rm -Rf "+self.dbdir+"'"
+ print "!!! "+str(e)
+ print
+ sys.exit(1)
+
+ def clearcontents(self):
+ if os.path.exists(self.dbdir+"/CONTENTS"):
+ os.unlink(self.dbdir+"/CONTENTS")
+
+ def getcontents(self):
+ if not os.path.exists(self.dbdir+"/CONTENTS"):
+ return None
+ if self.contentscache != []:
+ return self.contentscache
+ pkgfiles={}
+ myc=open(self.dbdir+"/CONTENTS","r")
+ mylines=myc.readlines()
+ myc.close()
+ pos=1
+ for line in mylines:
+ mydat = string.split(line)
+ # we do this so we can remove from non-root filesystems
+ # (use the ROOT var to allow maintenance on other partitions)
+ try:
+ mydat[1]=os.path.normpath(root+mydat[1][1:])
+ if mydat[0]=="obj":
+ #format: type, mtime, md5sum
+ pkgfiles[string.join(mydat[1:-2]," ")]=[mydat[0], mydat[-1], mydat[-2]]
+ elif mydat[0]=="dir":
+ #format: type
+ pkgfiles[string.join(mydat[1:])]=[mydat[0] ]
+ elif mydat[0]=="sym":
+ #format: type, mtime, dest
+ x=len(mydat)-1
+ if (x >= 13) and (mydat[-1][-1]==')'): # Old/Broken symlink entry
+ mydat = mydat[:-10]+[mydat[-10:][stat.ST_MTIME][:-1]]
+ writemsg("FIXED SYMLINK LINE: %s\n" % mydat, 1)
+ x=len(mydat)-1
+ splitter=-1
+ while(x>=0):
+ if mydat[x]=="->":
+ splitter=x
+ break
+ x=x-1
+ if splitter==-1:
+ return None
+ pkgfiles[string.join(mydat[1:splitter]," ")]=[mydat[0], mydat[-1], string.join(mydat[(splitter+1):-1]," ")]
+ elif mydat[0]=="dev":
+ #format: type
+ pkgfiles[string.join(mydat[1:]," ")]=[mydat[0] ]
+ elif mydat[0]=="fif":
+ #format: type
+ pkgfiles[string.join(mydat[1:]," ")]=[mydat[0]]
+ else:
+ return None
+ except (KeyError,IndexError):
+ print "portage: CONTENTS line",pos,"corrupt!"
+ pos += 1
+ self.contentscache=pkgfiles
+ return pkgfiles
+
+ def updateprotect(self):
+ #do some config file management prep
+ self.protect=[]
+ for x in string.split(self.settings["CONFIG_PROTECT"]):
+ ppath=normalize_path(self.myroot+x)+"/"
+ if os.path.isdir(ppath):
+ self.protect.append(ppath)
+
+ self.protectmask=[]
+ for x in string.split(self.settings["CONFIG_PROTECT_MASK"]):
+ ppath=normalize_path(self.myroot+x)+"/"
+ if os.path.isdir(ppath):
+ self.protectmask.append(ppath)
+ #if it doesn't exist, silently skip it
+
+ def isprotected(self,obj):
+ """Checks if obj is in the current protect/mask directories. Returns
+ 0 on unprotected/masked, and 1 on protected."""
+ masked=0
+ protected=0
+ for ppath in self.protect:
+ if (len(ppath) > masked) and (obj[0:len(ppath)]==ppath):
+ protected=len(ppath)
+ #config file management
+ for pmpath in self.protectmask:
+ if (len(pmpath) >= protected) and (obj[0:len(pmpath)]==pmpath):
+ #skip, it's in the mask
+ masked=len(pmpath)
+ return (protected > masked)
+
+ def unmerge(self,pkgfiles=None,trimworld=1,cleanup=0):
+ global dircache
+ dircache={}
+
+ self.lockdb()
+
+ self.settings.load_infodir(self.dbdir)
+
+ if not pkgfiles:
+ print "No package files given... Grabbing a set."
+ pkgfiles=self.getcontents()
+
+ # Now, don't assume that the name of the ebuild is the same as the
+ # name of the dir; the package may have been moved.
+ myebuildpath=None
+
+ # We should use the environement file if possible,
+ # as it has all sourced files already included.
+ # XXX: Need to ensure it doesn't overwrite any important vars though.
+ if os.access(self.dbdir+"/environment.bz2", os.R_OK):
+ spawn("bzip2 -d "+self.dbdir+"/environment.bz2",self.settings,free=1)
+
+ if not myebuildpath:
+ mystuff=listdir(self.dbdir,EmptyOnError=1)
+ for x in mystuff:
+ if x[-7:]==".ebuild":
+ myebuildpath=self.dbdir+"/"+x
+ break
+
+ #do prerm script
+ if myebuildpath and os.path.exists(myebuildpath):
+ a=doebuild(myebuildpath,"prerm",self.myroot,self.settings,cleanup=cleanup,use_cache=0,tree="vartree")
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED prerm: "+str(a)+"\n")
+ sys.exit(123)
+
+ if pkgfiles:
+ mykeys=pkgfiles.keys()
+ mykeys.sort()
+ mykeys.reverse()
+
+ self.updateprotect()
+
+ #process symlinks second-to-last, directories last.
+ mydirs=[]
+ mysyms=[]
+ modprotect="/lib/modules/"
+ for obj in mykeys:
+ obj=os.path.normpath(obj)
+ if obj[:2]=="//":
+ obj=obj[1:]
+ if not os.path.exists(obj):
+ if not os.path.islink(obj):
+ #we skip this if we're dealing with a symlink
+ #because os.path.exists() will operate on the
+ #link target rather than the link itself.
+ print "--- !found "+str(pkgfiles[obj][0]), obj
+ continue
+ # next line includes a tweak to protect modules from being unmerged,
+ # but we don't protect modules from being overwritten if they are
+ # upgraded. We effectively only want one half of the config protection
+ # functionality for /lib/modules. For portage-ng both capabilities
+ # should be able to be independently specified.
+ if self.isprotected(obj) or ((len(obj) > len(modprotect)) and (obj[0:len(modprotect)]==modprotect)):
+ print "--- cfgpro "+str(pkgfiles[obj][0]), obj
+ continue
+
+ lstatobj=os.lstat(obj)
+ lmtime=str(lstatobj[stat.ST_MTIME])
+ if (pkgfiles[obj][0] not in ("dir","fif","dev","sym")) and (lmtime != pkgfiles[obj][1]):
+ print "--- !mtime", pkgfiles[obj][0], obj
+ continue
+
+ if pkgfiles[obj][0]=="dir":
+ if not os.path.isdir(obj):
+ print "--- !dir ","dir", obj
+ continue
+ mydirs.append(obj)
+ elif pkgfiles[obj][0]=="sym":
+ if not os.path.islink(obj):
+ print "--- !sym ","sym", obj
+ continue
+ mysyms.append(obj)
+ elif pkgfiles[obj][0]=="obj":
+ if not os.path.isfile(obj):
+ print "--- !obj ","obj", obj
+ continue
+ mymd5=portage_checksum.perform_md5(obj, calc_prelink=1)
+
+ # string.lower is needed because db entries used to be in upper-case. The
+ # string.lower allows for backwards compatibility.
+ if mymd5 != string.lower(pkgfiles[obj][2]):
+ print "--- !md5 ","obj", obj
+ continue
+ try:
+ os.unlink(obj)
+ except (OSError,IOError),e:
+ pass
+ print "<<< ","obj",obj
+ elif pkgfiles[obj][0]=="fif":
+ if not stat.S_ISFIFO(lstatobj[stat.ST_MODE]):
+ print "--- !fif ","fif", obj
+ continue
+ try:
+ os.unlink(obj)
+ except (OSError,IOError),e:
+ pass
+ print "<<< ","fif",obj
+ elif pkgfiles[obj][0]=="dev":
+ print "--- ","dev",obj
+
+ #Now, we need to remove symlinks and directories. We'll repeatedly
+ #remove dead symlinks, then directories until we stop making progress.
+ #This is how we'll clean up directories containing symlinks pointing to
+ #directories that are now empty. These cases will require several
+ #iterations through our two-stage symlink/directory cleaning loop.
+
+ #main symlink and directory removal loop:
+
+ #progress -- are we making progress? Initialized to 1 so loop will start
+ progress=1
+ while progress:
+ #let's see if we're able to make progress this iteration...
+ progress=0
+
+ #step 1: remove all the dead symlinks we can...
+
+ pos = 0
+ while pos<len(mysyms):
+ obj=mysyms[pos]
+ if os.path.exists(obj):
+ pos += 1
+ else:
+ #we have a dead symlink; remove it from our list, then from existence
+ del mysyms[pos]
+ #we've made progress!
+ progress = 1
+ try:
+ os.unlink(obj)
+ print "<<< ","sym",obj
+ except (OSError,IOError),e:
+ print "!!! ","sym",obj
+ #immutable?
+ pass
+
+ #step 2: remove all the empty directories we can...
+
+ pos = 0
+ while pos<len(mydirs):
+ obj=mydirs[pos]
+ objld=listdir(obj)
+
+ if objld == None:
+ print "mydirs["+str(pos)+"]",mydirs[pos]
+ print "obj",obj
+ print "objld",objld
+ # the directory doesn't exist yet, continue
+ pos += 1
+ continue
+
+ if len(objld)>0:
+ #we won't remove this directory (yet), continue
+ pos += 1
+ continue
+ elif (objld != None):
+ #zappo time
+ del mydirs[pos]
+ #we've made progress!
+ progress = 1
+ try:
+ os.rmdir(obj)
+ print "<<< ","dir",obj
+ except (OSError,IOError),e:
+ #immutable?
+ pass
+ #else:
+ # print "--- !empty","dir", obj
+ # continue
+
+ #step 3: if we've made progress, we'll give this another go...
+
+ #step 4: otherwise, we'll print out the remaining stuff that we didn't unmerge (and rightly so!)
+
+ #directories that aren't empty:
+ for x in mydirs:
+ print "--- !empty dir", x
+
+ #symlinks whose target still exists:
+ for x in mysyms:
+ print "--- !targe sym", x
+
+ #step 5: well, removal of package objects is complete, now for package *meta*-objects....
+
+ #remove self from vartree database so that our own virtual gets zapped if we're the last node
+ db[self.myroot]["vartree"].zap(self.mycpv)
+
+ # New code to remove stuff from the world and virtuals files when unmerged.
+ if trimworld:
+ worldlist=grabfile(self.myroot+WORLD_FILE)
+ mykey=cpv_getkey(self.mycpv)
+ newworldlist=[]
+ for x in worldlist:
+ if dep_getkey(x)==mykey:
+ matches=db[self.myroot]["vartree"].dbapi.match(x,use_cache=0)
+ if not matches:
+ #zap our world entry
+ pass
+ elif (len(matches)==1) and (matches[0]==self.mycpv):
+ #zap our world entry
+ pass
+ else:
+ #others are around; keep it.
+ newworldlist.append(x)
+ else:
+ #this doesn't match the package we're unmerging; keep it.
+ newworldlist.append(x)
+
+ # if the base dir doesn't exist, create it.
+ # (spanky noticed bug)
+ # XXX: dumb question, but abstracting the root uid might be wise/useful for
+ # 2nd pkg manager installation setups.
+ if not os.path.exists(os.path.dirname(self.myroot+WORLD_FILE)):
+ pdir = os.path.dirname(self.myroot + WORLD_FILE)
+ os.makedirs(pdir, mode=0755)
+ os.chown(pdir, 0, portage_gid)
+ os.chmod(pdir, 02770)
+
+ myworld=open(self.myroot+WORLD_FILE,"w")
+ for x in newworldlist:
+ myworld.write(x+"\n")
+ myworld.close()
+
+ #do original postrm
+ if myebuildpath and os.path.exists(myebuildpath):
+ # XXX: This should be the old config, not the current one.
+ # XXX: Use vardbapi to load up env vars.
+ a=doebuild(myebuildpath,"postrm",self.myroot,self.settings,use_cache=0,tree="vartree")
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED postrm: "+str(a)+"\n")
+ sys.exit(123)
+
+ self.unlockdb()
+
+ def isowner(self,filename,destroot):
+ """ check if filename is a new file or belongs to this package
+ (for this or a previous version)"""
+ destfile = os.path.normpath(destroot+"/"+filename)
+ if not os.path.exists(destfile):
+ return True
+ if self.getcontents() and filename in self.getcontents().keys():
+ return True
+
+ return False
+
+ def treewalk(self,srcroot,destroot,inforoot,myebuild,cleanup=0):
+ global db
+ # srcroot = ${D};
+ # destroot = where to merge, ie. ${ROOT},
+ # inforoot = root of db entry,
+ # secondhand = list of symlinks that have been skipped due to
+ # their target not existing (will merge later),
+
+ if not os.path.exists(self.dbcatdir):
+ os.makedirs(self.dbcatdir)
+
+ # This blocks until we can get the dirs to ourselves.
+ self.lockdb()
+
+ otherversions=[]
+ for v in db[self.myroot]["vartree"].dbapi.cp_list(self.mysplit[0]):
+ otherversions.append(v.split("/")[1])
+
+ # check for package collisions
+ if "collision-protect" in features:
+ myfilelist = listdir(srcroot, recursive=1, filesonly=1, followSymlinks=False)
+
+ # the linkcheck only works if we are in srcroot
+ mycwd = os.getcwd()
+ os.chdir(srcroot)
+ mysymlinks = filter(os.path.islink, listdir(srcroot, recursive=1, filesonly=0, followSymlinks=False))
+
+ stopmerge=False
+ starttime=time.time()
+ i=0
+
+ otherpkg=[]
+ mypkglist=[]
+
+ if self.pkg in otherversions:
+ otherversions.remove(self.pkg) # we already checked this package
+
+ for v in otherversions:
+ # should we check for same SLOT here ?
+ mypkglist.append(dblink(self.cat,v,destroot,self.settings))
+
+ print green("*")+" checking "+str(len(myfilelist))+" files for package collisions"
+ for f in myfilelist:
+ nocheck = False
+ # listdir isn't intelligent enough to exclude symlinked dirs,
+ # so we have to do it ourself
+ for s in mysymlinks:
+ # the length comparison makes sure that the symlink itself is checked
+ if f[:len(s)] == s and len(f) > len(s):
+ nocheck = True
+ if nocheck:
+ continue
+ i=i+1
+ if i % 1000 == 0:
+ print str(i)+" files checked ..."
+ if f[0] != "/":
+ f="/"+f
+ isowned = False
+ for ver in [self]+mypkglist:
+ if (ver.isowner(f, destroot) or ver.isprotected(f)):
+ isowned = True
+ break
+ if not isowned:
+ print "existing file "+f+" is not owned by this package"
+ stopmerge=True
+ print green("*")+" spent "+str(time.time()-starttime)+" seconds checking for file collisions"
+ if stopmerge:
+ print red("*")+" This package is blocked because it wants to overwrite"
+ print red("*")+" files belonging to other packages (see messages above)."
+ print red("*")+" If you have no clue what this is all about report it "
+ print red("*")+" as a bug for this package on http://bugs.gentoo.org"
+ print
+ print red("package "+self.cat+"/"+self.pkg+" NOT merged")
+ print
+ # Why is the package already merged here db-wise? Shouldn't be the case
+ # only unmerge if it ia new package and has no contents
+ if not self.getcontents():
+ self.unmerge()
+ self.delete()
+ self.unlockdb()
+ sys.exit(1)
+ try:
+ os.chdir(mycwd)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+
+ # get old contents info for later unmerging
+ oldcontents = self.getcontents()
+
+ self.dbdir = self.dbtmpdir
+ self.delete()
+ if not os.path.exists(self.dbtmpdir):
+ os.makedirs(self.dbtmpdir)
+
+ print ">>> Merging",self.mycpv,"to",destroot
+
+ # run preinst script
+ if myebuild:
+ # if we are merging a new ebuild, use *its* pre/postinst rather than using the one in /var/db/pkg
+ # (if any).
+ a=doebuild(myebuild,"preinst",root,self.settings,cleanup=cleanup,use_cache=0)
+ else:
+ a=doebuild(inforoot+"/"+self.pkg+".ebuild","preinst",root,self.settings,cleanup=cleanup,use_cache=0)
+
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED preinst: "+str(a)+"\n")
+ sys.exit(123)
+
+ # copy "info" files (like SLOT, CFLAGS, etc.) into the database
+ for x in listdir(inforoot):
+ self.copyfile(inforoot+"/"+x)
+
+ # get current counter value (counter_tick also takes care of incrementing it)
+ # XXX Need to make this destroot, but it needs to be initialized first. XXX
+ # XXX bis: leads to some invalidentry() call through cp_all().
+ counter = db["/"]["vartree"].dbapi.counter_tick(self.myroot,mycpv=self.mycpv)
+ # write local package counter for recording
+ lcfile = open(self.dbtmpdir+"/COUNTER","w")
+ lcfile.write(str(counter))
+ lcfile.close()
+
+ # open CONTENTS file (possibly overwriting old one) for recording
+ outfile=open(self.dbtmpdir+"/CONTENTS","w")
+
+ self.updateprotect()
+
+ #if we have a file containing previously-merged config file md5sums, grab it.
+ if os.path.exists(destroot+CONFIG_MEMORY_FILE):
+ cfgfiledict=grabdict(destroot+CONFIG_MEMORY_FILE)
+ else:
+ cfgfiledict={}
+ if self.settings.has_key("NOCONFMEM"):
+ cfgfiledict["IGNORE"]=1
+ else:
+ cfgfiledict["IGNORE"]=0
+
+ # set umask to 0 for merging; back up umask, save old one in prevmask (since this is a global change)
+ mymtime = long(time.time())
+ prevmask = os.umask(0)
+ secondhand = []
+
+ # we do a first merge; this will recurse through all files in our srcroot but also build up a
+ # "second hand" of symlinks to merge later
+ if self.mergeme(srcroot,destroot,outfile,secondhand,"",cfgfiledict,mymtime):
+ return 1
+
+ # now, it's time for dealing our second hand; we'll loop until we can't merge anymore. The rest are
+ # broken symlinks. We'll merge them too.
+ lastlen=0
+ while len(secondhand) and len(secondhand)!=lastlen:
+ # clear the thirdhand. Anything from our second hand that
+ # couldn't get merged will be added to thirdhand.
+
+ thirdhand=[]
+ self.mergeme(srcroot,destroot,outfile,thirdhand,secondhand,cfgfiledict,mymtime)
+
+ #swap hands
+ lastlen=len(secondhand)
+
+ # our thirdhand now becomes our secondhand. It's ok to throw
+ # away secondhand since thirdhand contains all the stuff that
+ # couldn't be merged.
+ secondhand = thirdhand
+
+ if len(secondhand):
+ # force merge of remaining symlinks (broken or circular; oh well)
+ self.mergeme(srcroot,destroot,outfile,None,secondhand,cfgfiledict,mymtime)
+
+ #restore umask
+ os.umask(prevmask)
+
+ #if we opened it, close it
+ outfile.flush()
+ outfile.close()
+
+ if (oldcontents):
+ print ">>> Safely unmerging already-installed instance..."
+ self.dbdir = self.dbpkgdir
+ self.unmerge(oldcontents,trimworld=0)
+ self.dbdir = self.dbtmpdir
+ print ">>> original instance of package unmerged safely."
+
+ # We hold both directory locks.
+ self.dbdir = self.dbpkgdir
+ self.delete()
+ movefile(self.dbtmpdir, self.dbpkgdir, mysettings=self.settings)
+
+ self.unlockdb()
+
+ #write out our collection of md5sums
+ if cfgfiledict.has_key("IGNORE"):
+ del cfgfiledict["IGNORE"]
+
+ # XXXX: HACK! PathSpec is very necessary here.
+ if not os.path.exists(destroot+PRIVATE_PATH):
+ os.makedirs(destroot+PRIVATE_PATH)
+ os.chown(destroot+PRIVATE_PATH,os.getuid(),portage_gid)
+ os.chmod(destroot+PRIVATE_PATH,02770)
+ dirlist = prefix_array(listdir(destroot+PRIVATE_PATH),destroot+PRIVATE_PATH+"/")
+ while dirlist:
+ dirlist.sort()
+ dirlist.reverse() # Gets them in file-before basedir order
+ x = dirlist[0]
+ if os.path.isdir(x):
+ dirlist += prefix_array(listdir(x),x+"/")
+ continue
+ os.unlink(destroot+PRIVATE_PATH+"/"+x)
+
+ mylock = portage_locks.lockfile(destroot+CONFIG_MEMORY_FILE)
+ writedict(cfgfiledict,destroot+CONFIG_MEMORY_FILE)
+ portage_locks.unlockfile(mylock)
+
+ #do postinst script
+ if myebuild:
+ # if we are merging a new ebuild, use *its* pre/postinst rather than using the one in /var/db/pkg
+ # (if any).
+ a=doebuild(myebuild,"postinst",root,self.settings,use_cache=0)
+ else:
+ a=doebuild(inforoot+"/"+self.pkg+".ebuild","postinst",root,self.settings,use_cache=0)
+
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED postinst: "+str(a)+"\n")
+ sys.exit(123)
+
+ downgrade = False
+ for v in otherversions:
+ if pkgcmp(catpkgsplit(self.pkg)[1:], catpkgsplit(v)[1:]) < 0:
+ downgrade = True
+
+ #update environment settings, library paths. DO NOT change symlinks.
+ env_update(makelinks=(not downgrade))
+ #dircache may break autoclean because it remembers the -MERGING-pkg file
+ global dircache
+ if dircache.has_key(self.dbcatdir):
+ del dircache[self.dbcatdir]
+ print ">>>",self.mycpv,"merged."
+ return 0
+
+ def mergeme(self,srcroot,destroot,outfile,secondhand,stufftomerge,cfgfiledict,thismtime):
+ srcroot=os.path.normpath("///"+srcroot)+"/"
+ destroot=os.path.normpath("///"+destroot)+"/"
+ # this is supposed to merge a list of files. There will be 2 forms of argument passing.
+ if type(stufftomerge)==types.StringType:
+ #A directory is specified. Figure out protection paths, listdir() it and process it.
+ mergelist=listdir(srcroot+stufftomerge)
+ offset=stufftomerge
+ # We need mydest defined up here to calc. protection paths. This is now done once per
+ # directory rather than once per file merge. This should really help merge performance.
+ # Trailing / ensures that protects/masks with trailing /'s match.
+ mytruncpath="/"+offset+"/"
+ myppath=self.isprotected(mytruncpath)
+ else:
+ mergelist=stufftomerge
+ offset=""
+ for x in mergelist:
+ mysrc=os.path.normpath("///"+srcroot+offset+x)
+ mydest=os.path.normpath("///"+destroot+offset+x)
+ # myrealdest is mydest without the $ROOT prefix (makes a difference if ROOT!="/")
+ myrealdest="/"+offset+x
+ # stat file once, test using S_* macros many times (faster that way)
+ try:
+ mystat=os.lstat(mysrc)
+ except SystemExit, e:
+ raise
+ except OSError, e:
+ writemsg("\n")
+ writemsg(red("!!! ERROR: There appears to be ")+bold("FILE SYSTEM CORRUPTION.")+red(" A file that is listed\n"))
+ writemsg(red("!!! as existing is not capable of being stat'd. If you are using an\n"))
+ writemsg(red("!!! experimental kernel, please boot into a stable one, force an fsck,\n"))
+ writemsg(red("!!! and ensure your filesystem is in a sane state. ")+bold("'shutdown -Fr now'\n"))
+ writemsg(red("!!! File: ")+str(mysrc)+"\n")
+ writemsg(red("!!! Error: ")+str(e)+"\n")
+ sys.exit(1)
+ except Exception, e:
+ writemsg("\n")
+ writemsg(red("!!! ERROR: An unknown error has occurred during the merge process.\n"))
+ writemsg(red("!!! A stat call returned the following error for the following file:"))
+ writemsg( "!!! Please ensure that your filesystem is intact, otherwise report\n")
+ writemsg( "!!! this as a portage bug at bugs.gentoo.org. Append 'emerge info'.\n")
+ writemsg( "!!! File: "+str(mysrc)+"\n")
+ writemsg( "!!! Error: "+str(e)+"\n")
+ sys.exit(1)
+
+
+ mymode=mystat[stat.ST_MODE]
+ # handy variables; mydest is the target object on the live filesystems;
+ # mysrc is the source object in the temporary install dir
+ try:
+ mydmode=os.lstat(mydest)[stat.ST_MODE]
+ except SystemExit, e:
+ raise
+ except:
+ #dest file doesn't exist
+ mydmode=None
+
+ if stat.S_ISLNK(mymode):
+ # we are merging a symbolic link
+ myabsto=abssymlink(mysrc)
+ if myabsto[0:len(srcroot)]==srcroot:
+ myabsto=myabsto[len(srcroot):]
+ if myabsto[0]!="/":
+ myabsto="/"+myabsto
+ myto=os.readlink(mysrc)
+ if self.settings and self.settings["D"]:
+ if myto.find(self.settings["D"])==0:
+ myto=myto[len(self.settings["D"]):]
+ # myrealto contains the path of the real file to which this symlink points.
+ # we can simply test for existence of this file to see if the target has been merged yet
+ myrealto=os.path.normpath(os.path.join(destroot,myabsto))
+ if mydmode!=None:
+ #destination exists
+ if not stat.S_ISLNK(mydmode):
+ if stat.S_ISDIR(mydmode):
+ # directory in the way: we can't merge a symlink over a directory
+ # we won't merge this, continue with next file...
+ continue
+ srctarget = os.path.normpath(os.path.dirname(mysrc)+"/"+myto)
+ if os.path.exists(mysrc) and stat.S_ISDIR(os.stat(mysrc)[stat.ST_MODE]):
+ # Kill file blocking installation of symlink to dir #71787
+ pass
+ elif self.isprotected(mydest):
+ # Use md5 of the target in ${D} if it exists...
+ if os.path.exists(os.path.normpath(srcroot+myabsto)):
+ mydest = new_protect_filename(myrealdest, newmd5=portage_checksum.perform_md5(srcroot+myabsto))
+ else:
+ mydest = new_protect_filename(myrealdest, newmd5=portage_checksum.perform_md5(myabsto))
+
+ # if secondhand==None it means we're operating in "force" mode and should not create a second hand.
+ if (secondhand!=None) and (not os.path.exists(myrealto)):
+ # either the target directory doesn't exist yet or the target file doesn't exist -- or
+ # the target is a broken symlink. We will add this file to our "second hand" and merge
+ # it later.
+ secondhand.append(mysrc[len(srcroot):])
+ continue
+ # unlinking no longer necessary; "movefile" will overwrite symlinks atomically and correctly
+ mymtime=movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)
+ if mymtime!=None:
+ print ">>>",mydest,"->",myto
+ outfile.write("sym "+myrealdest+" -> "+myto+" "+str(mymtime)+"\n")
+ else:
+ print "!!! Failed to move file."
+ print "!!!",mydest,"->",myto
+ sys.exit(1)
+ elif stat.S_ISDIR(mymode):
+ # we are merging a directory
+ if mydmode!=None:
+ # destination exists
+
+ if bsd_chflags:
+ # Save then clear flags on dest.
+ dflags=bsd_chflags.lgetflags(mydest)
+ if(bsd_chflags.lchflags(mydest, 0)<0):
+ writemsg("!!! Couldn't clear flags on '"+mydest+"'.\n")
+
+ if not os.access(mydest, os.W_OK):
+ pkgstuff = pkgsplit(self.pkg)
+ writemsg("\n!!! Cannot write to '"+mydest+"'.\n")
+ writemsg("!!! Please check permissions and directories for broken symlinks.\n")
+ writemsg("!!! You may start the merge process again by using ebuild:\n")
+ writemsg("!!! ebuild "+self.settings["PORTDIR"]+"/"+self.cat+"/"+pkgstuff[0]+"/"+self.pkg+".ebuild merge\n")
+ writemsg("!!! And finish by running this: env-update\n\n")
+ return 1
+
+ if stat.S_ISLNK(mydmode) or stat.S_ISDIR(mydmode):
+ # a symlink to an existing directory will work for us; keep it:
+ print "---",mydest+"/"
+ if bsd_chflags:
+ bsd_chflags.lchflags(mydest, dflags)
+ else:
+ # a non-directory and non-symlink-to-directory. Won't work for us. Move out of the way.
+ if movefile(mydest,mydest+".backup", mysettings=self.settings) == None:
+ sys.exit(1)
+ print "bak",mydest,mydest+".backup"
+ #now create our directory
+ if selinux_enabled:
+ sid = selinux.get_sid(mysrc)
+ selinux.secure_mkdir(mydest,sid)
+ else:
+ os.mkdir(mydest)
+ if bsd_chflags:
+ bsd_chflags.lchflags(mydest, dflags)
+ os.chmod(mydest,mystat[0])
+ lchown(mydest,mystat[4],mystat[5])
+ print ">>>",mydest+"/"
+ else:
+ #destination doesn't exist
+ if selinux_enabled:
+ sid = selinux.get_sid(mysrc)
+ selinux.secure_mkdir(mydest,sid)
+ else:
+ os.mkdir(mydest)
+ os.chmod(mydest,mystat[0])
+ if bsd_chflags:
+ bsd_chflags.lchflags(mydest, bsd_chflags.lgetflags(mysrc))
+ lchown(mydest,mystat[4],mystat[5])
+ print ">>>",mydest+"/"
+ outfile.write("dir "+myrealdest+"\n")
+ # recurse and merge this directory
+ if self.mergeme(srcroot,destroot,outfile,secondhand,offset+x+"/",cfgfiledict,thismtime):
+ return 1
+ elif stat.S_ISREG(mymode):
+ # we are merging a regular file
+ mymd5=portage_checksum.perform_md5(mysrc,calc_prelink=1)
+ # calculate config file protection stuff
+ mydestdir=os.path.dirname(mydest)
+ moveme=1
+ zing="!!!"
+ if mydmode!=None:
+ # destination file exists
+ if stat.S_ISDIR(mydmode):
+ # install of destination is blocked by an existing directory with the same name
+ moveme=0
+ print "!!!",mydest
+ elif stat.S_ISREG(mydmode) or (stat.S_ISLNK(mydmode) and os.path.exists(mydest) and stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])):
+ cfgprot=0
+ # install of destination is blocked by an existing regular file,
+ # or by a symlink to an existing regular file;
+ # now, config file management may come into play.
+ # we only need to tweak mydest if cfg file management is in play.
+ if myppath:
+ # we have a protection path; enable config file management.
+ destmd5=portage_checksum.perform_md5(mydest,calc_prelink=1)
+ cycled=0
+ if cfgfiledict.has_key(myrealdest):
+ if destmd5 in cfgfiledict[myrealdest]:
+ #cycle
+ print "cycle"
+ del cfgfiledict[myrealdest]
+ cycled=1
+ if mymd5==destmd5:
+ #file already in place; simply update mtimes of destination
+ os.utime(mydest,(thismtime,thismtime))
+ zing="---"
+ moveme=0
+ elif cycled:
+ #mymd5!=destmd5 and we've cycled; move mysrc into place as a ._cfg file
+ moveme=1
+ cfgfiledict[myrealdest]=[mymd5]
+ cfgprot=1
+ elif cfgfiledict.has_key(myrealdest) and (mymd5 in cfgfiledict[myrealdest]):
+ #myd5!=destmd5, we haven't cycled, and the file we're merging has been already merged previously
+ zing="-o-"
+ moveme=cfgfiledict["IGNORE"]
+ cfgprot=cfgfiledict["IGNORE"]
+ else:
+ #mymd5!=destmd5, we haven't cycled, and the file we're merging hasn't been merged before
+ moveme=1
+ cfgprot=1
+ if not cfgfiledict.has_key(myrealdest):
+ cfgfiledict[myrealdest]=[]
+ if mymd5 not in cfgfiledict[myrealdest]:
+ cfgfiledict[myrealdest].append(mymd5)
+ # only record the last md5
+ if len(cfgfiledict[myrealdest])>1:
+ del cfgfiledict[myrealdest][0]
+
+ if cfgprot:
+ mydest = new_protect_filename(myrealdest, newmd5=mymd5)
+
+ # whether config protection or not, we merge the new file the
+ # same way. Unless moveme=0 (blocking directory)
+ if moveme:
+ mymtime=movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)
+ if mymtime == None:
+ sys.exit(1)
+ zing=">>>"
+ else:
+ mymtime=thismtime
+ # We need to touch the destination so that on --update the
+ # old package won't yank the file with it. (non-cfgprot related)
+ os.utime(myrealdest,(thismtime,thismtime))
+ zing="---"
+ if self.settings["USERLAND"] == "Darwin" and myrealdest[-2:] == ".a":
+
+ # XXX kludge, bug #58848; can be killed when portage stops relying on
+ # md5+mtime, and uses refcounts
+ # alright, we've fooled w/ mtime on the file; this pisses off static archives
+ # basically internal mtime != file's mtime, so the linker (falsely) thinks
+ # the archive is stale, and needs to have it's toc rebuilt.
+
+ myf=open(myrealdest,"r+")
+
+ # ar mtime field is digits padded with spaces, 12 bytes.
+ lms=str(thismtime+5).ljust(12)
+ myf.seek(0)
+ magic=myf.read(8)
+ if magic != "!<arch>\n":
+ # not an archive (dolib.a from portage.py makes it here fex)
+ myf.close()
+ else:
+ st=os.stat(myrealdest)
+ while myf.tell() < st.st_size - 12:
+ # skip object name
+ myf.seek(16,1)
+
+ # update mtime
+ myf.write(lms)
+
+ # skip uid/gid/mperm
+ myf.seek(20,1)
+
+ # read the archive member's size
+ x=long(myf.read(10))
+
+ # skip the trailing newlines, and add the potential
+ # extra padding byte if it's not an even size
+ myf.seek(x + 2 + (x % 2),1)
+
+ # and now we're at the end. yay.
+ myf.close()
+ mymd5=portage_checksum.perform_md5(myrealdest,calc_prelink=1)
+ os.utime(myrealdest,(thismtime,thismtime))
+
+ if mymtime!=None:
+ zing=">>>"
+ outfile.write("obj "+myrealdest+" "+mymd5+" "+str(mymtime)+"\n")
+ print zing,mydest
+ else:
+ # we are merging a fifo or device node
+ zing="!!!"
+ if mydmode==None:
+ # destination doesn't exist
+ if movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)!=None:
+ zing=">>>"
+ if stat.S_ISFIFO(mymode):
+ # we don't record device nodes in CONTENTS,
+ # although we do merge them.
+ outfile.write("fif "+myrealdest+"\n")
+ else:
+ sys.exit(1)
+ print zing+" "+mydest
+
+ def merge(self,mergeroot,inforoot,myroot,myebuild=None,cleanup=0):
+ return self.treewalk(mergeroot,myroot,inforoot,myebuild,cleanup=cleanup)
+
+ def getstring(self,name):
+ "returns contents of a file with whitespace converted to spaces"
+ if not os.path.exists(self.dbdir+"/"+name):
+ return ""
+ myfile=open(self.dbdir+"/"+name,"r")
+ mydata=string.split(myfile.read())
+ myfile.close()
+ return string.join(mydata," ")
+
+ def copyfile(self,fname):
+ shutil.copyfile(fname,self.dbdir+"/"+os.path.basename(fname))
+
+ def getfile(self,fname):
+ if not os.path.exists(self.dbdir+"/"+fname):
+ return ""
+ myfile=open(self.dbdir+"/"+fname,"r")
+ mydata=myfile.read()
+ myfile.close()
+ return mydata
+
+ def setfile(self,fname,data):
+ myfile=open(self.dbdir+"/"+fname,"w")
+ myfile.write(data)
+ myfile.close()
+
+ def getelements(self,ename):
+ if not os.path.exists(self.dbdir+"/"+ename):
+ return []
+ myelement=open(self.dbdir+"/"+ename,"r")
+ mylines=myelement.readlines()
+ myreturn=[]
+ for x in mylines:
+ for y in string.split(x[:-1]):
+ myreturn.append(y)
+ myelement.close()
+ return myreturn
+
+ def setelements(self,mylist,ename):
+ myelement=open(self.dbdir+"/"+ename,"w")
+ for x in mylist:
+ myelement.write(x+"\n")
+ myelement.close()
+
+ def isregular(self):
+ "Is this a regular package (does it have a CATEGORY file? A dblink can be virtual *and* regular)"
+ return os.path.exists(self.dbdir+"/CATEGORY")
+
+def cleanup_pkgmerge(mypkg,origdir):
+ shutil.rmtree(settings["PORTAGE_TMPDIR"]+"/portage-pkg/"+mypkg)
+ if os.path.exists(settings["PORTAGE_TMPDIR"]+"/portage/"+mypkg+"/temp/environment"):
+ os.unlink(settings["PORTAGE_TMPDIR"]+"/portage/"+mypkg+"/temp/environment")
+ os.chdir(origdir)
+
+def pkgmerge(mytbz2,myroot,mysettings):
+ """will merge a .tbz2 file, returning a list of runtime dependencies
+ that must be satisfied, or None if there was a merge error. This
+ code assumes the package exists."""
+ if mytbz2[-5:]!=".tbz2":
+ print "!!! Not a .tbz2 file"
+ return None
+ mypkg=os.path.basename(mytbz2)[:-5]
+ xptbz2=xpak.tbz2(mytbz2)
+ pkginfo={}
+ mycat=xptbz2.getfile("CATEGORY")
+ if not mycat:
+ print "!!! CATEGORY info missing from info chunk, aborting..."
+ return None
+ mycat=mycat.strip()
+ mycatpkg=mycat+"/"+mypkg
+ tmploc=mysettings["PORTAGE_TMPDIR"]+"/portage-pkg/"
+ pkgloc=tmploc+"/"+mypkg+"/bin/"
+ infloc=tmploc+"/"+mypkg+"/inf/"
+ myebuild=tmploc+"/"+mypkg+"/inf/"+os.path.basename(mytbz2)[:-4]+"ebuild"
+ if os.path.exists(tmploc+"/"+mypkg):
+ shutil.rmtree(tmploc+"/"+mypkg,1)
+ os.makedirs(pkgloc)
+ os.makedirs(infloc)
+ print ">>> extracting info"
+ xptbz2.unpackinfo(infloc)
+ # run pkg_setup early, so we can bail out early
+ # (before extracting binaries) if there's a problem
+ origdir=getcwd()
+ os.chdir(pkgloc)
+
+ mysettings.configdict["pkg"]["CATEGORY"] = mycat;
+ a=doebuild(myebuild,"setup",myroot,mysettings,tree="bintree")
+ print ">>> extracting",mypkg
+ notok=spawn("bzip2 -dqc -- '"+mytbz2+"' | tar xpf -",mysettings,free=1)
+ if notok:
+ print "!!! Error extracting",mytbz2
+ cleanup_pkgmerge(mypkg,origdir)
+ return None
+
+ # the merge takes care of pre/postinst and old instance
+ # auto-unmerge, virtual/provides updates, etc.
+ mysettings.load_infodir(infloc)
+ mylink=dblink(mycat,mypkg,myroot,mysettings)
+ mylink.merge(pkgloc,infloc,myroot,myebuild,cleanup=1)
+
+ if not os.path.exists(infloc+"/RDEPEND"):
+ returnme=""
+ else:
+ #get runtime dependencies
+ a=open(infloc+"/RDEPEND","r")
+ returnme=string.join(string.split(a.read())," ")
+ a.close()
+ cleanup_pkgmerge(mypkg,origdir)
+ return returnme
+
+
+if os.environ.has_key("ROOT"):
+ root=os.environ["ROOT"]
+ if not len(root):
+ root="/"
+ elif root[-1]!="/":
+ root=root+"/"
+else:
+ root="/"
+if root != "/":
+ if not os.path.exists(root[:-1]):
+ writemsg("!!! Error: ROOT "+root+" does not exist. Please correct this.\n")
+ writemsg("!!! Exiting.\n\n")
+ sys.exit(1)
+ elif not os.path.isdir(root[:-1]):
+ writemsg("!!! Error: ROOT "+root[:-1]+" is not a directory. Please correct this.\n")
+ writemsg("!!! Exiting.\n\n")
+ sys.exit(1)
+
+#create tmp and var/tmp if they don't exist; read config
+os.umask(0)
+if not os.path.exists(root+"tmp"):
+ writemsg(">>> "+root+"tmp doesn't exist, creating it...\n")
+ os.mkdir(root+"tmp",01777)
+if not os.path.exists(root+"var/tmp"):
+ writemsg(">>> "+root+"var/tmp doesn't exist, creating it...\n")
+ try:
+ os.mkdir(root+"var",0755)
+ except (OSError,IOError):
+ pass
+ try:
+ os.mkdir(root+"var/tmp",01777)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("portage: couldn't create /var/tmp; exiting.\n")
+ sys.exit(1)
+if not os.path.exists(root+"var/lib/portage"):
+ writemsg(">>> "+root+"var/lib/portage doesn't exist, creating it...\n")
+ try:
+ os.mkdir(root+"var",0755)
+ except (OSError,IOError):
+ pass
+ try:
+ os.mkdir(root+"var/lib",0755)
+ except (OSError,IOError):
+ pass
+ try:
+ os.mkdir(root+"var/lib/portage",02750)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("portage: couldn't create /var/lib/portage; exiting.\n")
+ sys.exit(1)
+
+
+#####################################
+# Deprecation Checks
+
+os.umask(022)
+profiledir=None
+if "PORTAGE_CALLER" in os.environ and os.environ["PORTAGE_CALLER"] == "emerge" and os.path.isdir(PROFILE_PATH):
+ profiledir = PROFILE_PATH
+ if os.access(DEPRECATED_PROFILE_FILE, os.R_OK):
+ deprecatedfile = open(DEPRECATED_PROFILE_FILE, "r")
+ dcontent = deprecatedfile.readlines()
+ deprecatedfile.close()
+ newprofile = dcontent[0]
+ writemsg(red("\n!!! Your current profile is deprecated and not supported anymore.\n"))
+ writemsg(red("!!! Please upgrade to the following profile if possible:\n"))
+ writemsg(8*" "+green(newprofile)+"\n")
+ if len(dcontent) > 1:
+ writemsg("To upgrade do the following steps:\n")
+ for myline in dcontent[1:]:
+ writemsg(myline)
+ writemsg("\n\n")
+
+if os.path.exists(USER_VIRTUALS_FILE):
+ writemsg(red("\n!!! /etc/portage/virtuals is deprecated in favor of\n"))
+ writemsg(red("!!! /etc/portage/profile/virtuals. Please move it to\n"))
+ writemsg(red("!!! this new location.\n\n"))
+
+#
+#####################################
+
+db={}
+
+# =============================================================================
+# =============================================================================
+# -----------------------------------------------------------------------------
+# We're going to lock the global config to prevent changes, but we need
+# to ensure the global settings are right.
+settings=config(config_profile_path=PROFILE_PATH,config_incrementals=portage_const.INCREMENTALS)
+
+# useful info
+settings["PORTAGE_MASTER_PID"]=str(os.getpid())
+settings.backup_changes("PORTAGE_MASTER_PID")
+# We are disabling user-specific bashrc files.
+settings["BASH_ENV"] = INVALID_ENV_FILE
+settings.backup_changes("BASH_ENV")
+
+# gets virtual package settings
+def getvirtuals(myroot):
+ global settings
+ writemsg("--- DEPRECATED call to getvirtual\n")
+ return settings.getvirtuals(myroot)
+
+def do_vartree(mysettings):
+ global virts,virts_p
+ virts=mysettings.getvirtuals("/")
+ virts_p={}
+
+ if virts:
+ myvkeys=virts.keys()
+ for x in myvkeys:
+ vkeysplit=x.split("/")
+ if not virts_p.has_key(vkeysplit[1]):
+ virts_p[vkeysplit[1]]=virts[x]
+ db["/"]={"virtuals":virts,"vartree":vartree("/",virts)}
+ if root!="/":
+ virts=mysettings.getvirtuals(root)
+ db[root]={"virtuals":virts,"vartree":vartree(root,virts)}
+ #We need to create the vartree first, then load our settings, and then set up our other trees
+
+usedefaults=settings.use_defs
+
+# XXX: This is a circular fix.
+#do_vartree(settings)
+#settings.loadVirtuals('/')
+do_vartree(settings)
+#settings.loadVirtuals('/')
+
+settings.reset() # XXX: Regenerate use after we get a vartree -- GLOBAL
+
+
+# XXX: Might cause problems with root="/" assumptions
+portdb=portdbapi(settings["PORTDIR"])
+
+settings.lock()
+# -----------------------------------------------------------------------------
+# =============================================================================
+# =============================================================================
+
+
+if 'selinux' in settings["USE"].split(" "):
+ try:
+ import selinux
+ selinux_enabled=1
+ except OSError, e:
+ writemsg(red("!!! SELinux not loaded: ")+str(e)+"\n")
+ selinux_enabled=0
+ except ImportError:
+ writemsg(red("!!! SELinux module not found.")+" Please verify that it was installed.\n")
+ selinux_enabled=0
+else:
+ selinux_enabled=0
+
+cachedirs=[CACHE_PATH]
+if root!="/":
+ cachedirs.append(root+CACHE_PATH)
+if not os.environ.has_key("SANDBOX_ACTIVE"):
+ for cachedir in cachedirs:
+ if not os.path.exists(cachedir):
+ os.makedirs(cachedir,0755)
+ writemsg(">>> "+cachedir+" doesn't exist, creating it...\n")
+ if not os.path.exists(cachedir+"/dep"):
+ os.makedirs(cachedir+"/dep",2755)
+ writemsg(">>> "+cachedir+"/dep doesn't exist, creating it...\n")
+ try:
+ os.chown(cachedir,uid,portage_gid)
+ os.chmod(cachedir,0775)
+ except OSError:
+ pass
+ try:
+ mystat=os.lstat(cachedir+"/dep")
+ os.chown(cachedir+"/dep",uid,portage_gid)
+ os.chmod(cachedir+"/dep",02775)
+ if mystat[stat.ST_GID]!=portage_gid:
+ spawn("chown -R "+str(uid)+":"+str(portage_gid)+" "+cachedir+"/dep",settings,free=1)
+ spawn("chmod -R u+rw,g+rw "+cachedir+"/dep",settings,free=1)
+ except OSError:
+ pass
+
+def flushmtimedb(record):
+ if mtimedb:
+ if record in mtimedb.keys():
+ del mtimedb[record]
+ #print "mtimedb["+record+"] is cleared."
+ else:
+ writemsg("Invalid or unset record '"+record+"' in mtimedb.\n")
+
+#grab mtimes for eclasses and upgrades
+mtimedb={}
+mtimedbkeys=[
+"updates", "info",
+"version", "starttime",
+"resume", "ldpath"
+]
+mtimedbfile=root+"var/cache/edb/mtimedb"
+try:
+ mypickle=cPickle.Unpickler(open(mtimedbfile))
+ mypickle.find_global=None
+ mtimedb=mypickle.load()
+ if mtimedb.has_key("old"):
+ mtimedb["updates"]=mtimedb["old"]
+ del mtimedb["old"]
+ if mtimedb.has_key("cur"):
+ del mtimedb["cur"]
+except SystemExit, e:
+ raise
+except:
+ #print "!!!",e
+ mtimedb={"updates":{},"version":"","starttime":0}
+
+for x in mtimedb.keys():
+ if x not in mtimedbkeys:
+ writemsg("Deleting invalid mtimedb key: "+str(x)+"\n")
+ del mtimedb[x]
+
+#,"porttree":portagetree(root,virts),"bintree":binarytree(root,virts)}
+features=settings["FEATURES"].split()
+
+do_upgrade_packagesmessage=0
+def do_upgrade(mykey):
+ global do_upgrade_packagesmessage
+ writemsg("\n\n")
+ writemsg(green("Performing Global Updates: ")+bold(mykey)+"\n")
+ writemsg("(Could take a couple of minutes if you have a lot of binary packages.)\n")
+ writemsg(" "+bold(".")+"='update pass' "+bold("*")+"='binary update' "+bold("@")+"='/var/db move'\n"+" "+bold("s")+"='/var/db SLOT move' "+bold("S")+"='binary SLOT move' "+bold("p")+"='update /etc/portage/package.*'\n")
+ processed=1
+ #remove stale virtual entries (mappings for packages that no longer exist)
+
+ update_files={}
+ file_contents={}
+ myxfiles = ["package.mask","package.unmask","package.keywords","package.use"]
+ myxfiles = myxfiles + prefix_array(myxfiles, "profile/")
+ for x in myxfiles:
+ try:
+ myfile = open("/etc/portage/"+x,"r")
+ file_contents[x] = myfile.readlines()
+ myfile.close()
+ except IOError:
+ if file_contents.has_key(x):
+ del file_contents[x]
+ continue
+
+ worldlist=grabfile("/"+WORLD_FILE)
+ myupd=grabfile(mykey)
+ db["/"]["bintree"]=binarytree("/",settings["PKGDIR"],virts)
+ for myline in myupd:
+ mysplit=myline.split()
+ if not len(mysplit):
+ continue
+ if mysplit[0]!="move" and mysplit[0]!="slotmove":
+ writemsg("portage: Update type \""+mysplit[0]+"\" not recognized.\n")
+ processed=0
+ continue
+ if mysplit[0]=="move" and len(mysplit)!=3:
+ writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n")
+ processed=0
+ continue
+ if mysplit[0]=="slotmove" and len(mysplit)!=4:
+ writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n")
+ processed=0
+ continue
+ sys.stdout.write(".")
+ sys.stdout.flush()
+
+ if mysplit[0]=="move":
+ db["/"]["vartree"].dbapi.move_ent(mysplit)
+ db["/"]["bintree"].move_ent(mysplit)
+ #update world entries:
+ for x in range(0,len(worldlist)):
+ #update world entries, if any.
+ worldlist[x]=dep_transform(worldlist[x],mysplit[1],mysplit[2])
+
+ #update /etc/portage/packages.*
+ for x in file_contents:
+ for mypos in range(0,len(file_contents[x])):
+ line=file_contents[x][mypos]
+ if line[0]=="#" or string.strip(line)=="":
+ continue
+ key=dep_getkey(line.split()[0])
+ if key==mysplit[1]:
+ file_contents[x][mypos]=string.replace(line,mysplit[1],mysplit[2])
+ update_files[x]=1
+ sys.stdout.write("p")
+ sys.stdout.flush()
+
+ elif mysplit[0]=="slotmove":
+ db["/"]["vartree"].dbapi.move_slot_ent(mysplit)
+ db["/"]["bintree"].move_slot_ent(mysplit,settings["PORTAGE_TMPDIR"]+"/tbz2")
+
+ for x in update_files:
+ mydblink = dblink('','','/',settings)
+ if mydblink.isprotected("/etc/portage/"+x):
+ updating_file=new_protect_filename("/etc/portage/"+x)[0]
+ else:
+ updating_file="/etc/portage/"+x
+ try:
+ myfile=open(updating_file,"w")
+ myfile.writelines(file_contents[x])
+ myfile.close()
+ except IOError:
+ continue
+
+ # We gotta do the brute force updates for these now.
+ if (settings["PORTAGE_CALLER"] in ["fixpackages"]) or \
+ ("fixpackages" in features):
+ db["/"]["bintree"].update_ents(myupd,settings["PORTAGE_TMPDIR"]+"/tbz2")
+ else:
+ do_upgrade_packagesmessage = 1
+
+ if processed:
+ #update our internal mtime since we processed all our directives.
+ mtimedb["updates"][mykey]=os.stat(mykey)[stat.ST_MTIME]
+ myworld=open("/"+WORLD_FILE,"w")
+ for x in worldlist:
+ myworld.write(x+"\n")
+ myworld.close()
+ print ""
+
+def portageexit():
+ global uid,portage_gid,portdb,db
+ if secpass and not os.environ.has_key("SANDBOX_ACTIVE"):
+ # wait child process death
+ try:
+ while True:
+ os.wait()
+ except OSError:
+ #writemsg(">>> All child process are now dead.")
+ pass
+
+ close_portdbapi_caches()
+
+ if mtimedb:
+ # Store mtimedb
+ mymfn=mtimedbfile
+ try:
+ mtimedb["version"]=VERSION
+ cPickle.dump(mtimedb, open(mymfn,"w"), -1)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+ try:
+ os.chown(mymfn,uid,portage_gid)
+ os.chmod(mymfn,0664)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+atexit.register(portageexit)
+
+if (secpass==2) and (not os.environ.has_key("SANDBOX_ACTIVE")):
+ if settings["PORTAGE_CALLER"] in ["emerge","fixpackages"]:
+ #only do this if we're root and not running repoman/ebuild digest
+ updpath=os.path.normpath(settings["PORTDIR"]+"///profiles/updates")
+ didupdate=0
+ if not mtimedb.has_key("updates"):
+ mtimedb["updates"]={}
+ try:
+ mylist=listdir(updpath,EmptyOnError=1)
+ # resort the list
+ mylist=[myfile[3:]+"-"+myfile[:2] for myfile in mylist]
+ mylist.sort()
+ mylist=[myfile[5:]+"-"+myfile[:4] for myfile in mylist]
+ for myfile in mylist:
+ mykey=updpath+"/"+myfile
+ if not os.path.isfile(mykey):
+ continue
+ if (not mtimedb["updates"].has_key(mykey)) or \
+ (mtimedb["updates"][mykey] != os.stat(mykey)[stat.ST_MTIME]) or \
+ (settings["PORTAGE_CALLER"] == "fixpackages"):
+ didupdate=1
+ do_upgrade(mykey)
+ portageexit() # This lets us save state for C-c.
+ except OSError:
+ #directory doesn't exist
+ pass
+ if didupdate:
+ #make sure our internal databases are consistent; recreate our virts and vartree
+ do_vartree(settings)
+ if do_upgrade_packagesmessage and \
+ listdir(settings["PKGDIR"]+"/All/",EmptyOnError=1):
+ writemsg("\n\n\n ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the")
+ writemsg("\n tbz2's in the packages directory. "+bold("Note: This can take a very long time."))
+ writemsg("\n")
+
+
+
+
+
+#continue setting up other trees
+db["/"]["porttree"]=portagetree("/",virts)
+db["/"]["bintree"]=binarytree("/",settings["PKGDIR"],virts)
+if root!="/":
+ db[root]["porttree"]=portagetree(root,virts)
+ db[root]["bintree"]=binarytree(root,settings["PKGDIR"],virts)
+
+profileroots = [settings["PORTDIR"]+"/profiles/"]
+for x in settings["PORTDIR_OVERLAY"].split():
+ profileroots.insert(0, x+"/profiles/")
+thirdparty_lists = grab_multiple("thirdpartymirrors", profileroots, grabdict)
+thirdpartymirrors = stack_dictlist(thirdparty_lists, incremental=True)
+
+if not os.path.exists(settings["PORTAGE_TMPDIR"]):
+ writemsg("portage: the directory specified in your PORTAGE_TMPDIR variable, \""+settings["PORTAGE_TMPDIR"]+",\"\n")
+ writemsg("does not exist. Please create this directory or correct your PORTAGE_TMPDIR setting.\n")
+ sys.exit(1)
+if not os.path.isdir(settings["PORTAGE_TMPDIR"]):
+ writemsg("portage: the directory specified in your PORTAGE_TMPDIR variable, \""+settings["PORTAGE_TMPDIR"]+",\"\n")
+ writemsg("is not a directory. Please correct your PORTAGE_TMPDIR setting.\n")
+ sys.exit(1)
+
+# COMPATABILITY -- This shouldn't be used.
+pkglines = settings.packages
+
+groups=settings["ACCEPT_KEYWORDS"].split()
+archlist=[]
+for myarch in grabfile(settings["PORTDIR"]+"/profiles/arch.list"):
+ archlist += [myarch,"~"+myarch]
+for group in groups:
+ if not archlist:
+ writemsg("--- 'profiles/arch.list' is empty or not available. Empty portage tree?\n")
+ break
+ elif (group not in archlist) and group[0]!='-':
+ writemsg("\n"+red("!!! INVALID ACCEPT_KEYWORDS: ")+str(group)+"\n")
+
+# Clear the cache
+dircache={}
+
+if not os.path.islink(PROFILE_PATH) and os.path.exists(settings["PORTDIR"]+"/profiles"):
+ writemsg(red("\a\n\n!!! "+PROFILE_PATH+" is not a symlink and will probably prevent most merges.\n"))
+ writemsg(red("!!! It should point into a profile within %s/profiles/\n" % settings["PORTDIR"]))
+ writemsg(red("!!! (You can safely ignore this message when syncing. It's harmless.)\n\n\n"))
+ time.sleep(3)
+
+# ============================================================================
+# ============================================================================
+
diff --git a/pym/portage.py.orig b/pym/portage.py.orig
new file mode 100644
index 00000000..5fae17ea
--- /dev/null
+++ b/pym/portage.py.orig
@@ -0,0 +1,7427 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage.py,v 1.524.2.59 2005/04/23 07:26:04 jstubbs Exp $
+cvs_id_string="$Id: portage.py,v 1.524.2.59 2005/04/23 07:26:04 jstubbs Exp $"[5:-2]
+
+VERSION="$Revision: 1.524.2.59 $"[11:-2] + "-cvs"
+
+# ===========================================================================
+# START OF IMPORTS -- START OF IMPORTS -- START OF IMPORTS -- START OF IMPORT
+# ===========================================================================
+
+try:
+ import sys
+except SystemExit, e:
+ raise
+except:
+ print "Failed to import sys! Something is _VERY_ wrong with python."
+ raise SystemExit, 127
+
+try:
+ import os,string,types,atexit,signal,fcntl
+ import time,cPickle,traceback,copy
+ import re,pwd,grp,commands
+ import shlex,shutil
+
+ import stat
+ import commands
+ from time import sleep
+ from random import shuffle
+except SystemExit, e:
+ raise
+except Exception, e:
+ sys.stderr.write("\n\n")
+ sys.stderr.write("!!! Failed to complete python imports. There are internal modules for\n")
+ sys.stderr.write("!!! python and failure here indicates that you have a problem with python\n")
+ sys.stderr.write("!!! itself and thus portage is no able to continue processing.\n\n")
+
+ sys.stderr.write("!!! You might consider starting python with verbose flags to see what has\n")
+ sys.stderr.write("!!! gone wrong. Here is the information we got for this exception:\n")
+
+ sys.stderr.write(" "+str(e)+"\n\n");
+ sys.exit(127)
+except:
+ sys.stderr.write("\n\n")
+ sys.stderr.write("!!! Failed to complete python imports. There are internal modules for\n")
+ sys.stderr.write("!!! python and failure here indicates that you have a problem with python\n")
+ sys.stderr.write("!!! itself and thus portage is no able to continue processing.\n\n")
+
+ sys.stderr.write("!!! You might consider starting python with verbose flags to see what has\n")
+ sys.stderr.write("!!! gone wrong. The exception was non-standard and we were unable to catch it.\n\n")
+ sys.exit(127)
+
+try:
+ # XXX: This should get renamed to bsd_chflags, I think.
+ import chflags
+ bsd_chflags = chflags
+except SystemExit, e:
+ raise
+except:
+ # XXX: This should get renamed to bsd_chflags, I think.
+ bsd_chflags = None
+
+try:
+ import cvstree
+ import xpak
+ import getbinpkg
+ import portage_dep
+
+ # XXX: This needs to get cleaned up.
+ import output
+ from output import blue, bold, brown, darkblue, darkgreen, darkred, darkteal, \
+ darkyellow, fuchsia, fuscia, green, purple, red, teal, turquoise, white, \
+ xtermTitle, xtermTitleReset, yellow
+
+ import portage_const
+ from portage_const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \
+ USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
+ PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
+ EBUILD_SH_BINARY, SANDBOX_BINARY, DEPSCAN_SH_BINARY, BASH_BINARY, \
+ MOVE_BINARY, PRELINK_BINARY, WORLD_FILE, MAKE_CONF_FILE, MAKE_DEFAULTS_FILE, \
+ DEPRECATED_PROFILE_FILE, USER_VIRTUALS_FILE, EBUILD_SH_ENV_FILE, \
+ INVALID_ENV_FILE, CUSTOM_MIRRORS_FILE, SANDBOX_PIDS_FILE, CONFIG_MEMORY_FILE,\
+ INCREMENTALS, STICKIES
+
+ from portage_data import ostype, lchown, userland, secpass, uid, wheelgid, \
+ portage_uid, portage_gid
+
+ import portage_util
+ from portage_util import grab_multiple, grabdict, grabdict_package, grabfile, grabfile_package, \
+ grabints, map_dictlist_vals, pickle_read, pickle_write, stack_dictlist, stack_dicts, stack_lists, \
+ unique_array, varexpand, writedict, writeints, writemsg, getconfig
+ import portage_exception
+ import portage_gpg
+ import portage_locks
+ import portage_exec
+ from portage_locks import unlockfile,unlockdir,lockfile,lockdir
+ import portage_checksum
+ from portage_checksum import perform_md5,perform_checksum,prelink_capable
+ from portage_localization import _
+except SystemExit, e:
+ raise
+except Exception, e:
+ sys.stderr.write("\n\n")
+ sys.stderr.write("!!! Failed to complete portage imports. There are internal modules for\n")
+ sys.stderr.write("!!! portage and failure here indicates that you have a problem with your\n")
+ sys.stderr.write("!!! installation of portage. Please try a rescue portage located in the\n")
+ sys.stderr.write("!!! portage tree under '/usr/portage/sys-apps/portage/files/' (default).\n")
+ sys.stderr.write("!!! There is a README.RESCUE file that details the steps required to perform\n")
+ sys.stderr.write("!!! a recovery of portage.\n")
+
+ sys.stderr.write(" "+str(e)+"\n\n")
+ sys.exit(127)
+
+
+# ===========================================================================
+# END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END
+# ===========================================================================
+
+
+def exithandler(signum,frame):
+ """Handles ^C interrupts in a sane manner"""
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+ signal.signal(signal.SIGTERM, signal.SIG_IGN)
+
+ # 0=send to *everybody* in process group
+ portageexit()
+ print "Exiting due to signal"
+ os.kill(0,signum)
+ sys.exit(1)
+
+signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+signal.signal(signal.SIGINT, exithandler)
+signal.signal(signal.SIGTERM, exithandler)
+signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+def load_mod(name):
+ modname = string.join(string.split(name,".")[:-1],".")
+ mod = __import__(modname)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+def best_from_dict(key, top_dict, key_order, EmptyOnError=1, FullCopy=1, AllowEmpty=1):
+ for x in key_order:
+ if top_dict.has_key(x) and top_dict[x].has_key(key):
+ if FullCopy:
+ return copy.deepcopy(top_dict[x][key])
+ else:
+ return top_dict[x][key]
+ if EmptyOnError:
+ return ""
+ else:
+ raise KeyError, "Key not found in list; '%s'" % key
+
+def getcwd():
+ "this fixes situations where the current directory doesn't exist"
+ try:
+ return os.getcwd()
+ except SystemExit, e:
+ raise
+ except:
+ os.chdir("/")
+ return "/"
+getcwd()
+
+def abssymlink(symlink):
+ "This reads symlinks, resolving the relative symlinks, and returning the absolute."
+ mylink=os.readlink(symlink)
+ if mylink[0] != '/':
+ mydir=os.path.dirname(symlink)
+ mylink=mydir+"/"+mylink
+ return os.path.normpath(mylink)
+
+def suffix_array(array,suffix,doblanks=1):
+ """Appends a given suffix to each element in an Array/List/Tuple.
+ Returns a List."""
+ if type(array) not in [types.ListType, types.TupleType]:
+ raise TypeError, "List or Tuple expected. Got %s" % type(array)
+ newarray=[]
+ for x in array:
+ if x or doblanks:
+ newarray.append(x + suffix)
+ else:
+ newarray.append(x)
+ return newarray
+
+def prefix_array(array,prefix,doblanks=1):
+ """Prepends a given prefix to each element in an Array/List/Tuple.
+ Returns a List."""
+ if type(array) not in [types.ListType, types.TupleType]:
+ raise TypeError, "List or Tuple expected. Got %s" % type(array)
+ newarray=[]
+ for x in array:
+ if x or doblanks:
+ newarray.append(prefix + x)
+ else:
+ newarray.append(x)
+ return newarray
+
+def normalize_path(mypath):
+ newpath = os.path.normpath(mypath)
+ if len(newpath) > 1:
+ if newpath[:2] == "//":
+ newpath = newpath[1:]
+ return newpath
+
+dircache = {}
+cacheHit=0
+cacheMiss=0
+cacheStale=0
+def cacheddir(my_original_path, ignorecvs, ignorelist, EmptyOnError, followSymlinks=True):
+ global cacheHit,cacheMiss,cacheStale
+ mypath = normalize_path(my_original_path)
+ if dircache.has_key(mypath):
+ cacheHit += 1
+ cached_mtime, list, ftype = dircache[mypath]
+ else:
+ cacheMiss += 1
+ cached_mtime, list, ftype = -1, [], []
+ try:
+ pathstat = os.stat(mypath)
+ if stat.S_ISDIR(pathstat[stat.ST_MODE]):
+ mtime = pathstat[stat.ST_MTIME]
+ else:
+ raise Exception
+ except SystemExit, e:
+ raise
+ except:
+ if EmptyOnError:
+ return [], []
+ return None, None
+ if mtime != cached_mtime:
+ if dircache.has_key(mypath):
+ cacheStale += 1
+ list = os.listdir(mypath)
+ ftype = []
+ for x in list:
+ try:
+ if followSymlinks:
+ pathstat = os.stat(mypath+"/"+x)
+ else:
+ pathstat = os.lstat(mypath+"/"+x)
+
+ if stat.S_ISREG(pathstat[stat.ST_MODE]):
+ ftype.append(0)
+ elif stat.S_ISDIR(pathstat[stat.ST_MODE]):
+ ftype.append(1)
+ elif stat.S_ISLNK(pathstat[stat.ST_MODE]):
+ ftype.append(2)
+ else:
+ ftype.append(3)
+ except SystemExit, e:
+ raise
+ except:
+ ftype.append(3)
+ dircache[mypath] = mtime, list, ftype
+
+ ret_list = []
+ ret_ftype = []
+ for x in range(0, len(list)):
+ if(ignorecvs and (len(list[x]) > 2) and (list[x][:2]!=".#")):
+ ret_list.append(list[x])
+ ret_ftype.append(ftype[x])
+ elif (list[x] not in ignorelist):
+ ret_list.append(list[x])
+ ret_ftype.append(ftype[x])
+
+ writemsg("cacheddirStats: H:%d/M:%d/S:%d\n" % (cacheHit, cacheMiss, cacheStale),10)
+ return ret_list, ret_ftype
+
+
+def listdir(mypath, recursive=False, filesonly=False, ignorecvs=False, ignorelist=[], followSymlinks=True,
+ EmptyOnError=False):
+
+ list, ftype = cacheddir(mypath, ignorecvs, ignorelist, EmptyOnError, followSymlinks)
+
+ if list is None:
+ list=[]
+ if ftype is None:
+ ftype=[]
+
+ if not filesonly and not recursive:
+ return list
+
+ if recursive:
+ x=0
+ while x<len(ftype):
+ if ftype[x]==1 and not (ignorecvs and os.path.basename(list[x]) in ('CVS','.svn')):
+ l,f = cacheddir(mypath+"/"+list[x], ignorecvs, ignorelist, EmptyOnError,
+ followSymlinks)
+
+ l=l[:]
+ for y in range(0,len(l)):
+ l[y]=list[x]+"/"+l[y]
+ list=list+l
+ ftype=ftype+f
+ x+=1
+ if filesonly:
+ rlist=[]
+ for x in range(0,len(ftype)):
+ if ftype[x]==0:
+ rlist=rlist+[list[x]]
+ else:
+ rlist=list
+
+ return rlist
+
+starttime=long(time.time())
+features=[]
+
+def tokenize(mystring):
+ """breaks a string like 'foo? (bar) oni? (blah (blah))'
+ into embedded lists; returns None on paren mismatch"""
+
+ # This function is obsoleted.
+ # Use dep_parenreduce
+
+ newtokens=[]
+ curlist=newtokens
+ prevlists=[]
+ level=0
+ accum=""
+ for x in mystring:
+ if x=="(":
+ if accum:
+ curlist.append(accum)
+ accum=""
+ prevlists.append(curlist)
+ curlist=[]
+ level=level+1
+ elif x==")":
+ if accum:
+ curlist.append(accum)
+ accum=""
+ if level==0:
+ writemsg("!!! tokenizer: Unmatched left parenthesis in:\n'"+str(mystring)+"'\n")
+ return None
+ newlist=curlist
+ curlist=prevlists.pop()
+ curlist.append(newlist)
+ level=level-1
+ elif x in string.whitespace:
+ if accum:
+ curlist.append(accum)
+ accum=""
+ else:
+ accum=accum+x
+ if accum:
+ curlist.append(accum)
+ if (level!=0):
+ writemsg("!!! tokenizer: Exiting with unterminated parenthesis in:\n'"+str(mystring)+"'\n")
+ return None
+ return newtokens
+
+def flatten(mytokens):
+ """this function now turns a [1,[2,3]] list into
+ a [1,2,3] list and returns it."""
+ newlist=[]
+ for x in mytokens:
+ if type(x)==types.ListType:
+ newlist.extend(flatten(x))
+ else:
+ newlist.append(x)
+ return newlist
+
+#beautiful directed graph object
+
+class digraph:
+ def __init__(self):
+ self.dict={}
+ #okeys = keys, in order they were added (to optimize firstzero() ordering)
+ self.okeys=[]
+
+ def addnode(self,mykey,myparent):
+ if not self.dict.has_key(mykey):
+ self.okeys.append(mykey)
+ if myparent==None:
+ self.dict[mykey]=[0,[]]
+ else:
+ self.dict[mykey]=[0,[myparent]]
+ self.dict[myparent][0]=self.dict[myparent][0]+1
+ return
+ if myparent and (not myparent in self.dict[mykey][1]):
+ self.dict[mykey][1].append(myparent)
+ self.dict[myparent][0]=self.dict[myparent][0]+1
+
+ def delnode(self,mykey):
+ if not self.dict.has_key(mykey):
+ return
+ for x in self.dict[mykey][1]:
+ self.dict[x][0]=self.dict[x][0]-1
+ del self.dict[mykey]
+ while 1:
+ try:
+ self.okeys.remove(mykey)
+ except ValueError:
+ break
+
+ def allnodes(self):
+ "returns all nodes in the dictionary"
+ return self.dict.keys()
+
+ def firstzero(self):
+ "returns first node with zero references, or NULL if no such node exists"
+ for x in self.okeys:
+ if self.dict[x][0]==0:
+ return x
+ return None
+
+ def depth(self, mykey):
+ depth=0
+ while (self.dict[mykey][1]):
+ depth=depth+1
+ mykey=self.dict[mykey][1][0]
+ return depth
+
+ def allzeros(self):
+ "returns all nodes with zero references, or NULL if no such node exists"
+ zerolist = []
+ for x in self.dict.keys():
+ mys = string.split(x)
+ if mys[0] != "blocks" and self.dict[x][0]==0:
+ zerolist.append(x)
+ return zerolist
+
+ def hasallzeros(self):
+ "returns 0/1, Are all nodes zeros? 1 : 0"
+ zerolist = []
+ for x in self.dict.keys():
+ if self.dict[x][0]!=0:
+ return 0
+ return 1
+
+ def empty(self):
+ if len(self.dict)==0:
+ return 1
+ return 0
+
+ def hasnode(self,mynode):
+ return self.dict.has_key(mynode)
+
+ def copy(self):
+ mygraph=digraph()
+ for x in self.dict.keys():
+ mygraph.dict[x]=self.dict[x][:]
+ mygraph.okeys=self.okeys[:]
+ return mygraph
+
+# valid end of version components; integers specify offset from release version
+# pre=prerelease, p=patchlevel (should always be followed by an int), rc=release candidate
+# all but _p (where it is required) can be followed by an optional trailing integer
+
+endversion={"pre":-2,"p":0,"alpha":-4,"beta":-3,"rc":-1}
+# as there's no reliable way to set {}.keys() order
+# netversion_keys will be used instead of endversion.keys
+# to have fixed search order, so that "pre" is checked
+# before "p"
+endversion_keys = ["pre", "p", "alpha", "beta", "rc"]
+
+#parse /etc/env.d and generate /etc/profile.env
+
+def env_update(makelinks=1):
+ global root
+ if not os.path.exists(root+"etc/env.d"):
+ prevmask=os.umask(0)
+ os.makedirs(root+"etc/env.d",0755)
+ os.umask(prevmask)
+ fns=listdir(root+"etc/env.d",EmptyOnError=1)
+ fns.sort()
+ pos=0
+ while (pos<len(fns)):
+ if len(fns[pos])<=2:
+ del fns[pos]
+ continue
+ if (fns[pos][0] not in string.digits) or (fns[pos][1] not in string.digits):
+ del fns[pos]
+ continue
+ pos=pos+1
+
+ specials={
+ "KDEDIRS":[],"PATH":[],"CLASSPATH":[],"LDPATH":[],"MANPATH":[],
+ "INFODIR":[],"INFOPATH":[],"ROOTPATH":[],"CONFIG_PROTECT":[],
+ "CONFIG_PROTECT_MASK":[],"PRELINK_PATH":[],"PRELINK_PATH_MASK":[],
+ "PYTHONPATH":[], "ADA_INCLUDE_PATH":[], "ADA_OBJECTS_PATH":[]
+ }
+ colon_separated = [
+ "ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH",
+ "LDPATH", "MANPATH",
+ "PATH", "PRELINK_PATH",
+ "PRELINK_PATH_MASK", "PYTHON_PATH"
+ ]
+
+ env={}
+
+ for x in fns:
+ # don't process backup files
+ if x[-1]=='~' or x[-4:]==".bak":
+ continue
+ myconfig=getconfig(root+"etc/env.d/"+x)
+ if myconfig==None:
+ writemsg("!!! Parsing error in "+str(root)+"etc/env.d/"+str(x)+"\n")
+ #parse error
+ continue
+ # process PATH, CLASSPATH, LDPATH
+ for myspec in specials.keys():
+ if myconfig.has_key(myspec):
+ if myspec in colon_separated:
+ specials[myspec].extend(string.split(varexpand(myconfig[myspec]),":"))
+ else:
+ specials[myspec].append(varexpand(myconfig[myspec]))
+ del myconfig[myspec]
+ # process all other variables
+ for myenv in myconfig.keys():
+ env[myenv]=varexpand(myconfig[myenv])
+
+ if os.path.exists(root+"etc/ld.so.conf"):
+ myld=open(root+"etc/ld.so.conf")
+ myldlines=myld.readlines()
+ myld.close()
+ oldld=[]
+ for x in myldlines:
+ #each line has at least one char (a newline)
+ if x[0]=="#":
+ continue
+ oldld.append(x[:-1])
+ # os.rename(root+"etc/ld.so.conf",root+"etc/ld.so.conf.bak")
+ # Where is the new ld.so.conf generated? (achim)
+ else:
+ oldld=None
+
+ ld_cache_update=False
+ if os.environ.has_key("PORTAGE_CALLER") and \
+ os.environ["PORTAGE_CALLER"] == "env-update":
+ ld_cache_update = True
+
+ newld=specials["LDPATH"]
+ if (oldld!=newld):
+ #ld.so.conf needs updating and ldconfig needs to be run
+ myfd=open(root+"etc/ld.so.conf","w")
+ myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n")
+ myfd.write("# contents of /etc/env.d directory\n")
+ for x in specials["LDPATH"]:
+ myfd.write(x+"\n")
+ myfd.close()
+ ld_cache_update=True
+
+ # Update prelink.conf if we are prelink-enabled
+ if prelink_capable:
+ newprelink=open(root+"etc/prelink.conf","w")
+ newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n")
+ newprelink.write("# contents of /etc/env.d directory\n")
+
+ for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]:
+ newprelink.write("-l "+x+"\n");
+ for x in specials["LDPATH"]+specials["PATH"]+specials["PRELINK_PATH"]:
+ if not x:
+ continue
+ if x[-1]!='/':
+ x=x+"/"
+ plmasked=0
+ for y in specials["PRELINK_PATH_MASK"]:
+ if not y:
+ continue
+ if y[-1]!='/':
+ y=y+"/"
+ if y==x[0:len(y)]:
+ plmasked=1
+ break
+ if not plmasked:
+ newprelink.write("-h "+x+"\n")
+ for x in specials["PRELINK_PATH_MASK"]:
+ newprelink.write("-b "+x+"\n")
+ newprelink.close()
+
+ if not mtimedb.has_key("ldpath"):
+ mtimedb["ldpath"]={}
+
+ for x in specials["LDPATH"]+['/usr/lib','/lib']:
+ try:
+ newldpathtime=os.stat(x)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except:
+ newldpathtime=0
+ if mtimedb["ldpath"].has_key(x):
+ if mtimedb["ldpath"][x]==newldpathtime:
+ pass
+ else:
+ mtimedb["ldpath"][x]=newldpathtime
+ ld_cache_update=True
+ else:
+ mtimedb["ldpath"][x]=newldpathtime
+ ld_cache_update=True
+
+ if (ld_cache_update or makelinks):
+ # We can't update links if we haven't cleaned other versions first, as
+ # an older package installed ON TOP of a newer version will cause ldconfig
+ # to overwrite the symlinks we just made. -X means no links. After 'clean'
+ # we can safely create links.
+ writemsg(">>> Regenerating "+str(root)+"etc/ld.so.cache...\n")
+ if makelinks:
+ commands.getstatusoutput("cd / ; /sbin/ldconfig -r "+root)
+ else:
+ commands.getstatusoutput("cd / ; /sbin/ldconfig -X -r "+root)
+
+ del specials["LDPATH"]
+
+ penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
+ penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
+ cenvnotice = penvnotice[:]
+ penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
+ cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"
+
+ #create /etc/profile.env for bash support
+ outfile=open(root+"/etc/profile.env","w")
+ outfile.write(penvnotice)
+
+ for path in specials.keys():
+ if len(specials[path])==0:
+ continue
+ outstring="export "+path+"='"
+ if path in ["CONFIG_PROTECT","CONFIG_PROTECT_MASK"]:
+ for x in specials[path][:-1]:
+ outstring += x+" "
+ else:
+ for x in specials[path][:-1]:
+ outstring=outstring+x+":"
+ outstring=outstring+specials[path][-1]+"'"
+ outfile.write(outstring+"\n")
+
+ #create /etc/profile.env
+ for x in env.keys():
+ if type(env[x])!=types.StringType:
+ continue
+ outfile.write("export "+x+"='"+env[x]+"'\n")
+ outfile.close()
+
+ #create /etc/csh.env for (t)csh support
+ outfile=open(root+"/etc/csh.env","w")
+ outfile.write(cenvnotice)
+
+ for path in specials.keys():
+ if len(specials[path])==0:
+ continue
+ outstring="setenv "+path+" '"
+ if path in ["CONFIG_PROTECT","CONFIG_PROTECT_MASK"]:
+ for x in specials[path][:-1]:
+ outstring += x+" "
+ else:
+ for x in specials[path][:-1]:
+ outstring=outstring+x+":"
+ outstring=outstring+specials[path][-1]+"'"
+ outfile.write(outstring+"\n")
+ #get it out of the way
+ del specials[path]
+
+ #create /etc/csh.env
+ for x in env.keys():
+ if type(env[x])!=types.StringType:
+ continue
+ outfile.write("setenv "+x+" '"+env[x]+"'\n")
+ outfile.close()
+ if os.path.exists(DEPSCAN_SH_BINARY):
+ spawn(DEPSCAN_SH_BINARY,settings,free=1)
+
+def new_protect_filename(mydest, newmd5=None):
+ """Resolves a config-protect filename for merging, optionally
+ using the last filename if the md5 matches.
+ (dest,md5) ==> 'string' --- path_to_target_filename
+ (dest) ==> ('next', 'highest') --- next_target and most-recent_target
+ """
+
+ # config protection filename format:
+ # ._cfg0000_foo
+ # 0123456789012
+ prot_num=-1
+ last_pfile=""
+
+ if (len(mydest) == 0):
+ raise ValueError, "Empty path provided where a filename is required"
+ if (mydest[-1]=="/"): # XXX add better directory checking
+ raise ValueError, "Directory provided but this function requires a filename"
+ if not os.path.exists(mydest):
+ return mydest
+
+ real_filename = os.path.basename(mydest)
+ real_dirname = os.path.dirname(mydest)
+ for pfile in listdir(real_dirname):
+ if pfile[0:5] != "._cfg":
+ continue
+ if pfile[10:] != real_filename:
+ continue
+ try:
+ new_prot_num = int(pfile[5:9])
+ if new_prot_num > prot_num:
+ prot_num = new_prot_num
+ last_pfile = pfile
+ except SystemExit, e:
+ raise
+ except:
+ continue
+ prot_num = prot_num + 1
+
+ new_pfile = os.path.normpath(real_dirname+"/._cfg"+string.zfill(prot_num,4)+"_"+real_filename)
+ old_pfile = os.path.normpath(real_dirname+"/"+last_pfile)
+ if last_pfile and newmd5:
+ if portage_checksum.perform_md5(real_dirname+"/"+last_pfile) == newmd5:
+ return old_pfile
+ else:
+ return new_pfile
+ elif newmd5:
+ return new_pfile
+ else:
+ return (new_pfile, old_pfile)
+
+#XXX: These two are now implemented in portage_util.py but are needed here
+#XXX: until the isvalidatom() dependency is sorted out.
+
+def grabdict_package(myfilename,juststrings=0):
+ pkgs=grabdict(myfilename, juststrings=juststrings, empty=1)
+ for x in pkgs.keys():
+ if not isvalidatom(x):
+ del(pkgs[x])
+ writemsg("--- Invalid atom in %s: %s\n" % (myfilename, x))
+ return pkgs
+
+def grabfile_package(myfilename,compatlevel=0):
+ pkgs=grabfile(myfilename,compatlevel)
+ for x in range(len(pkgs)-1,-1,-1):
+ pkg = pkgs[x]
+ if pkg[0] == "-":
+ pkg = pkg[1:]
+ if pkg[0] == "*":
+ pkg = pkg[1:]
+ if not isvalidatom(pkg):
+ writemsg("--- Invalid atom in %s: %s\n" % (myfilename, pkgs[x]))
+ del(pkgs[x])
+ return pkgs
+
+# returns a tuple. (version[string], error[string])
+# They are pretty much mutually exclusive.
+# Either version is a string and error is none, or
+# version is None and error is a string
+#
+def ExtractKernelVersion(base_dir):
+ lines = []
+ pathname = os.path.join(base_dir, 'Makefile')
+ try:
+ f = open(pathname, 'r')
+ except OSError, details:
+ return (None, str(details))
+ except IOError, details:
+ return (None, str(details))
+
+ try:
+ for i in range(4):
+ lines.append(f.readline())
+ except OSError, details:
+ return (None, str(details))
+ except IOError, details:
+ return (None, str(details))
+
+ lines = map(string.strip, lines)
+
+ version = ''
+
+ #XXX: The following code relies on the ordering of vars within the Makefile
+ for line in lines:
+ # split on the '=' then remove annoying whitespace
+ items = string.split(line, '=')
+ items = map(string.strip, items)
+ if items[0] == 'VERSION' or \
+ items[0] == 'PATCHLEVEL':
+ version += items[1]
+ version += "."
+ elif items[0] == 'SUBLEVEL':
+ version += items[1]
+ elif items[0] == 'EXTRAVERSION' and \
+ items[-1] != items[0]:
+ version += items[1]
+
+ # Grab a list of files named localversion* and sort them
+ localversions = os.listdir(base_dir)
+ for x in range(len(localversions)-1,-1,-1):
+ if localversions[x][:12] != "localversion":
+ del localversions[x]
+ localversions.sort()
+
+ # Append the contents of each to the version string, stripping ALL whitespace
+ for lv in localversions:
+ version += string.join(string.split(string.join(grabfile(base_dir+"/"+lv))), "")
+
+ # Check the .config for a CONFIG_LOCALVERSION and append that too, also stripping whitespace
+ kernelconfig = getconfig(base_dir+"/.config")
+ if kernelconfig and kernelconfig.has_key("CONFIG_LOCALVERSION"):
+ version += string.join(string.split(kernelconfig["CONFIG_LOCALVERSION"]), "")
+
+ return (version,None)
+
+
+autouse_val = None
+def autouse(myvartree,use_cache=1):
+ "returns set of USE variables auto-enabled due to packages being installed"
+ global usedefaults, autouse_val
+ if autouse_val is not None:
+ return autouse_val
+ if profiledir==None:
+ autouse_val = ""
+ return ""
+ myusevars=""
+ for myuse in usedefaults:
+ dep_met = True
+ for mydep in usedefaults[myuse]:
+ if not myvartree.dep_match(mydep,use_cache=True):
+ dep_met = False
+ break
+ if dep_met:
+ myusevars += " "+myuse
+ autouse_val = myusevars
+ return myusevars
+
+def check_config_instance(test):
+ if not test or (str(test.__class__) != 'portage.config'):
+ raise TypeError, "Invalid type for config object: %s" % test.__class__
+
+class config:
+ def __init__(self, clone=None, mycpv=None, config_profile_path=None, config_incrementals=None):
+
+ self.already_in_regenerate = 0
+
+ self.locked = 0
+ self.mycpv = None
+ self.puse = []
+ self.modifiedkeys = []
+
+ self.virtuals = {}
+ self.v_count = 0
+
+ # Virtuals obtained from the vartree
+ self.treeVirtuals = {}
+ # Virtuals by user specification. Includes negatives.
+ self.userVirtuals = {}
+ # Virtual negatives from user specifications.
+ self.negVirtuals = {}
+
+ self.user_profile_dir = None
+
+ if clone:
+ self.incrementals = copy.deepcopy(clone.incrementals)
+ self.profile_path = copy.deepcopy(clone.profile_path)
+ self.user_profile_dir = copy.deepcopy(clone.user_profile_dir)
+
+ self.module_priority = copy.deepcopy(clone.module_priority)
+ self.modules = copy.deepcopy(clone.modules)
+
+ self.depcachedir = copy.deepcopy(clone.depcachedir)
+
+ self.packages = copy.deepcopy(clone.packages)
+ self.virtuals = copy.deepcopy(clone.virtuals)
+
+ self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
+ self.userVirtuals = copy.deepcopy(clone.userVirtuals)
+ self.negVirtuals = copy.deepcopy(clone.negVirtuals)
+
+ self.use_defs = copy.deepcopy(clone.use_defs)
+ self.usemask = copy.deepcopy(clone.usemask)
+
+ self.configlist = copy.deepcopy(clone.configlist)
+ self.configlist[-1] = os.environ.copy()
+ self.configdict = { "globals": self.configlist[0],
+ "defaults": self.configlist[1],
+ "conf": self.configlist[2],
+ "pkg": self.configlist[3],
+ "auto": self.configlist[4],
+ "backupenv": self.configlist[5],
+ "env": self.configlist[6] }
+ self.profiles = copy.deepcopy(clone.profiles)
+ self.backupenv = copy.deepcopy(clone.backupenv)
+ self.pusedict = copy.deepcopy(clone.pusedict)
+ self.categories = copy.deepcopy(clone.categories)
+ self.pkeywordsdict = copy.deepcopy(clone.pkeywordsdict)
+ self.pmaskdict = copy.deepcopy(clone.pmaskdict)
+ self.punmaskdict = copy.deepcopy(clone.punmaskdict)
+ self.prevmaskdict = copy.deepcopy(clone.prevmaskdict)
+ self.pprovideddict = copy.deepcopy(clone.pprovideddict)
+ self.lookuplist = copy.deepcopy(clone.lookuplist)
+ self.uvlist = copy.deepcopy(clone.uvlist)
+ self.dirVirtuals = copy.deepcopy(clone.dirVirtuals)
+ self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
+ else:
+ self.depcachedir = DEPCACHE_PATH
+
+ if not config_profile_path:
+ global profiledir
+ writemsg("config_profile_path not specified to class config\n")
+ self.profile_path = profiledir[:]
+ else:
+ self.profile_path = config_profile_path[:]
+
+ if not config_incrementals:
+ writemsg("incrementals not specified to class config\n")
+ self.incrementals = copy.deepcopy(portage_const.INCREMENTALS)
+ else:
+ self.incrementals = copy.deepcopy(config_incrementals)
+
+ self.module_priority = ["user","default"]
+ self.modules = {}
+ self.modules["user"] = getconfig(MODULES_FILE_PATH)
+ if self.modules["user"] == None:
+ self.modules["user"] = {}
+ self.modules["default"] = {
+ "portdbapi.metadbmodule": "portage_db_flat.database",
+ "portdbapi.auxdbmodule": "portage_db_flat.database",
+ "eclass_cache.dbmodule": "portage_db_cpickle.database",
+ }
+
+ self.usemask=[]
+ self.configlist=[]
+ self.backupenv={}
+ # back up our incremental variables:
+ self.configdict={}
+ # configlist will contain: [ globals, defaults, conf, pkg, auto, backupenv (incrementals), origenv ]
+
+ # The symlink might not exist or might not be a symlink.
+ try:
+ self.profiles=[abssymlink(self.profile_path)]
+ except SystemExit, e:
+ raise
+ except:
+ self.profiles=[self.profile_path]
+
+ mypath = self.profiles[0]
+ while os.path.exists(mypath+"/parent"):
+ mypath = os.path.normpath(mypath+"///"+grabfile(mypath+"/parent")[0])
+ if os.path.exists(mypath):
+ self.profiles.insert(0,mypath)
+
+ if os.environ.has_key("PORTAGE_CALLER") and os.environ["PORTAGE_CALLER"] == "repoman":
+ pass
+ else:
+ # XXX: This should depend on ROOT?
+ if os.path.exists("/"+CUSTOM_PROFILE_PATH):
+ self.user_profile_dir = os.path.normpath("/"+"///"+CUSTOM_PROFILE_PATH)
+ self.profiles.append(self.user_profile_dir[:])
+
+ self.packages_list = grab_multiple("packages", self.profiles, grabfile_package)
+ self.packages = stack_lists(self.packages_list, incremental=1)
+ del self.packages_list
+ #self.packages = grab_stacked("packages", self.profiles, grabfile, incremental_lines=1)
+
+ # revmaskdict
+ self.prevmaskdict={}
+ for x in self.packages:
+ mycatpkg=dep_getkey(x)
+ if not self.prevmaskdict.has_key(mycatpkg):
+ self.prevmaskdict[mycatpkg]=[x]
+ else:
+ self.prevmaskdict[mycatpkg].append(x)
+
+ # get profile-masked use flags -- INCREMENTAL Child over parent
+ usemask_lists = grab_multiple("use.mask", self.profiles, grabfile)
+ self.usemask = stack_lists(usemask_lists, incremental=True)
+ del usemask_lists
+ use_defs_lists = grab_multiple("use.defaults", self.profiles, grabdict)
+ self.use_defs = stack_dictlist(use_defs_lists, incremental=True)
+ del use_defs_lists
+
+ try:
+ mygcfg_dlists = grab_multiple("make.globals", self.profiles+["/etc"], getconfig)
+ self.mygcfg = stack_dicts(mygcfg_dlists, incrementals=portage_const.INCREMENTALS, ignore_none=1)
+
+ if self.mygcfg == None:
+ self.mygcfg = {}
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! %s\n" % (e))
+ writemsg("!!! Incorrect multiline literals can cause this. Do not use them.\n")
+ writemsg("!!! Errors in this file should be reported on bugs.gentoo.org.\n")
+ sys.exit(1)
+ self.configlist.append(self.mygcfg)
+ self.configdict["globals"]=self.configlist[-1]
+
+ self.mygcfg = {}
+ if self.profiles:
+ try:
+ mygcfg_dlists = grab_multiple("make.defaults", self.profiles, getconfig)
+ self.mygcfg = stack_dicts(mygcfg_dlists, incrementals=portage_const.INCREMENTALS, ignore_none=1)
+ #self.mygcfg = grab_stacked("make.defaults", self.profiles, getconfig)
+ if self.mygcfg == None:
+ self.mygcfg = {}
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! %s\n" % (e))
+ writemsg("!!! 'rm -Rf /usr/portage/profiles; emerge sync' may fix this. If it does\n")
+ writemsg("!!! not then please report this to bugs.gentoo.org and, if possible, a dev\n")
+ writemsg("!!! on #gentoo (irc.freenode.org)\n")
+ sys.exit(1)
+ self.configlist.append(self.mygcfg)
+ self.configdict["defaults"]=self.configlist[-1]
+
+ try:
+ # XXX: Should depend on root?
+ self.mygcfg=getconfig("/"+MAKE_CONF_FILE,allow_sourcing=True)
+ if self.mygcfg == None:
+ self.mygcfg = {}
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! %s\n" % (e))
+ writemsg("!!! Incorrect multiline literals can cause this. Do not use them.\n")
+ sys.exit(1)
+
+
+ self.configlist.append(self.mygcfg)
+ self.configdict["conf"]=self.configlist[-1]
+
+ self.configlist.append({})
+ self.configdict["pkg"]=self.configlist[-1]
+
+ #auto-use:
+ self.configlist.append({})
+ self.configdict["auto"]=self.configlist[-1]
+
+ #backup-env (for recording our calculated incremental variables:)
+ self.backupenv = os.environ.copy()
+ self.configlist.append(self.backupenv) # XXX Why though?
+ self.configdict["backupenv"]=self.configlist[-1]
+
+ self.configlist.append(os.environ.copy())
+ self.configdict["env"]=self.configlist[-1]
+
+
+ # make lookuplist for loading package.*
+ self.lookuplist=self.configlist[:]
+ self.lookuplist.reverse()
+
+ archlist = grabfile(self["PORTDIR"]+"/profiles/arch.list")
+ self.configdict["conf"]["PORTAGE_ARCHLIST"] = string.join(archlist)
+
+ if os.environ.get("PORTAGE_CALLER","") == "repoman":
+ # repoman shouldn't use local settings.
+ locations = [self["PORTDIR"] + "/profiles"]
+ self.pusedict = {}
+ self.pkeywordsdict = {}
+ self.punmaskdict = {}
+ else:
+ locations = [self["PORTDIR"] + "/profiles", USER_CONFIG_PATH]
+
+ pusedict=grabdict_package(USER_CONFIG_PATH+"/package.use")
+ self.pusedict = {}
+ for key in pusedict.keys():
+ cp = dep_getkey(key)
+ if not self.pusedict.has_key(cp):
+ self.pusedict[cp] = {}
+ self.pusedict[cp][key] = pusedict[key]
+
+ #package.keywords
+ pkgdict=grabdict_package(USER_CONFIG_PATH+"/package.keywords")
+ self.pkeywordsdict = {}
+ for key in pkgdict.keys():
+ # default to ~arch if no specific keyword is given
+ if not pkgdict[key]:
+ mykeywordlist = []
+ if self.configdict["defaults"] and self.configdict["defaults"].has_key("ACCEPT_KEYWORDS"):
+ groups = self.configdict["defaults"]["ACCEPT_KEYWORDS"].split()
+ else:
+ groups = []
+ for keyword in groups:
+ if not keyword[0] in "~-":
+ mykeywordlist.append("~"+keyword)
+ pkgdict[key] = mykeywordlist
+ cp = dep_getkey(key)
+ if not self.pkeywordsdict.has_key(cp):
+ self.pkeywordsdict[cp] = {}
+ self.pkeywordsdict[cp][key] = pkgdict[key]
+
+ #package.unmask
+ pkgunmasklines = grabfile_package(USER_CONFIG_PATH+"/package.unmask")
+ self.punmaskdict = {}
+ for x in pkgunmasklines:
+ mycatpkg=dep_getkey(x)
+ if self.punmaskdict.has_key(mycatpkg):
+ self.punmaskdict[mycatpkg].append(x)
+ else:
+ self.punmaskdict[mycatpkg]=[x]
+
+ #getting categories from an external file now
+ categories = grab_multiple("categories", locations, grabfile)
+ self.categories = stack_lists(categories, incremental=1)
+ del categories
+
+ # get virtuals -- needs categories
+ self.loadVirtuals('/')
+
+ #package.mask
+ pkgmasklines = grab_multiple("package.mask", self.profiles + locations, grabfile_package)
+ pkgmasklines = stack_lists(pkgmasklines, incremental=1)
+
+ self.pmaskdict = {}
+ for x in pkgmasklines:
+ mycatpkg=dep_getkey(x)
+ if self.pmaskdict.has_key(mycatpkg):
+ self.pmaskdict[mycatpkg].append(x)
+ else:
+ self.pmaskdict[mycatpkg]=[x]
+
+ pkgprovidedlines = grab_multiple("package.provided", self.profiles, grabfile)
+ pkgprovidedlines = stack_lists(pkgprovidedlines, incremental=1)
+ for x in range(len(pkgprovidedlines)-1, -1, -1):
+ cpvr = catpkgsplit(pkgprovidedlines[x])
+ if not cpvr or cpvr[0] == "null":
+ writemsg("Invalid package name in package.provided: "+pkgprovidedlines[x]+"\n")
+ del pkgprovidedlines[x]
+
+ self.pprovideddict = {}
+ for x in pkgprovidedlines:
+ cpv=catpkgsplit(x)
+ if not x:
+ continue
+ mycatpkg=dep_getkey(x)
+ if self.pprovideddict.has_key(mycatpkg):
+ self.pprovideddict[mycatpkg].append(x)
+ else:
+ self.pprovideddict[mycatpkg]=[x]
+
+ self.lookuplist=self.configlist[:]
+ self.lookuplist.reverse()
+
+ useorder=self["USE_ORDER"]
+ if not useorder:
+ # reasonable defaults; this is important as without USE_ORDER,
+ # USE will always be "" (nothing set)!
+ useorder="env:pkg:conf:auto:defaults"
+ useordersplit=useorder.split(":")
+
+ self.uvlist=[]
+ for x in useordersplit:
+ if self.configdict.has_key(x):
+ if "PKGUSE" in self.configdict[x].keys():
+ del self.configdict[x]["PKGUSE"] # Delete PkgUse, Not legal to set.
+ #prepend db to list to get correct order
+ self.uvlist[0:0]=[self.configdict[x]]
+
+ self.configdict["env"]["PORTAGE_GID"]=str(portage_gid)
+ self.backupenv["PORTAGE_GID"]=str(portage_gid)
+
+ if self.has_key("PORT_LOGDIR") and not self["PORT_LOGDIR"]:
+ # port_logdir is defined, but empty. this causes a traceback in doebuild.
+ writemsg(yellow("!!!")+" PORT_LOGDIR was defined, but set to nothing.\n")
+ writemsg(yellow("!!!")+" Disabling it. Please set it to a non null value.\n")
+ del self["PORT_LOGDIR"]
+
+ if self["PORTAGE_CACHEDIR"]:
+ # XXX: Deprecated -- April 15 -- NJ
+ writemsg(yellow(">>> PORTAGE_CACHEDIR has been deprecated!")+"\n")
+ writemsg(">>> Please use PORTAGE_DEPCACHEDIR instead.\n")
+ self.depcachedir = self["PORTAGE_CACHEDIR"]
+ del self["PORTAGE_CACHEDIR"]
+
+ if self["PORTAGE_DEPCACHEDIR"]:
+ #the auxcache is the only /var/cache/edb/ entry that stays at / even when "root" changes.
+ # XXX: Could move with a CHROOT functionality addition.
+ self.depcachedir = self["PORTAGE_DEPCACHEDIR"]
+ del self["PORTAGE_DEPCACHEDIR"]
+
+ overlays = string.split(self["PORTDIR_OVERLAY"])
+ if overlays:
+ new_ov=[]
+ for ov in overlays:
+ ov=os.path.normpath(ov)
+ if os.path.isdir(ov):
+ new_ov.append(ov)
+ else:
+ writemsg(red("!!! Invalid PORTDIR_OVERLAY (not a dir): "+ov+"\n"))
+ self["PORTDIR_OVERLAY"] = string.join(new_ov)
+ self.backup_changes("PORTDIR_OVERLAY")
+
+ self.regenerate()
+
+ self.features = portage_util.unique_array(self["FEATURES"].split())
+
+ #XXX: Should this be temporary? Is it possible at all to have a default?
+ if "gpg" in self.features:
+ if not os.path.exists(self["PORTAGE_GPG_DIR"]) or not os.path.isdir(self["PORTAGE_GPG_DIR"]):
+ writemsg("PORTAGE_GPG_DIR is invalid. Removing gpg from FEATURES.\n")
+ self.features.remove("gpg")
+
+ if "maketest" in self.features and "test" not in self.features:
+ self.features.append("test")
+
+ if not portage_exec.sandbox_capable and ("sandbox" in self.features or "usersandbox" in self.features):
+ writemsg(red("!!! Problem with sandbox binary. Disabling...\n\n"))
+ if "sandbox" in self.features:
+ self.features.remove("sandbox")
+ if "usersandbox" in self.features:
+ self.features.remove("usersandbox")
+
+ self.features.sort()
+ self["FEATURES"] = " ".join(["-*"]+self.features)
+ self.backup_changes("FEATURES")
+
+ if not len(self["CBUILD"]):
+ self["CBUILD"] = self["CHOST"]
+ self.backup_changes("CBUILD")
+
+ if mycpv:
+ self.setcpv(mycpv)
+
+ def loadVirtuals(self,root):
+ self.virtuals = self.getvirtuals(root)
+
+ def load_best_module(self,property_string):
+ best_mod = best_from_dict(property_string,self.modules,self.module_priority)
+ return load_mod(best_mod)
+
+ def lock(self):
+ self.locked = 1
+
+ def unlock(self):
+ self.locked = 0
+
+ def modifying(self):
+ if self.locked:
+ raise Exception, "Configuration is locked."
+
+ def backup_changes(self,key=None):
+ if key and self.configdict["env"].has_key(key):
+ self.backupenv[key] = copy.deepcopy(self.configdict["env"][key])
+ else:
+ raise KeyError, "No such key defined in environment: %s" % key
+
+ def reset(self,keeping_pkg=0,use_cache=1):
+ "reset environment to original settings"
+ for x in self.configlist[-1].keys():
+ if x not in self.backupenv.keys():
+ del self.configlist[-1][x]
+
+ self.configdict["env"].update(self.backupenv)
+
+ self.modifiedkeys = []
+ if not keeping_pkg:
+ self.puse = ""
+ self.configdict["pkg"].clear()
+ self.regenerate(use_cache=use_cache)
+
+ def load_infodir(self,infodir):
+ if self.configdict.has_key("pkg"):
+ for x in self.configdict["pkg"].keys():
+ del self.configdict["pkg"][x]
+ else:
+ writemsg("No pkg setup for settings instance?\n")
+ sys.exit(17)
+
+ if os.path.exists(infodir):
+ if os.path.exists(infodir+"/environment"):
+ self.configdict["pkg"]["PORT_ENV_FILE"] = infodir+"/environment"
+
+ myre = re.compile('^[A-Z]+$')
+ for filename in listdir(infodir,filesonly=1,EmptyOnError=1):
+ if myre.match(filename):
+ try:
+ mydata = string.strip(open(infodir+"/"+filename).read())
+ if len(mydata)<2048:
+ if filename == "USE":
+ self.configdict["pkg"][filename] = "-* "+mydata
+ else:
+ self.configdict["pkg"][filename] = mydata
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("!!! Unable to read file: %s\n" % infodir+"/"+filename)
+ pass
+ return 1
+ return 0
+
+ def setcpv(self,mycpv,use_cache=1):
+ self.modifying()
+ self.mycpv = mycpv
+ cp = dep_getkey(mycpv)
+ newpuse = ""
+ if self.pusedict.has_key(cp):
+ self.pusekey = best_match_to_list(self.mycpv, self.pusedict[cp].keys())
+ if self.pusekey:
+ newpuse = string.join(self.pusedict[cp][self.pusekey])
+ if newpuse == self.puse:
+ return
+ self.puse = newpuse
+ self.configdict["pkg"]["PKGUSE"] = self.puse[:] # For saving to PUSE file
+ self.configdict["pkg"]["USE"] = self.puse[:] # this gets appended to USE
+ self.reset(keeping_pkg=1,use_cache=use_cache)
+
+ def setinst(self,mycpv,mydbapi):
+ # Grab the virtuals this package provides and add them into the tree virtuals.
+ provides = mydbapi.aux_get(mycpv, ["PROVIDE"])[0]
+ if isinstance(mydbapi, portdbapi):
+ myuse = self["USE"]
+ else:
+ myuse = mydbapi.aux_get(mycpv, ["USE"])[0]
+ virts = flatten(portage_dep.use_reduce(portage_dep.paren_reduce(provides), uselist=myuse.split()))
+
+ cp = dep_getkey(mycpv)
+ for virt in virts:
+ virt = dep_getkey(virt)
+ if not self.treeVirtuals.has_key(virt):
+ self.treeVirtuals[virt] = []
+ # XXX: Is this bad? -- It's a permanent modification
+ self.treeVirtuals[virt] = portage_util.unique_array(self.treeVirtuals[virt]+[cp])
+
+ self.virtuals = self.__getvirtuals_compile()
+
+
+ def regenerate(self,useonly=0,use_cache=1):
+ global usesplit,profiledir
+
+ if self.already_in_regenerate:
+ # XXX: THIS REALLY NEEDS TO GET FIXED. autouse() loops.
+ writemsg("!!! Looping in regenerate.\n",1)
+ return
+ else:
+ self.already_in_regenerate = 1
+
+ if useonly:
+ myincrementals=["USE"]
+ else:
+ myincrementals=portage_const.INCREMENTALS
+ for mykey in myincrementals:
+ if mykey=="USE":
+ mydbs=self.uvlist
+ # XXX Global usage of db... Needs to go away somehow.
+ if db.has_key(root) and db[root].has_key("vartree"):
+ self.configdict["auto"]["USE"]=autouse(db[root]["vartree"],use_cache=use_cache)
+ else:
+ self.configdict["auto"]["USE"]=""
+ else:
+ mydbs=self.configlist[:-1]
+
+ myflags=[]
+ for curdb in mydbs:
+ if not curdb.has_key(mykey):
+ continue
+ #variables are already expanded
+ mysplit=curdb[mykey].split()
+
+ for x in mysplit:
+ if x=="-*":
+ # "-*" is a special "minus" var that means "unset all settings".
+ # so USE="-* gnome" will have *just* gnome enabled.
+ myflags=[]
+ continue
+
+ if x[0]=="+":
+ # Not legal. People assume too much. Complain.
+ writemsg(red("USE flags should not start with a '+': %s\n" % x))
+ x=x[1:]
+
+ if (x[0]=="-"):
+ if (x[1:] in myflags):
+ # Unset/Remove it.
+ del myflags[myflags.index(x[1:])]
+ continue
+
+ # We got here, so add it now.
+ if x not in myflags:
+ myflags.append(x)
+
+ myflags.sort()
+ #store setting in last element of configlist, the original environment:
+ self.configlist[-1][mykey]=string.join(myflags," ")
+ del myflags
+
+ #cache split-up USE var in a global
+ usesplit=[]
+
+ for x in string.split(self.configlist[-1]["USE"]):
+ if x not in self.usemask:
+ usesplit.append(x)
+
+ if self.has_key("USE_EXPAND"):
+ for var in string.split(self["USE_EXPAND"]):
+ if self.has_key(var):
+ for x in string.split(self[var]):
+ mystr = string.lower(var)+"_"+x
+ if mystr not in usesplit:
+ usesplit.append(mystr)
+
+ # Pre-Pend ARCH variable to USE settings so '-*' in env doesn't kill arch.
+ if self.configdict["defaults"].has_key("ARCH"):
+ if self.configdict["defaults"]["ARCH"]:
+ if self.configdict["defaults"]["ARCH"] not in usesplit:
+ usesplit.insert(0,self.configdict["defaults"]["ARCH"])
+
+ self.configlist[-1]["USE"]=string.join(usesplit," ")
+
+ self.already_in_regenerate = 0
+
+ def getvirtuals(self, myroot):
+ myvirts = {}
+
+ # This breaks catalyst/portage when setting to a fresh/empty root.
+ # Virtuals cannot be calculated because there is nothing to work
+ # from. So the only ROOT prefixed dir should be local configs.
+ #myvirtdirs = prefix_array(self.profiles,myroot+"/")
+ myvirtdirs = copy.deepcopy(self.profiles)
+ while self.user_profile_dir in myvirtdirs:
+ myvirtdirs.remove(self.user_profile_dir)
+
+
+ # Rules
+ # R1: Collapse profile virtuals
+ # R2: Extract user-negatives.
+ # R3: Collapse user-virtuals.
+ # R4: Apply user negatives to all except user settings.
+
+ # Order of preference:
+ # 1. user-declared that are installed
+ # 3. installed and in profile
+ # 4. installed
+ # 2. user-declared set
+ # 5. profile
+
+ self.dirVirtuals = grab_multiple("virtuals", myvirtdirs, grabdict)
+ self.dirVirtuals.reverse()
+
+ if self.user_profile_dir and os.path.exists(self.user_profile_dir+"/virtuals"):
+ self.userVirtuals = grabdict(self.user_profile_dir+"/virtuals")
+
+ # Store all the negatives for later.
+ for x in self.userVirtuals.keys():
+ self.negVirtuals[x] = []
+ for y in self.userVirtuals[x]:
+ if y[0] == '-':
+ self.negVirtuals[x].append(y[:])
+
+ # Collapse the user virtuals so that we don't deal with negatives.
+ self.userVirtuals = stack_dictlist([self.userVirtuals],incremental=1)
+
+ # Collapse all the profile virtuals including user negations.
+ self.dirVirtuals = stack_dictlist([self.negVirtuals]+self.dirVirtuals,incremental=1)
+
+ # Repoman does not use user or tree virtuals.
+ if os.environ.get("PORTAGE_CALLER","") != "repoman":
+ # XXX: vartree does not use virtuals, does user set matter?
+ temp_vartree = vartree(myroot,self.dirVirtuals,categories=self.categories)
+ # Reduce the provides into a list by CP.
+ self.treeVirtuals = map_dictlist_vals(getCPFromCPV,temp_vartree.get_all_provides())
+
+ return self.__getvirtuals_compile()
+
+ def __getvirtuals_compile(self):
+ """Actually generate the virtuals we have collected.
+ The results are reversed so the list order is left to right.
+ Given data is [Best,Better,Good] sets of [Good, Better, Best]"""
+
+ # Virtuals by profile+tree preferences.
+ ptVirtuals = {}
+ # Virtuals by user+tree preferences.
+ utVirtuals = {}
+
+ # If a user virtual is already installed, we preference it.
+ for x in self.userVirtuals.keys():
+ utVirtuals[x] = []
+ if self.treeVirtuals.has_key(x):
+ for y in self.userVirtuals[x]:
+ if y in self.treeVirtuals[x]:
+ utVirtuals[x].append(y)
+ #print "F:",utVirtuals
+ #utVirtuals[x].reverse()
+ #print "R:",utVirtuals
+
+ # If a profile virtual is already installed, we preference it.
+ for x in self.dirVirtuals.keys():
+ ptVirtuals[x] = []
+ if self.treeVirtuals.has_key(x):
+ for y in self.dirVirtuals[x]:
+ if y in self.treeVirtuals[x]:
+ ptVirtuals[x].append(y)
+
+ # UserInstalled, ProfileInstalled, Installed, User, Profile
+ biglist = [utVirtuals, ptVirtuals, self.treeVirtuals,
+ self.userVirtuals, self.dirVirtuals]
+
+ # We reverse each dictlist so that the order matches everything
+ # else in portage. [-*, a, b] [b, c, d] ==> [b, a]
+ for dictlist in biglist:
+ for key in dictlist:
+ dictlist[key].reverse()
+
+ # User settings and profile settings take precedence over tree.
+ val = stack_dictlist(biglist,incremental=1)
+
+ return val
+
+ def __delitem__(self,mykey):
+ for x in self.lookuplist:
+ if x != None:
+ if mykey in x:
+ del x[mykey]
+
+ def __getitem__(self,mykey):
+ match = ''
+ for x in self.lookuplist:
+ if x == None:
+ writemsg("!!! lookuplist is null.\n")
+ elif x.has_key(mykey):
+ match = x[mykey]
+ break
+
+ if 0 and match and mykey in ["PORTAGE_BINHOST"]:
+ # These require HTTP Encoding
+ try:
+ import urllib
+ if urllib.unquote(match) != match:
+ writemsg("Note: %s already contains escape codes." % (mykey))
+ else:
+ match = urllib.quote(match)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("Failed to fix %s using urllib, attempting to continue.\n" % (mykey))
+ pass
+
+ elif mykey == "CONFIG_PROTECT_MASK":
+ match += " /etc/env.d"
+
+ return match
+
+ def has_key(self,mykey):
+ for x in self.lookuplist:
+ if x.has_key(mykey):
+ return 1
+ return 0
+
+ def keys(self):
+ mykeys=[]
+ for x in self.lookuplist:
+ for y in x.keys():
+ if y not in mykeys:
+ mykeys.append(y)
+ return mykeys
+
+ def __setitem__(self,mykey,myvalue):
+ "set a value; will be thrown away at reset() time"
+ if type(myvalue) != types.StringType:
+ raise ValueError("Invalid type being used as a value: '%s': '%s'" % (str(mykey),str(myvalue)))
+ self.modifying()
+ self.modifiedkeys += [mykey]
+ self.configdict["env"][mykey]=myvalue
+
+ def environ(self):
+ "return our locally-maintained environment"
+ mydict={}
+ for x in self.keys():
+ mydict[x]=self[x]
+ if not mydict.has_key("HOME") and mydict.has_key("BUILD_PREFIX"):
+ writemsg("*** HOME not set. Setting to "+mydict["BUILD_PREFIX"]+"\n")
+ mydict["HOME"]=mydict["BUILD_PREFIX"][:]
+
+ return mydict
+
+
+# XXX This would be to replace getstatusoutput completely.
+# XXX Issue: cannot block execution. Deadlock condition.
+def spawn(mystring,mysettings,debug=0,free=0,droppriv=0,fd_pipes=None,**keywords):
+ """spawn a subprocess with optional sandbox protection,
+ depending on whether sandbox is enabled. The "free" argument,
+ when set to 1, will disable sandboxing. This allows us to
+ spawn processes that are supposed to modify files outside of the
+ sandbox. We can't use os.system anymore because it messes up
+ signal handling. Using spawn allows our Portage signal handler
+ to work."""
+
+ if type(mysettings) == types.DictType:
+ env=mysettings
+ keywords["opt_name"]="[ %s ]" % "portage"
+ else:
+ check_config_instance(mysettings)
+ env=mysettings.environ()
+ keywords["opt_name"]="[%s]" % mysettings["PF"]
+
+ # XXX: Negative RESTRICT word
+ droppriv=(droppriv and ("userpriv" in features) and not \
+ (("nouserpriv" in string.split(mysettings["RESTRICT"])) or \
+ ("userpriv" in string.split(mysettings["RESTRICT"]))))
+
+
+ if ("sandbox" in features) and (not free):
+ keywords["opt_name"] += " sandbox"
+ if droppriv and portage_gid and portage_uid:
+ keywords.update({"uid":portage_uid,"gid":portage_gid,"groups":[portage_gid],"umask":002})
+ return portage_exec.spawn_sandbox(mystring,env=env,**keywords)
+ else:
+ keywords["opt_name"] += " bash"
+ return portage_exec.spawn_bash(mystring,env=env,**keywords)
+
+
+
+def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks",use_locks=1, try_mirrors=1):
+ "fetch files. Will use digest file if available."
+
+ # 'nomirror' is bad/negative logic. You Restrict mirroring, not no-mirroring.
+ if ("mirror" in mysettings["RESTRICT"].split()) or \
+ ("nomirror" in mysettings["RESTRICT"].split()):
+ if ("mirror" in features) and ("lmirror" not in features):
+ # lmirror should allow you to bypass mirror restrictions.
+ # XXX: This is not a good thing, and is temporary at best.
+ print ">>> \"mirror\" mode desired and \"mirror\" restriction found; skipping fetch."
+ return 1
+
+ global thirdpartymirrors
+
+ check_config_instance(mysettings)
+
+ custommirrors=grabdict(CUSTOM_MIRRORS_FILE)
+
+ mymirrors=[]
+
+ if listonly or ("distlocks" not in features):
+ use_locks = 0
+
+ fetch_to_ro = 0
+ if "skiprocheck" in features:
+ fetch_to_ro = 1
+
+ if not os.access(mysettings["DISTDIR"],os.W_OK) and fetch_to_ro:
+ if use_locks:
+ writemsg(red("!!! You are fetching to a read-only filesystem, you should turn locking off"));
+ writemsg("!!! This can be done by adding -distlocks to FEATURES in /etc/make.conf");
+# use_locks = 0
+
+ # local mirrors are always added
+ if custommirrors.has_key("local"):
+ mymirrors += custommirrors["local"]
+
+ if ("nomirror" in mysettings["RESTRICT"].split()) or \
+ ("mirror" in mysettings["RESTRICT"].split()):
+ # We don't add any mirrors.
+ pass
+ else:
+ if try_mirrors:
+ for x in mysettings["GENTOO_MIRRORS"].split():
+ if x:
+ if x[-1] == '/':
+ mymirrors += [x[:-1]]
+ else:
+ mymirrors += [x]
+
+ mydigests = {}
+ digestfn = mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+ if os.path.exists(digestfn):
+ mydigests = digestParseFile(digestfn)
+
+ fsmirrors = []
+ for x in range(len(mymirrors)-1,-1,-1):
+ if mymirrors[x] and mymirrors[x][0]=='/':
+ fsmirrors += [mymirrors[x]]
+ del mymirrors[x]
+
+ for myuri in myuris:
+ myfile=os.path.basename(myuri)
+ try:
+ destdir = mysettings["DISTDIR"]+"/"
+ if not os.path.exists(destdir+myfile):
+ for mydir in fsmirrors:
+ if os.path.exists(mydir+"/"+myfile):
+ writemsg(_("Local mirror has file: %(file)s\n" % {"file":myfile}))
+ shutil.copyfile(mydir+"/"+myfile,destdir+"/"+myfile)
+ break
+ except (OSError,IOError),e:
+ # file does not exist
+ writemsg(_("!!! %(file)s not found in %(dir)s\n") % {"file":myfile, "dir":mysettings["DISTDIR"]})
+ gotit=0
+
+ if "fetch" in mysettings["RESTRICT"].split():
+ # fetch is restricted. Ensure all files have already been downloaded; otherwise,
+ # print message and exit.
+ gotit=1
+ for myuri in myuris:
+ myfile=os.path.basename(myuri)
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/"+myfile)
+ except (OSError,IOError),e:
+ # file does not exist
+ writemsg(_("!!! %(file)s not found in %(dir)s\n") % {"file":myfile, "dir":mysettings["DISTDIR"]})
+ gotit=0
+ if not gotit:
+ print
+ print "!!!",mysettings["CATEGORY"]+"/"+mysettings["PF"],"has fetch restriction turned on."
+ print "!!! This probably means that this ebuild's files must be downloaded"
+ print "!!! manually. See the comments in the ebuild for more information."
+ print
+ spawn(EBUILD_SH_BINARY+" nofetch",mysettings)
+ return 0
+ return 1
+ locations=mymirrors[:]
+ filedict={}
+ primaryuri_indexes={}
+ for myuri in myuris:
+ myfile=os.path.basename(myuri)
+ if not filedict.has_key(myfile):
+ filedict[myfile]=[]
+ for y in range(0,len(locations)):
+ filedict[myfile].append(locations[y]+"/distfiles/"+myfile)
+ if myuri[:9]=="mirror://":
+ eidx = myuri.find("/", 9)
+ if eidx != -1:
+ mirrorname = myuri[9:eidx]
+
+ # Try user-defined mirrors first
+ if custommirrors.has_key(mirrorname):
+ for cmirr in custommirrors[mirrorname]:
+ filedict[myfile].append(cmirr+"/"+myuri[eidx+1:])
+ # remove the mirrors we tried from the list of official mirrors
+ if cmirr.strip() in thirdpartymirrors[mirrorname]:
+ thirdpartymirrors[mirrorname].remove(cmirr)
+ # now try the official mirrors
+ if thirdpartymirrors.has_key(mirrorname):
+ try:
+ shuffle(thirdpartymirrors[mirrorname])
+ except SystemExit, e:
+ raise
+ except:
+ writemsg(red("!!! YOU HAVE A BROKEN PYTHON/GLIBC.\n"))
+ writemsg( "!!! You are most likely on a pentium4 box and have specified -march=pentium4\n")
+ writemsg( "!!! or -fpmath=sse2. GCC was generating invalid sse2 instructions in versions\n")
+ writemsg( "!!! prior to 3.2.3. Please merge the latest gcc or rebuid python with either\n")
+ writemsg( "!!! -march=pentium3 or set -mno-sse2 in your cflags.\n\n\n")
+ time.sleep(10)
+
+ for locmirr in thirdpartymirrors[mirrorname]:
+ filedict[myfile].append(locmirr+"/"+myuri[eidx+1:])
+
+ if not filedict[myfile]:
+ writemsg("No known mirror by the name: %s\n" % (mirrorname))
+ else:
+ writemsg("Invalid mirror definition in SRC_URI:\n")
+ writemsg(" %s\n" % (myuri))
+ else:
+ if "primaryuri" in mysettings["RESTRICT"].split():
+ # Use the source site first.
+ if primaryuri_indexes.has_key(myfile):
+ primaryuri_indexes[myfile] += 1
+ else:
+ primaryuri_indexes[myfile] = 0
+ filedict[myfile].insert(primaryuri_indexes[myfile], myuri)
+ else:
+ filedict[myfile].append(myuri)
+
+ missingSourceHost = False
+ for myfile in filedict.keys(): # Gives a list, not just the first one
+ if not filedict[myfile]:
+ writemsg("Warning: No mirrors available for file '%s'\n" % (myfile))
+ missingSourceHost = True
+ if missingSourceHost:
+ return 0
+ del missingSourceHost
+
+ can_fetch=True
+ if not os.access(mysettings["DISTDIR"]+"/",os.W_OK):
+ if not fetch_to_ro:
+ print "!!! No write access to %s" % mysettings["DISTDIR"]+"/"
+ can_fetch=False
+ else:
+ mystat=os.stat(mysettings["DISTDIR"]+"/")
+ if mystat.st_gid != portage_gid:
+ try:
+ os.chown(mysettings["DISTDIR"],-1,portage_gid)
+ except OSError, oe:
+ if oe.errno == 1:
+ print red("!!!")+" Unable to chgrp of %s to portage, continuing\n" % mysettings["DISTDIR"]
+ else:
+ raise oe
+
+ # writable by portage_gid? This is specific to root, adjust perms if needed automatically.
+ if not stat.S_IMODE(mystat.st_mode) & 020:
+ try:
+ os.chmod(mysettings["DISTDIR"],stat.S_IMODE(mystat.st_mode) | 020)
+ except OSError, oe:
+ if oe.errno == 1:
+ print red("!!!")+" Unable to chmod %s to perms 0755. Non-root users will experience issues.\n" % mysettings["DISTDIR"]
+ else:
+ raise oe
+
+ if use_locks and locks_in_subdir:
+ if os.path.exists(mysettings["DISTDIR"]+"/"+locks_in_subdir):
+ if not os.access(mysettings["DISTDIR"]+"/"+locks_in_subdir,os.W_OK):
+ writemsg("!!! No write access to write to %s. Aborting.\n" % mysettings["DISTDIR"]+"/"+locks_in_subdir)
+ return 0
+ else:
+ old_umask=os.umask(0002)
+ os.mkdir(mysettings["DISTDIR"]+"/"+locks_in_subdir,0775)
+ if os.stat(mysettings["DISTDIR"]+"/"+locks_in_subdir).st_gid != portage_gid:
+ try:
+ os.chown(mysettings["DISTDIR"]+"/"+locks_in_subdir,-1,portage_gid)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ os.umask(old_umask)
+
+
+ for myfile in filedict.keys():
+ fetched=0
+ file_lock = None
+ if listonly:
+ writemsg("\n")
+ else:
+ if use_locks and can_fetch:
+ if locks_in_subdir:
+ file_lock = portage_locks.lockfile(mysettings["DISTDIR"]+"/"+locks_in_subdir+"/"+myfile,wantnewlockfile=1)
+ else:
+ file_lock = portage_locks.lockfile(mysettings["DISTDIR"]+"/"+myfile,wantnewlockfile=1)
+ try:
+ for loc in filedict[myfile]:
+ if listonly:
+ writemsg(loc+" ")
+ continue
+ # allow different fetchcommands per protocol
+ protocol = loc[0:loc.find("://")]
+ if mysettings.has_key("FETCHCOMMAND_"+protocol.upper()):
+ fetchcommand=mysettings["FETCHCOMMAND_"+protocol.upper()]
+ else:
+ fetchcommand=mysettings["FETCHCOMMAND"]
+ if mysettings.has_key("RESUMECOMMAND_"+protocol.upper()):
+ resumecommand=mysettings["RESUMECOMMAND_"+protocol.upper()]
+ else:
+ resumecommand=mysettings["RESUMECOMMAND"]
+
+ fetchcommand=string.replace(fetchcommand,"${DISTDIR}",mysettings["DISTDIR"])
+ resumecommand=string.replace(resumecommand,"${DISTDIR}",mysettings["DISTDIR"])
+
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/"+myfile)
+ if mydigests.has_key(myfile):
+ #if we have the digest file, we know the final size and can resume the download.
+ if mystat[stat.ST_SIZE]<mydigests[myfile]["size"]:
+ fetched=1
+ else:
+ #we already have it downloaded, skip.
+ #if our file is bigger than the recorded size, digestcheck should catch it.
+ if not fetchonly:
+ fetched=2
+ else:
+ # Check md5sum's at each fetch for fetchonly.
+ verified_ok,reason = portage_checksum.verify_all(mysettings["DISTDIR"]+"/"+myfile, mydigests[myfile])
+ if not verified_ok:
+ writemsg("!!! Previously fetched file: "+str(myfile)+"\n!!! Reason: "+reason+"\nRefetching...\n\n")
+ os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+ fetched=0
+ else:
+ for x_key in mydigests[myfile].keys():
+ writemsg(">>> Previously fetched file: "+str(myfile)+" "+x_key+" ;-)\n")
+ fetched=2
+ break #No need to keep looking for this file, we have it!
+ else:
+ #we don't have the digest file, but the file exists. Assume it is fully downloaded.
+ fetched=2
+ except (OSError,IOError),e:
+ writemsg("An exception was caught(1)...\nFailing the download: %s.\n" % (str(e)),1)
+ fetched=0
+
+ if not can_fetch:
+ if fetched != 2:
+ if fetched == 0:
+ writemsg("!!! File %s isn't fetched but unable to get it.\n" % myfile)
+ else:
+ writemsg("!!! File %s isn't fully fetched, but unable to complete it\n" % myfile)
+ return 0
+ else:
+ continue
+
+ # check if we can actually write to the directory/existing file.
+ if fetched!=2 and os.path.exists(mysettings["DISTDIR"]+"/"+myfile) != \
+ os.access(mysettings["DISTDIR"]+"/"+myfile, os.W_OK) and not fetch_to_ro:
+ writemsg(red("***")+" Lack write access to %s, failing fetch\n" % str(mysettings["DISTDIR"]+"/"+myfile))
+ fetched=0
+ break
+ elif fetched!=2:
+ #we either need to resume or start the download
+ #you can't use "continue" when you're inside a "try" block
+ if fetched==1:
+ #resume mode:
+ writemsg(">>> Resuming download...\n")
+ locfetch=resumecommand
+ else:
+ #normal mode:
+ locfetch=fetchcommand
+ writemsg(">>> Downloading "+str(loc)+"\n")
+ myfetch=string.replace(locfetch,"${URI}",loc)
+ myfetch=string.replace(myfetch,"${FILE}",myfile)
+ try:
+ if selinux_enabled:
+ con=selinux.getcontext()
+ con=string.replace(con,mysettings["PORTAGE_T"],mysettings["PORTAGE_FETCH_T"])
+ selinux.setexec(con)
+ myret=spawn(myfetch,mysettings,free=1)
+ selinux.setexec(None)
+ else:
+ myret=spawn(myfetch,mysettings,free=1)
+ finally:
+ #if root, -always- set the perms.
+ if os.path.exists(mysettings["DISTDIR"]+"/"+myfile) and (fetched != 1 or os.getuid() == 0) \
+ and os.access(mysettings["DISTDIR"]+"/",os.W_OK):
+ if os.stat(mysettings["DISTDIR"]+"/"+myfile).st_gid != portage_gid:
+ try:
+ os.chown(mysettings["DISTDIR"]+"/"+myfile,-1,portage_gid)
+ except SystemExit, e:
+ raise
+ except:
+ portage_util.writemsg("chown failed on distfile: " + str(myfile))
+ os.chmod(mysettings["DISTDIR"]+"/"+myfile,0664)
+
+ if mydigests!=None and mydigests.has_key(myfile):
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/"+myfile)
+ # no exception? file exists. let digestcheck() report
+ # an appropriately for size or md5 errors
+ if (mystat[stat.ST_SIZE]<mydigests[myfile]["size"]):
+ # Fetch failed... Try the next one... Kill 404 files though.
+ if (mystat[stat.ST_SIZE]<100000) and (len(myfile)>4) and not ((myfile[-5:]==".html") or (myfile[-4:]==".htm")):
+ html404=re.compile("<title>.*(not found|404).*</title>",re.I|re.M)
+ try:
+ if html404.search(open(mysettings["DISTDIR"]+"/"+myfile).read()):
+ try:
+ os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+ writemsg(">>> Deleting invalid distfile. (Improper 404 redirect from server.)\n")
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ continue
+ if not fetchonly:
+ fetched=2
+ break
+ else:
+ # File is the correct size--check the MD5 sum for the fetched
+ # file NOW, for those users who don't have a stable/continuous
+ # net connection. This way we have a chance to try to download
+ # from another mirror...
+ verified_ok,reason = portage_checksum.verify_all(mysettings["DISTDIR"]+"/"+myfile, mydigests[myfile])
+ if not verified_ok:
+ writemsg("!!! Fetched file: "+str(myfile)+" VERIFY FAILED!\n!!! Reason: "+reason+"\nRemoving corrupt distfile...\n")
+ os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+ fetched=0
+ else:
+ for x_key in mydigests[myfile].keys():
+ writemsg(">>> "+str(myfile)+" "+x_key+" ;-)\n")
+ fetched=2
+ break
+ except (OSError,IOError),e:
+ writemsg("An exception was caught(2)...\nFailing the download: %s.\n" % (str(e)),1)
+ fetched=0
+ else:
+ if not myret:
+ fetched=2
+ break
+ elif mydigests!=None:
+ writemsg("No digest file available and download failed.\n\n")
+ finally:
+ if use_locks and file_lock:
+ portage_locks.unlockfile(file_lock)
+
+ if listonly:
+ writemsg("\n")
+ if (fetched!=2) and not listonly:
+ writemsg("!!! Couldn't download "+str(myfile)+". Aborting.\n")
+ return 0
+ return 1
+
+
+def digestCreate(myfiles,basedir,oldDigest={}):
+ """Takes a list of files and the directory they are in and returns the
+ dict of dict[filename][CHECKSUM_KEY] = hash
+ returns None on error."""
+ mydigests={}
+ for x in myfiles:
+ print "<<<",x
+ myfile=os.path.normpath(basedir+"///"+x)
+ if os.path.exists(myfile):
+ if not os.access(myfile, os.R_OK):
+ print "!!! Given file does not appear to be readable. Does it exist?"
+ print "!!! File:",myfile
+ return None
+ mydigests[x] = portage_checksum.perform_all(myfile)
+ mysize = os.stat(myfile)[stat.ST_SIZE]
+ else:
+ if x in oldDigest:
+ # DeepCopy because we might not have a unique reference.
+ mydigests[x] = copy.deepcopy(oldDigest[x])
+ mysize = copy.deepcopy(oldDigest[x]["size"])
+ else:
+ print "!!! We have a source URI, but no file..."
+ print "!!! File:",myfile
+ return None
+
+ if mydigests[x].has_key("size") and (mydigests[x]["size"] != mysize):
+ raise portage_exception.DigestException, "Size mismatch during checksums"
+ mydigests[x]["size"] = copy.deepcopy(mysize)
+ return mydigests
+
+def digestCreateLines(filelist, mydict):
+ mylines = []
+ mydigests = copy.deepcopy(mydict)
+ for myarchive in filelist:
+ mysize = mydigests[myarchive]["size"]
+ if len(mydigests[myarchive]) == 0:
+ raise portage_exception.DigestException, "No generate digest for '%(file)s'" % {"file":myarchive}
+ for sumName in mydigests[myarchive].keys():
+ if sumName not in portage_checksum.get_valid_checksum_keys():
+ continue
+ mysum = mydigests[myarchive][sumName]
+
+ myline = sumName[:]
+ myline += " "+mysum
+ myline += " "+myarchive
+ myline += " "+str(mysize)
+ if sumName != "MD5":
+ # XXXXXXXXXXXXXXXX This cannot be used!
+ # Older portage make very dumb assumptions about the formats.
+ # We need a lead-in period before we break everything.
+ continue
+ mylines.append(myline)
+ return mylines
+
+def digestgen(myarchives,mysettings,overwrite=1,manifestonly=0):
+ """generates digest file if missing. Assumes all files are available. If
+ overwrite=0, the digest will only be created if it doesn't already exist."""
+
+ # archive files
+ basedir=mysettings["DISTDIR"]+"/"
+ digestfn=mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+
+ # portage files -- p(ortagefiles)basedir
+ pbasedir=mysettings["O"]+"/"
+ manifestfn=pbasedir+"Manifest"
+
+ if not manifestonly:
+ if not os.path.isdir(mysettings["FILESDIR"]):
+ os.makedirs(mysettings["FILESDIR"])
+ mycvstree=cvstree.getentries(pbasedir, recursive=1)
+
+ if ("cvs" in features) and os.path.exists(pbasedir+"/CVS"):
+ if not cvstree.isadded(mycvstree,"files"):
+ if "autoaddcvs" in features:
+ print ">>> Auto-adding files/ dir to CVS..."
+ spawn("cd "+pbasedir+"; cvs add files",mysettings,free=1)
+ else:
+ print "--- Warning: files/ is not added to cvs."
+
+ if (not overwrite) and os.path.exists(digestfn):
+ return 1
+
+ print green(">>> Generating digest file...")
+
+ # Track the old digest so we can assume checksums without requiring
+ # all files to be downloaded. 'Assuming'
+ myolddigest = {}
+ if os.path.exists(digestfn):
+ myolddigest = digestParseFile(digestfn)
+
+ mydigests=digestCreate(myarchives, basedir, oldDigest=myolddigest)
+ if mydigests==None: # There was a problem, exit with an errorcode.
+ return 0
+
+ try:
+ outfile=open(digestfn, "w+")
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Filesystem error skipping generation. (Read-Only?)"
+ print "!!!",e
+ return 0
+ for x in digestCreateLines(myarchives, mydigests):
+ outfile.write(x+"\n")
+ outfile.close()
+ try:
+ os.chown(digestfn,os.getuid(),portage_gid)
+ os.chmod(digestfn,0664)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ print e
+
+ print green(">>> Generating manifest file...")
+ mypfiles=listdir(pbasedir,recursive=1,filesonly=1,ignorecvs=1,EmptyOnError=1)
+ mypfiles=cvstree.apply_cvsignore_filter(mypfiles)
+ for x in ["Manifest"]:
+ if x in mypfiles:
+ mypfiles.remove(x)
+
+ mydigests=digestCreate(mypfiles, pbasedir)
+ if mydigests==None: # There was a problem, exit with an errorcode.
+ return 0
+
+ try:
+ outfile=open(manifestfn, "w+")
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Filesystem error skipping generation. (Read-Only?)"
+ print "!!!",e
+ return 0
+ for x in digestCreateLines(mypfiles, mydigests):
+ outfile.write(x+"\n")
+ outfile.close()
+ try:
+ os.chown(manifestfn,os.getuid(),portage_gid)
+ os.chmod(manifestfn,0664)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ print e
+
+ if "cvs" in features and os.path.exists(pbasedir+"/CVS"):
+ mycvstree=cvstree.getentries(pbasedir, recursive=1)
+ myunaddedfiles=""
+ if not manifestonly and not cvstree.isadded(mycvstree,digestfn):
+ if digestfn[:len(pbasedir)]==pbasedir:
+ myunaddedfiles=digestfn[len(pbasedir):]+" "
+ else:
+ myunaddedfiles=digestfn+" "
+ if not cvstree.isadded(mycvstree,manifestfn[len(pbasedir):]):
+ if manifestfn[:len(pbasedir)]==pbasedir:
+ myunaddedfiles+=manifestfn[len(pbasedir):]+" "
+ else:
+ myunaddedfiles+=manifestfn
+ if myunaddedfiles:
+ if "autoaddcvs" in features:
+ print blue(">>> Auto-adding digest file(s) to CVS...")
+ spawn("cd "+pbasedir+"; cvs add "+myunaddedfiles,mysettings,free=1)
+ else:
+ print "--- Warning: digests are not yet added into CVS."
+ print darkgreen(">>> Computed message digests.")
+ print
+ return 1
+
+
+def digestParseFile(myfilename):
+ """(filename) -- Parses a given file for entries matching:
+ MD5 MD5_STRING_OF_HEX_CHARS FILE_NAME FILE_SIZE
+ Ignores lines that do not begin with 'MD5' and returns a
+ dict with the filenames as keys and [md5,size] as the values."""
+
+ if not os.path.exists(myfilename):
+ return None
+ mylines = portage_util.grabfile(myfilename, compat_level=1)
+
+ mydigests={}
+ for x in mylines:
+ myline=string.split(x)
+ if len(myline) < 4:
+ #invalid line
+ continue
+ if myline[0] not in portage_checksum.get_valid_checksum_keys():
+ continue
+ mykey = myline.pop(0)
+ myhash = myline.pop(0)
+ mysize = long(myline.pop())
+ myfn = string.join(myline, " ")
+ if myfn not in mydigests:
+ mydigests[myfn] = {}
+ mydigests[myfn][mykey] = myhash
+ if "size" in mydigests[myfn]:
+ if mydigests[myfn]["size"] != mysize:
+ raise portage_exception.DigestException, "Conflicting sizes in digest: %(filename)s" % {"filename":myfilename}
+ else:
+ mydigests[myfn]["size"] = mysize
+ return mydigests
+
+# XXXX strict was added here to fix a missing name error.
+# XXXX It's used below, but we're not paying attention to how we get it?
+def digestCheckFiles(myfiles, mydigests, basedir, note="", strict=0):
+ """(fileslist, digestdict, basedir) -- Takes a list of files and a dict
+ of their digests and checks the digests against the indicated files in
+ the basedir given. Returns 1 only if all files exist and match the md5s.
+ """
+ for x in myfiles:
+ if not mydigests.has_key(x):
+ print
+ print red("!!! No message digest entry found for file \""+x+".\"")
+ print "!!! Most likely a temporary problem. Try 'emerge sync' again later."
+ print "!!! If you are certain of the authenticity of the file then you may type"
+ print "!!! the following to generate a new digest:"
+ print "!!! ebuild /usr/portage/category/package/package-version.ebuild digest"
+ return 0
+ myfile=os.path.normpath(basedir+"/"+x)
+ if not os.path.exists(myfile):
+ if strict:
+ print "!!! File does not exist:",myfile
+ return 0
+ continue
+
+ ok,reason = portage_checksum.verify_all(myfile,mydigests[x])
+ if not ok:
+ print
+ print red("!!! Digest verification Failed:")
+ print red("!!!")+" "+str(myfile)
+ print red("!!! Reason: ")+reason
+ print
+ return 0
+ else:
+ print ">>> md5 "+note+" ;-)",x
+ return 1
+
+
+def digestcheck(myfiles, mysettings, strict=0):
+ """Checks md5sums. Assumes all files have been downloaded."""
+ # archive files
+ basedir=mysettings["DISTDIR"]+"/"
+ digestfn=mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+
+ # portage files -- p(ortagefiles)basedir
+ pbasedir=mysettings["O"]+"/"
+ manifestfn=pbasedir+"Manifest"
+
+ if not (os.path.exists(digestfn) and os.path.exists(manifestfn)):
+ if "digest" in features:
+ print ">>> No package digest/Manifest file found."
+ print ">>> \"digest\" mode enabled; auto-generating new digest..."
+ return digestgen(myfiles,mysettings)
+ else:
+ if not os.path.exists(manifestfn):
+ if strict:
+ print red("!!! No package manifest found:"),manifestfn
+ return 0
+ else:
+ print "--- No package manifest found:",manifestfn
+ if not os.path.exists(digestfn):
+ print "!!! No package digest file found:",digestfn
+ print "!!! Type \"ebuild foo.ebuild digest\" to generate it."
+ return 0
+
+ mydigests=digestParseFile(digestfn)
+ if mydigests==None:
+ print "!!! Failed to parse digest file:",digestfn
+ return 0
+ mymdigests=digestParseFile(manifestfn)
+ if "strict" not in features:
+ # XXX: Remove this when manifests become mainstream.
+ pass
+ elif mymdigests==None:
+ print "!!! Failed to parse manifest file:",manifestfn
+ if strict:
+ return 0
+ else:
+ # Check the portage-related files here.
+ mymfiles=listdir(pbasedir,recursive=1,filesonly=1,ignorecvs=1,EmptyOnError=1)
+ manifest_files = mymdigests.keys()
+ for x in ["Manifest", "ChangeLog", "metadata.xml"]:
+ while x in mymfiles:
+ mymfiles.remove(x)
+ while x in manifest_files:
+ manifest_files.remove(x)
+ for x in range(len(mymfiles)-1,-1,-1):
+ if mymfiles[x] in manifest_files:
+ manifest_files.remove(mymfiles[x])
+ elif len(cvstree.apply_cvsignore_filter([mymfiles[x]]))==0:
+ # we filter here, rather then above; manifest might have files flagged by the filter.
+ # if something is returned, then it's flagged as a bad file
+ # manifest doesn't know about it, so we kill it here.
+ del mymfiles[x]
+ else:
+ print red("!!! Security Violation: A file exists that is not in the manifest.")
+ print "!!! File:",mymfiles[x]
+ if strict:
+ return 0
+ if manifest_files and strict:
+ print red("!!! Files listed in the manifest do not exist!")
+ for x in manifest_files:
+ print x
+ return 0
+
+ if not digestCheckFiles(mymfiles, mymdigests, pbasedir, note="files ", strict=strict):
+ if strict:
+ print ">>> Please ensure you have sync'd properly. Please try '"+bold("emerge sync")+"' and"
+ print ">>> optionally examine the file(s) for corruption. "+bold("A sync will fix most cases.")
+ print
+ return 0
+ else:
+ print "--- Manifest check failed. 'strict' not enabled; ignoring."
+ print
+
+ # Just return the status, as it's the last check.
+ return digestCheckFiles(myfiles, mydigests, basedir, note="src_uri", strict=strict)
+
+# parse actionmap to spawn ebuild with the appropriate args
+def spawnebuild(mydo,actionmap,mysettings,debug,alwaysdep=0,logfile=None):
+ if alwaysdep or ("noauto" not in features):
+ # process dependency first
+ if "dep" in actionmap[mydo].keys():
+ retval=spawnebuild(actionmap[mydo]["dep"],actionmap,mysettings,debug,alwaysdep=alwaysdep,logfile=logfile)
+ if retval:
+ return retval
+ # spawn ebuild.sh
+ mycommand = EBUILD_SH_BINARY + " "
+ if selinux_enabled and ("sesandbox" in features) and (mydo in ["unpack","compile","test","install"]):
+ con=selinux.getcontext()
+ con=string.replace(con,mysettings["PORTAGE_T"],mysettings["PORTAGE_SANDBOX_T"])
+ selinux.setexec(con)
+ retval=spawn(mycommand + mydo,mysettings,debug=debug,
+ free=actionmap[mydo]["args"][0],
+ droppriv=actionmap[mydo]["args"][1],logfile=logfile)
+ selinux.setexec(None)
+ else:
+ retval=spawn(mycommand + mydo,mysettings, debug=debug,
+ free=actionmap[mydo]["args"][0],
+ droppriv=actionmap[mydo]["args"][1],logfile=logfile)
+ return retval
+
+def doebuild(myebuild,mydo,myroot,mysettings,debug=0,listonly=0,fetchonly=0,cleanup=0,dbkey=None,use_cache=1,fetchall=0,tree="porttree"):
+ global db
+
+ ebuild_path = os.path.abspath(myebuild)
+ pkg_dir = os.path.dirname(ebuild_path)
+
+ if mysettings.configdict["pkg"].has_key("CATEGORY"):
+ cat = mysettings.configdict["pkg"]["CATEGORY"]
+ else:
+ cat = os.path.basename(os.path.normpath(pkg_dir+"/.."))
+ mypv = os.path.basename(ebuild_path)[:-7]
+ mycpv = cat+"/"+mypv
+
+ mysplit=pkgsplit(mypv,silent=0)
+ if mysplit==None:
+ writemsg("!!! Error: PF is null '%s'; exiting.\n" % mypv)
+ return 1
+
+ if mydo != "depend":
+ # XXX: We're doing a little hack here to curtain the gvisible locking
+ # XXX: that creates a deadlock... Really need to isolate that.
+ mysettings.reset(use_cache=use_cache)
+ mysettings.setcpv(mycpv,use_cache=use_cache)
+
+ validcommands = ["help","clean","prerm","postrm","preinst","postinst",
+ "config","setup","depend","fetch","digest",
+ "unpack","compile","test","install","rpm","qmerge","merge",
+ "package","unmerge", "manifest"]
+
+ if mydo not in validcommands:
+ validcommands.sort()
+ writemsg("!!! doebuild: '%s' is not one of the following valid commands:" % mydo)
+ for vcount in range(len(validcommands)):
+ if vcount%6 == 0:
+ writemsg("\n!!! ")
+ writemsg(string.ljust(validcommands[vcount], 11))
+ writemsg("\n")
+ return 1
+
+ if not os.path.exists(myebuild):
+ writemsg("!!! doebuild: "+str(myebuild)+" not found for "+str(mydo)+"\n")
+ return 1
+
+ if debug: # Otherwise it overrides emerge's settings.
+ # We have no other way to set debug... debug can't be passed in
+ # due to how it's coded... Don't overwrite this so we can use it.
+ mysettings["PORTAGE_DEBUG"]=str(debug)
+
+ mysettings["ROOT"] = myroot
+ mysettings["STARTDIR"] = getcwd()
+
+ mysettings["EBUILD"] = ebuild_path
+ mysettings["O"] = pkg_dir
+ mysettings["CATEGORY"] = cat
+ mysettings["FILESDIR"] = pkg_dir+"/files"
+ mysettings["PF"] = mypv
+
+ mysettings["ECLASSDIR"] = mysettings["PORTDIR"]+"/eclass"
+ mysettings["SANDBOX_LOG"] = mycpv.replace("/", "_-_")
+
+ mysettings["PROFILE_PATHS"] = string.join(mysettings.profiles,"\n")+"\n"+CUSTOM_PROFILE_PATH
+ mysettings["P"] = mysplit[0]+"-"+mysplit[1]
+ mysettings["PN"] = mysplit[0]
+ mysettings["PV"] = mysplit[1]
+ mysettings["PR"] = mysplit[2]
+
+ if mydo != "depend":
+ try:
+ mysettings["INHERITED"], mysettings["RESTRICT"] = db[root][tree].dbapi.aux_get( \
+ mycpv,["INHERITED","RESTRICT"])
+ mysettings["PORTAGE_RESTRICT"]=string.join(flatten(portage_dep.use_reduce(portage_dep.paren_reduce( \
+ mysettings["RESTRICT"]), uselist=mysettings["USE"].split())),' ')
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+ if mysplit[2] == "r0":
+ mysettings["PVR"]=mysplit[1]
+ else:
+ mysettings["PVR"]=mysplit[1]+"-"+mysplit[2]
+
+ mysettings["SLOT"]=""
+
+ if mysettings.has_key("PATH"):
+ mysplit=string.split(mysettings["PATH"],":")
+ else:
+ mysplit=[]
+ if PORTAGE_BIN_PATH not in mysplit:
+ mysettings["PATH"]=PORTAGE_BIN_PATH+":"+mysettings["PATH"]
+
+
+ mysettings["BUILD_PREFIX"] = mysettings["PORTAGE_TMPDIR"]+"/portage"
+ mysettings["HOME"] = mysettings["BUILD_PREFIX"]+"/homedir"
+ mysettings["PKG_TMPDIR"] = mysettings["PORTAGE_TMPDIR"]+"/portage-pkg"
+ mysettings["BUILDDIR"] = mysettings["BUILD_PREFIX"]+"/"+mysettings["PF"]
+
+ mysettings["PORTAGE_BASHRC"] = EBUILD_SH_ENV_FILE
+
+ #set up KV variable -- DEP SPEEDUP :: Don't waste time. Keep var persistent.
+ if (mydo!="depend") or not mysettings.has_key("KV"):
+ mykv,err1=ExtractKernelVersion(root+"usr/src/linux")
+ if mykv:
+ # Regular source tree
+ mysettings["KV"]=mykv
+ else:
+ mysettings["KV"]=""
+
+ if (mydo!="depend") or not mysettings.has_key("KVERS"):
+ myso=os.uname()[2]
+ mysettings["KVERS"]=myso[1]
+
+
+ # get possible slot information from the deps file
+ if mydo=="depend":
+ if mysettings.has_key("PORTAGE_DEBUG") and mysettings["PORTAGE_DEBUG"]=="1":
+ # XXX: This needs to use a FD for saving the output into a file.
+ # XXX: Set this up through spawn
+ pass
+ writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
+ if dbkey:
+ mysettings["dbkey"] = dbkey
+ else:
+ mysettings["dbkey"] = mysettings.depcachedir+"/aux_db_key_temp"
+
+ retval = spawn(EBUILD_SH_BINARY+" depend",mysettings)
+ return retval
+
+ logfile=None
+ # Build directory creation isn't required for any of these.
+ if mydo not in ["fetch","digest","manifest"]:
+
+ if not os.path.exists(mysettings["BUILD_PREFIX"]):
+ os.makedirs(mysettings["BUILD_PREFIX"])
+ os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
+ os.chmod(mysettings["BUILD_PREFIX"],00775)
+
+ # Should be ok again to set $T, as sandbox does not depend on it
+ mysettings["T"]=mysettings["BUILDDIR"]+"/temp"
+ if cleanup or mydo=="clean":
+ if os.path.exists(mysettings["T"]):
+ shutil.rmtree(mysettings["T"])
+ if not os.path.exists(mysettings["T"]):
+ os.makedirs(mysettings["T"])
+ os.chown(mysettings["T"],portage_uid,portage_gid)
+ os.chmod(mysettings["T"],02770)
+
+ try: # XXX: negative RESTRICT
+ if not (("nouserpriv" in string.split(mysettings["PORTAGE_RESTRICT"])) or \
+ ("userpriv" in string.split(mysettings["PORTAGE_RESTRICT"]))):
+ if ("userpriv" in features) and (portage_uid and portage_gid):
+ if (secpass==2):
+ if os.path.exists(mysettings["HOME"]):
+ # XXX: Potentially bad, but held down by HOME replacement above.
+ spawn("rm -Rf "+mysettings["HOME"],mysettings, free=1)
+ if not os.path.exists(mysettings["HOME"]):
+ os.makedirs(mysettings["HOME"])
+ elif ("userpriv" in features):
+ print "!!! Disabling userpriv from features... Portage UID/GID not valid."
+ del features[features.index("userpriv")]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Couldn't empty HOME:",mysettings["HOME"]
+ print "!!!",e
+
+ try:
+ # no reason to check for depend since depend returns above.
+ if not os.path.exists(mysettings["BUILD_PREFIX"]):
+ os.makedirs(mysettings["BUILD_PREFIX"])
+ os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
+ if not os.path.exists(mysettings["BUILDDIR"]):
+ os.makedirs(mysettings["BUILDDIR"])
+ os.chown(mysettings["BUILDDIR"],portage_uid,portage_gid)
+ except OSError, e:
+ print "!!! File system problem. (ReadOnly? Out of space?)"
+ print "!!! Perhaps: rm -Rf",mysettings["BUILD_PREFIX"]
+ print "!!!",str(e)
+ return 1
+
+ try:
+ if not os.path.exists(mysettings["HOME"]):
+ os.makedirs(mysettings["HOME"])
+ os.chown(mysettings["HOME"],portage_uid,portage_gid)
+ os.chmod(mysettings["HOME"],02770)
+ except OSError, e:
+ print "!!! File system problem. (ReadOnly? Out of space?)"
+ print "!!! Failed to create fake home directory in BUILDDIR"
+ print "!!!",str(e)
+ return 1
+
+ try:
+ if ("ccache" in features):
+ if (not mysettings.has_key("CCACHE_DIR")) or (mysettings["CCACHE_DIR"]==""):
+ mysettings["CCACHE_DIR"]=mysettings["PORTAGE_TMPDIR"]+"/ccache"
+ if not os.path.exists(mysettings["CCACHE_DIR"]):
+ os.makedirs(mysettings["CCACHE_DIR"])
+ mystat = os.stat(mysettings["CCACHE_DIR"])
+ if ("userpriv" in features):
+ if mystat[stat.ST_UID] != portage_gid or ((mystat[stat.ST_MODE]&02070)!=02070):
+ spawn("chgrp -R "+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chown "+str(portage_uid)+":"+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chmod -R u+rw "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chmod -R g+rw "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ else:
+ if mystat[stat.ST_UID] != 0 or ((mystat[stat.ST_MODE]&02070)!=02070):
+ spawn("chgrp -R "+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chown 0:"+str(portage_gid)+" "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chmod -R u+rw "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ spawn("chmod -R g+rw "+mysettings["CCACHE_DIR"], mysettings, free=1)
+ except OSError, e:
+ print "!!! File system problem. (ReadOnly? Out of space?)"
+ print "!!! Perhaps: rm -Rf",mysettings["BUILD_PREFIX"]
+ print "!!!",str(e)
+ return 1
+
+ #try:
+ # mystat=os.stat(mysettings["CCACHE_DIR"])
+ # if (mystat[stat.ST_GID]!=portage_gid) or ((mystat[stat.ST_MODE]&02070)!=02070):
+ # print "*** Adjusting ccache permissions for portage user..."
+ # os.chown(mysettings["CCACHE_DIR"],portage_uid,portage_gid)
+ # os.chmod(mysettings["CCACHE_DIR"],02770)
+ # spawn("chown -R "+str(portage_uid)+":"+str(portage_gid)+" "+mysettings["CCACHE_DIR"],mysettings, free=1)
+ # spawn("chmod -R g+rw "+mysettings["CCACHE_DIR"],mysettings, free=1)
+ #except SystemExit, e:
+ # raise
+ #except:
+ # pass
+
+ if "distcc" in features:
+ try:
+ if (not mysettings.has_key("DISTCC_DIR")) or (mysettings["DISTCC_DIR"]==""):
+ mysettings["DISTCC_DIR"]=mysettings["PORTAGE_TMPDIR"]+"/portage/.distcc"
+ if not os.path.exists(mysettings["DISTCC_DIR"]):
+ os.makedirs(mysettings["DISTCC_DIR"])
+ os.chown(mysettings["DISTCC_DIR"],portage_uid,portage_gid)
+ os.chmod(mysettings["DISTCC_DIR"],02775)
+ for x in ("/lock", "/state"):
+ if not os.path.exists(mysettings["DISTCC_DIR"]+x):
+ os.mkdir(mysettings["DISTCC_DIR"]+x)
+ os.chown(mysettings["DISTCC_DIR"]+x,portage_uid,portage_gid)
+ os.chmod(mysettings["DISTCC_DIR"]+x,02775)
+ except OSError, e:
+ writemsg("\n!!! File system problem when setting DISTCC_DIR directory permissions.\n")
+ writemsg( "!!! DISTCC_DIR="+str(mysettings["DISTCC_DIR"]+"\n"))
+ writemsg( "!!! "+str(e)+"\n\n")
+ time.sleep(5)
+ features.remove("distcc")
+ mysettings["DISTCC_DIR"]=""
+
+ mysettings["WORKDIR"]=mysettings["BUILDDIR"]+"/work"
+ mysettings["D"]=mysettings["BUILDDIR"]+"/image/"
+
+ if mysettings.has_key("PORT_LOGDIR"):
+ if os.access(mysettings["PORT_LOGDIR"]+"/",os.W_OK):
+ try:
+ os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
+ os.chmod(mysettings["PORT_LOGDIR"],02770)
+ if not mysettings.has_key("LOG_PF") or (mysettings["LOG_PF"] != mysettings["PF"]):
+ mysettings["LOG_PF"]=mysettings["PF"]
+ mysettings["LOG_COUNTER"]=str(db[myroot]["vartree"].dbapi.get_counter_tick_core("/"))
+ logfile="%s/%s-%s.log" % (mysettings["PORT_LOGDIR"],mysettings["LOG_COUNTER"],mysettings["LOG_PF"])
+ except ValueError, e:
+ mysettings["PORT_LOGDIR"]=""
+ print "!!! Unable to chown/chmod PORT_LOGDIR. Disabling logging."
+ print "!!!",e
+ else:
+ print "!!! Cannot create log... No write access / Does not exist"
+ print "!!! PORT_LOGDIR:",mysettings["PORT_LOGDIR"]
+ mysettings["PORT_LOGDIR"]=""
+
+ if mydo=="unmerge":
+ return unmerge(mysettings["CATEGORY"],mysettings["PF"],myroot,mysettings)
+
+ # if any of these are being called, handle them -- running them out of the sandbox -- and stop now.
+ if mydo=="clean":
+ logfile=None
+ if mydo in ["help","clean","setup"]:
+ return spawn(EBUILD_SH_BINARY+" "+mydo,mysettings,debug=debug,free=1,logfile=logfile)
+ elif mydo in ["prerm","postrm","preinst","postinst","config"]:
+ mysettings.load_infodir(pkg_dir)
+ return spawn(EBUILD_SH_BINARY+" "+mydo,mysettings,debug=debug,free=1,logfile=logfile)
+
+ try:
+ mysettings["SLOT"],mysettings["RESTRICT"] = db["/"]["porttree"].dbapi.aux_get(mycpv,["SLOT","RESTRICT"])
+ except (IOError,KeyError):
+ print red("doebuild():")+" aux_get() error reading "+mycpv+"; aborting."
+ sys.exit(1)
+
+ newuris, alist = db["/"]["porttree"].dbapi.getfetchlist(mycpv,mysettings=mysettings)
+ alluris, aalist = db["/"]["porttree"].dbapi.getfetchlist(mycpv,mysettings=mysettings,all=1)
+ mysettings["A"]=string.join(alist," ")
+ mysettings["AA"]=string.join(aalist," ")
+ if ("mirror" in features) or fetchall:
+ fetchme=alluris[:]
+ checkme=aalist[:]
+ elif mydo=="digest":
+ fetchme=alluris[:]
+ checkme=aalist[:]
+ digestfn=mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
+ if os.path.exists(digestfn):
+ mydigests=digestParseFile(digestfn)
+ if mydigests:
+ for x in mydigests:
+ while x in checkme:
+ i = checkme.index(x)
+ del fetchme[i]
+ del checkme[i]
+ else:
+ fetchme=newuris[:]
+ checkme=alist[:]
+
+ try:
+ if not os.path.exists(mysettings["DISTDIR"]):
+ os.makedirs(mysettings["DISTDIR"])
+ if not os.path.exists(mysettings["DISTDIR"]+"/cvs-src"):
+ os.makedirs(mysettings["DISTDIR"]+"/cvs-src")
+ except OSError, e:
+ print "!!! File system problem. (Bad Symlink?)"
+ print "!!! Fetching may fail:",str(e)
+
+ try:
+ mystat=os.stat(mysettings["DISTDIR"]+"/cvs-src")
+ if ((mystat[stat.ST_GID]!=portage_gid) or ((mystat[stat.ST_MODE]&02770)!=02770)) and not listonly:
+ print "*** Adjusting cvs-src permissions for portage user..."
+ os.chown(mysettings["DISTDIR"]+"/cvs-src",0,portage_gid)
+ os.chmod(mysettings["DISTDIR"]+"/cvs-src",02770)
+ spawn("chgrp -R "+str(portage_gid)+" "+mysettings["DISTDIR"]+"/cvs-src", free=1)
+ spawn("chmod -R g+rw "+mysettings["DISTDIR"]+"/cvs-src", free=1)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+ if not fetch(fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
+ return 1
+
+ if mydo=="fetch" and listonly:
+ return 0
+
+ if "digest" in features:
+ #generate digest if it doesn't exist.
+ if mydo=="digest":
+ return (not digestgen(aalist,mysettings,overwrite=1))
+ else:
+ digestgen(aalist,mysettings,overwrite=0)
+ elif mydo=="digest":
+ #since we are calling "digest" directly, recreate the digest even if it already exists
+ return (not digestgen(aalist,mysettings,overwrite=1))
+ if mydo=="manifest":
+ return (not digestgen(aalist,mysettings,overwrite=1,manifestonly=1))
+
+ if not digestcheck(checkme, mysettings, ("strict" in features)):
+ return 1
+
+ if mydo=="fetch":
+ return 0
+
+ #initial dep checks complete; time to process main commands
+
+ nosandbox=(("userpriv" in features) and ("usersandbox" not in features))
+ actionmap={
+ "depend": { "args":(0,1)}, # sandbox / portage
+ "setup": { "args":(1,0)}, # without / root
+ "unpack": {"dep":"setup", "args":(0,1)}, # sandbox / portage
+ "compile": {"dep":"unpack", "args":(nosandbox,1)}, # optional / portage
+ "test": {"dep":"compile", "args":(nosandbox,1)}, # optional / portage
+ "install": {"dep":"test", "args":(0,0)}, # sandbox / root
+ "rpm": {"dep":"install", "args":(0,0)}, # sandbox / root
+ "package": {"dep":"install", "args":(0,0)}, # sandbox / root
+ }
+
+ if mydo in actionmap.keys():
+ if mydo=="package":
+ for x in ["","/"+mysettings["CATEGORY"],"/All"]:
+ if not os.path.exists(mysettings["PKGDIR"]+x):
+ os.makedirs(mysettings["PKGDIR"]+x)
+ # REBUILD CODE FOR TBZ2 --- XXXX
+ return spawnebuild(mydo,actionmap,mysettings,debug,logfile=logfile)
+ elif mydo=="qmerge":
+ #check to ensure install was run. this *only* pops up when users forget it and are using ebuild
+ if not os.path.exists(mysettings["BUILDDIR"]+"/.installed"):
+ print "!!! mydo=qmerge, but install phase hasn't been ran"
+ sys.exit(1)
+ #qmerge is specifically not supposed to do a runtime dep check
+ return merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["BUILDDIR"]+"/build-info",myroot,mysettings)
+ elif mydo=="merge":
+ retval=spawnebuild("install",actionmap,mysettings,debug,alwaysdep=1,logfile=logfile)
+ if retval:
+ return retval
+ return merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["BUILDDIR"]+"/build-info",myroot,mysettings,myebuild=mysettings["EBUILD"])
+ else:
+ print "!!! Unknown mydo:",mydo
+ sys.exit(1)
+
+expandcache={}
+
+def movefile(src,dest,newmtime=None,sstat=None,mysettings=None):
+ """moves a file from src to dest, preserving all permissions and attributes; mtime will
+ be preserved even when moving across filesystems. Returns true on success and false on
+ failure. Move is atomic."""
+ #print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"
+ global lchown
+
+ try:
+ if not sstat:
+ sstat=os.lstat(src)
+ if bsd_chflags:
+ sflags=bsd_chflags.lgetflags(src)
+ if sflags < 0:
+ # Problem getting flags...
+ writemsg("!!! Couldn't get flags for "+dest+"\n")
+ return None
+
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Stating source file failed... movefile()"
+ print "!!!",e
+ return None
+
+ destexists=1
+ try:
+ dstat=os.lstat(dest)
+ except SystemExit, e:
+ raise
+ except:
+ dstat=os.lstat(os.path.dirname(dest))
+ destexists=0
+
+ if bsd_chflags:
+ # Check that we can actually unset schg etc flags...
+ # Clear the flags on source and destination; we'll reinstate them after merging
+ if(destexists):
+ if bsd_chflags.lchflags(dest, 0) < 0:
+ writemsg("!!! Couldn't clear flags on file being merged: \n ")
+ # We might have an immutable flag on the parent dir; save and clear.
+ pflags=bsd_chflags.lgetflags(os.path.dirname(dest))
+ bsd_chflags.lchflags(os.path.dirname(dest), 0)
+
+ # Don't bother checking the return value here; if it fails then the next line will catch it.
+ bsd_chflags.lchflags(src, 0)
+
+ if bsd_chflags.lhasproblems(src)>0 or (destexists and bsd_chflags.lhasproblems(dest)>0) or bsd_chflags.lhasproblems(os.path.dirname(dest))>0:
+ # This is bad: we can't merge the file with these flags set.
+ writemsg("!!! Can't merge file "+dest+" because of flags set\n")
+ return None
+
+ if destexists:
+ if stat.S_ISLNK(dstat[stat.ST_MODE]):
+ try:
+ os.unlink(dest)
+ destexists=0
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+ if stat.S_ISLNK(sstat[stat.ST_MODE]):
+ try:
+ target=os.readlink(src)
+ if mysettings and mysettings["D"]:
+ if target.find(mysettings["D"])==0:
+ target=target[len(mysettings["D"]):]
+ if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
+ os.unlink(dest)
+ if selinux_enabled:
+ sid = selinux.get_lsid(src)
+ selinux.secure_symlink(target,dest,sid)
+ else:
+ os.symlink(target,dest)
+ lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+ if bsd_chflags:
+ # Restore the flags we saved before moving
+ if bsd_chflags.lchflags(dest, sflags) < 0 or bsd_chflags.lchflags(os.path.dirname(dest), pflags) < 0:
+ writemsg("!!! Couldn't restore flags ("+str(flags)+") on " + dest+":\n")
+ writemsg("!!! %s\n" % str(e))
+ return None
+ return os.lstat(dest)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! failed to properly create symlink:"
+ print "!!!",dest,"->",target
+ print "!!!",e
+ return None
+
+ renamefailed=1
+ if sstat[stat.ST_DEV]==dstat[stat.ST_DEV] or selinux_enabled:
+ try:
+ if selinux_enabled:
+ ret=selinux.secure_rename(src,dest)
+ else:
+ ret=os.rename(src,dest)
+ renamefailed=0
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ import errno
+ if e[0]!=errno.EXDEV:
+ # Some random error.
+ print "!!! Failed to move",src,"to",dest
+ print "!!!",e
+ return None
+ # Invalid cross-device-link 'bind' mounted or actually Cross-Device
+ if renamefailed:
+ didcopy=0
+ if stat.S_ISREG(sstat[stat.ST_MODE]):
+ try: # For safety copy then move it over.
+ if selinux_enabled:
+ selinux.secure_copy(src,dest+"#new")
+ selinux.secure_rename(dest+"#new",dest)
+ else:
+ shutil.copyfile(src,dest+"#new")
+ os.rename(dest+"#new",dest)
+ didcopy=1
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print '!!! copy',src,'->',dest,'failed.'
+ print "!!!",e
+ return None
+ else:
+ #we don't yet handle special, so we need to fall back to /bin/mv
+ if selinux_enabled:
+ a=commands.getstatusoutput(MOVE_BINARY+" -c -f "+"'"+src+"' '"+dest+"'")
+ else:
+ a=commands.getstatusoutput(MOVE_BINARY+" -f "+"'"+src+"' '"+dest+"'")
+ if a[0]!=0:
+ print "!!! Failed to move special file:"
+ print "!!! '"+src+"' to '"+dest+"'"
+ print "!!!",a
+ return None # failure
+ try:
+ if didcopy:
+ lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+ os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
+ os.unlink(src)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Failed to chown/chmod/unlink in movefile()"
+ print "!!!",dest
+ print "!!!",e
+ return None
+
+ if newmtime:
+ os.utime(dest,(newmtime,newmtime))
+ else:
+ os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
+ newmtime=sstat[stat.ST_MTIME]
+
+ if bsd_chflags:
+ # Restore the flags we saved before moving
+ if bsd_chflags.lchflags(dest, sflags) < 0 or bsd_chflags.lchflags(os.path.dirname(dest), pflags) < 0:
+ writemsg("!!! Couldn't restore flags ("+str(sflags)+") on " + dest+":\n")
+ return None
+
+ return newmtime
+
+def merge(mycat,mypkg,pkgloc,infloc,myroot,mysettings,myebuild=None):
+ mylink=dblink(mycat,mypkg,myroot,mysettings)
+ return mylink.merge(pkgloc,infloc,myroot,myebuild)
+
+def unmerge(cat,pkg,myroot,mysettings,mytrimworld=1):
+ mylink=dblink(cat,pkg,myroot,mysettings)
+ if mylink.exists():
+ mylink.unmerge(trimworld=mytrimworld,cleanup=1)
+ mylink.delete()
+
+def relparse(myver):
+ "converts last version part into three components"
+ number=0
+ suffix=0
+ endtype=0
+ endnumber=0
+
+ mynewver=string.split(myver,"_")
+ myver=mynewver[0]
+
+ #normal number or number with letter at end
+ divider=len(myver)-1
+ if myver[divider:] not in "1234567890":
+ #letter at end
+ suffix=ord(myver[divider:])
+ number=string.atof(myver[0:divider])
+ else:
+ number=string.atof(myver)
+
+ if len(mynewver)==2:
+ #an endversion
+ for x in endversion_keys:
+ elen=len(x)
+ if mynewver[1][:elen] == x:
+ match=1
+ endtype=endversion[x]
+ try:
+ endnumber=string.atof(mynewver[1][elen:])
+ except SystemExit, e:
+ raise
+ except:
+ endnumber=0
+ break
+ return [number,suffix,endtype,endnumber]
+
+#returns 1 if valid version string, else 0
+# valid string in format: <v1>.<v2>...<vx>[a-z,_{endversion}[vy]]
+# ververify doesn't do package rev.
+
+vercache={}
+def ververify(myorigval,silent=1):
+ try:
+ return vercache[myorigval]
+ except KeyError:
+ pass
+ if len(myorigval)==0:
+ if not silent:
+ print "!!! Name error: package contains empty \"-\" part."
+ return 0
+ myval=string.split(myorigval,'.')
+ if len(myval)==0:
+ if not silent:
+ print "!!! Name error: empty version string."
+ vercache[myorigval]=0
+ return 0
+ #all but the last version must be a numeric
+ for x in myval[:-1]:
+ if not len(x):
+ if not silent:
+ print "!!! Name error in",myorigval+": two decimal points in a row"
+ vercache[myorigval]=0
+ return 0
+ try:
+ foo=int(x)
+ except SystemExit, e:
+ raise
+ except:
+ if not silent:
+ print "!!! Name error in",myorigval+": \""+x+"\" is not a valid version component."
+ vercache[myorigval]=0
+ return 0
+ if not len(myval[-1]):
+ if not silent:
+ print "!!! Name error in",myorigval+": two decimal points in a row"
+ vercache[myorigval]=0
+ return 0
+ try:
+ foo=int(myval[-1])
+ vercache[myorigval]=1
+ return 1
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ #ok, our last component is not a plain number or blank, let's continue
+ if myval[-1][-1] in string.lowercase:
+ try:
+ foo=int(myval[-1][:-1])
+ vercache[myorigval]=1
+ return 1
+ # 1a, 2.0b, etc.
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ #ok, maybe we have a 1_alpha or 1_beta2; let's see
+ #ep="endpart"
+ ep=string.split(myval[-1],"_")
+ if len(ep)!=2:
+ if not silent:
+ print "!!! Name error in",myorigval
+ vercache[myorigval]=0
+ return 0
+ try:
+ foo=int(ep[0][-1])
+ chk=ep[0]
+ except SystemExit, e:
+ raise
+ except:
+ # because it's ok last char is not numeric. example: foo-1.0.0a_pre1
+ chk=ep[0][:-1]
+
+ try:
+ foo=int(chk)
+ except SystemExit, e:
+ raise
+ except:
+ #this needs to be numeric or numeric+single letter,
+ #i.e. the "1" in "1_alpha" or "1a_alpha"
+ if not silent:
+ print "!!! Name error in",myorigval+": characters before _ must be numeric or numeric+single letter"
+ vercache[myorigval]=0
+ return 0
+ for mye in endversion_keys:
+ if ep[1][0:len(mye)]==mye:
+ if len(mye)==len(ep[1]):
+ #no trailing numeric; ok
+ vercache[myorigval]=1
+ return 1
+ else:
+ try:
+ foo=int(ep[1][len(mye):])
+ vercache[myorigval]=1
+ return 1
+ except SystemExit, e:
+ raise
+ except:
+ #if no endversions work, *then* we return 0
+ pass
+ if not silent:
+ print "!!! Name error in",myorigval
+ vercache[myorigval]=0
+ return 0
+
+def isvalidatom(atom):
+ mycpv_cps = catpkgsplit(dep_getcpv(atom))
+ operator = get_operator(atom)
+ if operator:
+ if mycpv_cps and mycpv_cps[0] != "null":
+ # >=cat/pkg-1.0
+ return 1
+ else:
+ # >=cat/pkg or >=pkg-1.0 (no category)
+ return 0
+ if mycpv_cps:
+ # cat/pkg-1.0
+ return 0
+
+ if (len(string.split(atom, '/'))==2):
+ # cat/pkg
+ return 1
+ else:
+ return 0
+
+def isjustname(mypkg):
+ myparts=string.split(mypkg,'-')
+ for x in myparts:
+ if ververify(x):
+ return 0
+ return 1
+
+iscache={}
+def isspecific(mypkg):
+ "now supports packages with no category"
+ try:
+ return iscache[mypkg]
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ mysplit=string.split(mypkg,"/")
+ if not isjustname(mysplit[-1]):
+ iscache[mypkg]=1
+ return 1
+ iscache[mypkg]=0
+ return 0
+
+# This function can be used as a package verification function, i.e.
+# "pkgsplit("foo-1.2-1") will return None if foo-1.2-1 isn't a valid
+# package (with version) name. If it is a valid name, pkgsplit will
+# return a list containing: [ pkgname, pkgversion(norev), pkgrev ].
+# For foo-1.2-1, this list would be [ "foo", "1.2", "1" ]. For
+# Mesa-3.0, this list would be [ "Mesa", "3.0", "0" ].
+pkgcache={}
+
+def pkgsplit(mypkg,silent=1):
+ try:
+ if not pkgcache[mypkg]:
+ return None
+ return pkgcache[mypkg][:]
+ except KeyError:
+ pass
+ myparts=string.split(mypkg,'-')
+ if len(myparts)<2:
+ if not silent:
+ print "!!! Name error in",mypkg+": missing a version or name part."
+ pkgcache[mypkg]=None
+ return None
+ for x in myparts:
+ if len(x)==0:
+ if not silent:
+ print "!!! Name error in",mypkg+": empty \"-\" part."
+ pkgcache[mypkg]=None
+ return None
+ #verify rev
+ revok=0
+ myrev=myparts[-1]
+ if len(myrev) and myrev[0]=="r":
+ try:
+ int(myrev[1:])
+ revok=1
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ if revok:
+ if ververify(myparts[-2]):
+ if len(myparts)==2:
+ pkgcache[mypkg]=None
+ return None
+ else:
+ for x in myparts[:-2]:
+ if ververify(x):
+ pkgcache[mypkg]=None
+ return None
+ #names can't have versiony looking parts
+ myval=[string.join(myparts[:-2],"-"),myparts[-2],myparts[-1]]
+ pkgcache[mypkg]=myval
+ return myval
+ else:
+ pkgcache[mypkg]=None
+ return None
+
+ elif ververify(myparts[-1],silent=silent):
+ if len(myparts)==1:
+ if not silent:
+ print "!!! Name error in",mypkg+": missing name part."
+ pkgcache[mypkg]=None
+ return None
+ else:
+ for x in myparts[:-1]:
+ if ververify(x):
+ if not silent:
+ print "!!! Name error in",mypkg+": multiple version parts."
+ pkgcache[mypkg]=None
+ return None
+ myval=[string.join(myparts[:-1],"-"),myparts[-1],"r0"]
+ pkgcache[mypkg]=myval[:]
+ return myval
+ else:
+ pkgcache[mypkg]=None
+ return None
+
+def getCPFromCPV(mycpv):
+ """Calls pkgsplit on a cpv and returns only the cp."""
+ return pkgsplit(mycpv)[0]
+
+catcache={}
+def catpkgsplit(mydata,silent=1):
+ "returns [cat, pkgname, version, rev ]"
+ try:
+ if not catcache[mydata]:
+ return None
+ return catcache[mydata][:]
+ except KeyError:
+ pass
+ mysplit=mydata.split("/")
+ p_split=None
+ if len(mysplit)==1:
+ retval=["null"]
+ p_split=pkgsplit(mydata,silent=silent)
+ elif len(mysplit)==2:
+ retval=[mysplit[0]]
+ p_split=pkgsplit(mysplit[1],silent=silent)
+ if not p_split:
+ catcache[mydata]=None
+ return None
+ retval.extend(p_split)
+ catcache[mydata]=retval
+ return retval
+
+# vercmp:
+# This takes two version strings and returns an integer to tell you whether
+# the versions are the same, val1>val2 or val2>val1.
+vcmpcache={}
+def vercmp(val1,val2):
+ if val1==val2:
+ #quick short-circuit
+ return 0
+ valkey=val1+" "+val2
+ try:
+ return vcmpcache[valkey]
+ try:
+ return -vcmpcache[val2+" "+val1]
+ except KeyError:
+ pass
+ except KeyError:
+ pass
+
+ # consider 1_p2 vc 1.1
+ # after expansion will become (1_p2,0) vc (1,1)
+ # then 1_p2 is compared with 1 before 0 is compared with 1
+ # to solve the bug we need to convert it to (1,0_p2)
+ # by splitting _prepart part and adding it back _after_expansion
+ val1_prepart = val2_prepart = ''
+ if val1.count('_'):
+ val1, val1_prepart = val1.split('_', 1)
+ if val2.count('_'):
+ val2, val2_prepart = val2.split('_', 1)
+
+ # replace '-' by '.'
+ # FIXME: Is it needed? can val1/2 contain '-'?
+ val1=string.split(val1,'-')
+ if len(val1)==2:
+ val1[0]=val1[0]+"."+val1[1]
+ val2=string.split(val2,'-')
+ if len(val2)==2:
+ val2[0]=val2[0]+"."+val2[1]
+
+ val1=string.split(val1[0],'.')
+ val2=string.split(val2[0],'.')
+
+ #add back decimal point so that .03 does not become "3" !
+ for x in range(1,len(val1)):
+ if val1[x][0] == '0' :
+ val1[x]='.' + val1[x]
+ for x in range(1,len(val2)):
+ if val2[x][0] == '0' :
+ val2[x]='.' + val2[x]
+
+ # extend version numbers
+ if len(val2)<len(val1):
+ val2.extend(["0"]*(len(val1)-len(val2)))
+ elif len(val1)<len(val2):
+ val1.extend(["0"]*(len(val2)-len(val1)))
+
+ # add back _prepart tails
+ if val1_prepart:
+ val1[-1] += '_' + val1_prepart
+ if val2_prepart:
+ val2[-1] += '_' + val2_prepart
+ #The above code will extend version numbers out so they
+ #have the same number of digits.
+ for x in range(0,len(val1)):
+ cmp1=relparse(val1[x])
+ cmp2=relparse(val2[x])
+ for y in range(0,4):
+ myret=cmp1[y]-cmp2[y]
+ if myret != 0:
+ vcmpcache[valkey]=myret
+ return myret
+ vcmpcache[valkey]=0
+ return 0
+
+
+def pkgcmp(pkg1,pkg2):
+ """if returnval is less than zero, then pkg2 is newer than pkg1, zero if equal and positive if older."""
+ if pkg1[0] != pkg2[0]:
+ return None
+ mycmp=vercmp(pkg1[1],pkg2[1])
+ if mycmp>0:
+ return 1
+ if mycmp<0:
+ return -1
+ r1=int(pkg1[2][1:])
+ r2=int(pkg2[2][1:])
+ if r1>r2:
+ return 1
+ if r2>r1:
+ return -1
+ return 0
+
+def dep_parenreduce(mysplit,mypos=0):
+ "Accepts a list of strings, and converts '(' and ')' surrounded items to sub-lists"
+ while (mypos<len(mysplit)):
+ if (mysplit[mypos]=="("):
+ firstpos=mypos
+ mypos=mypos+1
+ while (mypos<len(mysplit)):
+ if mysplit[mypos]==")":
+ mysplit[firstpos:mypos+1]=[mysplit[firstpos+1:mypos]]
+ mypos=firstpos
+ break
+ elif mysplit[mypos]=="(":
+ #recurse
+ mysplit=dep_parenreduce(mysplit,mypos=mypos)
+ mypos=mypos+1
+ mypos=mypos+1
+ return mysplit
+
+def dep_opconvert(mysplit,myuse,mysettings):
+ "Does dependency operator conversion"
+
+ #check_config_instance(mysettings)
+
+ mypos=0
+ newsplit=[]
+ while mypos<len(mysplit):
+ if type(mysplit[mypos])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos],myuse,mysettings))
+ mypos += 1
+ elif mysplit[mypos]==")":
+ #mismatched paren, error
+ return None
+ elif mysplit[mypos]=="||":
+ if ((mypos+1)>=len(mysplit)) or (type(mysplit[mypos+1])!=types.ListType):
+ # || must be followed by paren'd list
+ return None
+ try:
+ mynew=dep_opconvert(mysplit[mypos+1],myuse,mysettings)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print "!!! Unable to satisfy OR dependency:",string.join(mysplit," || ")
+ raise e
+ mynew[0:0]=["||"]
+ newsplit.append(mynew)
+ mypos += 2
+ elif mysplit[mypos][-1]=="?":
+ #uses clause, i.e "gnome? ( foo bar )"
+ #this is a quick and dirty hack so that repoman can enable all USE vars:
+ if (len(myuse)==1) and (myuse[0]=="*") and mysettings:
+ # enable it even if it's ! (for repoman) but kill it if it's
+ # an arch variable that isn't for this arch. XXX Sparc64?
+ k=mysplit[mypos][:-1]
+ if k[0]=="!":
+ k=k[1:]
+ if k not in archlist and k not in mysettings.usemask:
+ enabled=1
+ elif k in archlist:
+ if k==mysettings["ARCH"]:
+ if mysplit[mypos][0]=="!":
+ enabled=0
+ else:
+ enabled=1
+ elif mysplit[mypos][0]=="!":
+ enabled=1
+ else:
+ enabled=0
+ else:
+ enabled=0
+ else:
+ if mysplit[mypos][0]=="!":
+ myusevar=mysplit[mypos][1:-1]
+ if myusevar in myuse:
+ enabled=0
+ else:
+ enabled=1
+ else:
+ myusevar=mysplit[mypos][:-1]
+ if myusevar in myuse:
+ enabled=1
+ else:
+ enabled=0
+ if (mypos+2<len(mysplit)) and (mysplit[mypos+2]==":"):
+ #colon mode
+ if enabled:
+ #choose the first option
+ if type(mysplit[mypos+1])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos+1],myuse,mysettings))
+ else:
+ newsplit.append(mysplit[mypos+1])
+ else:
+ #choose the alternate option
+ if type(mysplit[mypos+1])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos+3],myuse,mysettings))
+ else:
+ newsplit.append(mysplit[mypos+3])
+ mypos += 4
+ else:
+ #normal use mode
+ if enabled:
+ if type(mysplit[mypos+1])==types.ListType:
+ newsplit.append(dep_opconvert(mysplit[mypos+1],myuse,mysettings))
+ else:
+ newsplit.append(mysplit[mypos+1])
+ #otherwise, continue.
+ mypos += 2
+ else:
+ #normal item
+ newsplit.append(mysplit[mypos])
+ mypos += 1
+ return newsplit
+
+def dep_virtual(mysplit, mysettings):
+ "Does virtual dependency conversion"
+
+
+
+ newsplit=[]
+ for x in mysplit:
+ if type(x)==types.ListType:
+ newsplit.append(dep_virtual(x, mysettings))
+ else:
+ mykey=dep_getkey(x)
+ if mysettings.virtuals.has_key(mykey):
+ if len(mysettings.virtuals[mykey])==1:
+ a=string.replace(x, mykey, mysettings.virtuals[mykey][0])
+ else:
+ if x[0]=="!":
+ # blocker needs "and" not "or(||)".
+ a=[]
+ else:
+ a=['||']
+ for y in mysettings.virtuals[mykey]:
+ a.append(string.replace(x, mykey, y))
+ newsplit.append(a)
+ else:
+ newsplit.append(x)
+ return newsplit
+
+def dep_eval(deplist):
+ if len(deplist)==0:
+ return 1
+ if deplist[0]=="||":
+ #or list; we just need one "1"
+ for x in deplist[1:]:
+ if type(x)==types.ListType:
+ if dep_eval(x)==1:
+ return 1
+ elif x==1:
+ return 1
+ return 0
+ else:
+ for x in deplist:
+ if type(x)==types.ListType:
+ if dep_eval(x)==0:
+ return 0
+ elif x==0 or x==2:
+ return 0
+ return 1
+
+def dep_zapdeps(unreduced,reduced,vardbapi=None,use_binaries=0):
+ """Takes an unreduced and reduced deplist and removes satisfied dependencies.
+ Returned deplist contains steps that must be taken to satisfy dependencies."""
+ writemsg("ZapDeps -- %s\n" % (use_binaries), 2)
+ if unreduced==[] or unreduced==['||'] :
+ return []
+ if unreduced[0]=="||":
+ if dep_eval(reduced):
+ #deps satisfied, return empty list.
+ return []
+ else:
+ #try to find an installed dep.
+ ### We use fakedb when --update now, so we can't use local vardbapi here.
+ ### This should be fixed in the feature.
+ ### see bug 45468.
+ ##if vardbapi:
+ ## mydbapi=vardbapi
+ ##else:
+ ## mydbapi=db[root]["vartree"].dbapi
+ mydbapi=db[root]["vartree"].dbapi
+
+ if db["/"].has_key("porttree"):
+ myportapi=db["/"]["porttree"].dbapi
+ else:
+ myportapi=None
+
+ if use_binaries and db["/"].has_key("bintree"):
+ mybinapi=db["/"]["bintree"].dbapi
+ writemsg("Using bintree...\n",2)
+ else:
+ mybinapi=None
+
+ x=1
+ candidate=[]
+ while x<len(reduced):
+ writemsg("x: %s, reduced[x]: %s\n" % (x,reduced[x]), 2)
+ if (type(reduced[x])==types.ListType):
+ newcand = dep_zapdeps(unreduced[x], reduced[x], vardbapi=vardbapi, use_binaries=use_binaries)
+ candidate.append(newcand)
+ else:
+ if (reduced[x]==False):
+ candidate.append([unreduced[x]])
+ else:
+ candidate.append([])
+ x+=1
+
+ #use installed and no-masked package(s) in portage.
+ for x in candidate:
+ match=1
+ for pkg in x:
+ if not mydbapi.match(pkg):
+ match=0
+ break
+ if myportapi:
+ if not myportapi.match(pkg):
+ match=0
+ break
+ if match:
+ writemsg("Installed match: %s\n" % (x), 2)
+ return x
+
+ # Use binary packages if available.
+ if mybinapi:
+ for x in candidate:
+ match=1
+ for pkg in x:
+ if not mybinapi.match(pkg):
+ match=0
+ break
+ else:
+ writemsg("Binary match: %s\n" % (pkg), 2)
+ if match:
+ writemsg("Binary match final: %s\n" % (x), 2)
+ return x
+
+ #use no-masked package(s) in portage tree
+ if myportapi:
+ for x in candidate:
+ match=1
+ for pkg in x:
+ if not myportapi.match(pkg):
+ match=0
+ break
+ if match:
+ writemsg("Porttree match: %s\n" % (x), 2)
+ return x
+
+ #none of the no-masked pkg, use the first one
+ writemsg("Last resort candidate: %s\n" % (candidate[0]), 2)
+ return candidate[0]
+ else:
+ if dep_eval(reduced):
+ #deps satisfied, return empty list.
+ return []
+ else:
+ returnme=[]
+ x=0
+ while x<len(reduced):
+ if type(reduced[x])==types.ListType:
+ returnme+=dep_zapdeps(unreduced[x],reduced[x], vardbapi=vardbapi, use_binaries=use_binaries)
+ else:
+ if reduced[x]==False:
+ returnme.append(unreduced[x])
+ x += 1
+ return returnme
+
+def dep_getkey(mydep):
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ if mydep[0]=="!":
+ mydep=mydep[1:]
+ if mydep[:2] in [ ">=", "<=" ]:
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~":
+ mydep=mydep[1:]
+ if isspecific(mydep):
+ mysplit=catpkgsplit(mydep)
+ if not mysplit:
+ return mydep
+ return mysplit[0]+"/"+mysplit[1]
+ else:
+ return mydep
+
+def dep_getcpv(mydep):
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ if mydep[0]=="!":
+ mydep=mydep[1:]
+ if mydep[:2] in [ ">=", "<=" ]:
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~":
+ mydep=mydep[1:]
+ return mydep
+
+def cpv_getkey(mycpv):
+ myslash=mycpv.split("/")
+ mysplit=pkgsplit(myslash[-1])
+ mylen=len(myslash)
+ if mylen==2:
+ return myslash[0]+"/"+mysplit[0]
+ elif mylen==1:
+ return mysplit[0]
+ else:
+ return mysplit
+
+def key_expand(mykey,mydb=None,use_cache=1):
+ mysplit=mykey.split("/")
+ if len(mysplit)==1:
+ if mydb and type(mydb)==types.InstanceType:
+ for x in settings.categories:
+ if mydb.cp_list(x+"/"+mykey,use_cache=use_cache):
+ return x+"/"+mykey
+ if virts_p.has_key(mykey):
+ return(virts_p[mykey][0])
+ return "null/"+mykey
+ elif mydb:
+ if type(mydb)==types.InstanceType:
+ if (not mydb.cp_list(mykey,use_cache=use_cache)) and virts and virts.has_key(mykey):
+ return virts[mykey][0]
+ return mykey
+
+def cpv_expand(mycpv,mydb=None,use_cache=1):
+ """Given a string (packagename or virtual) expand it into a valid
+ cat/package string. Virtuals use the mydb to determine which provided
+ virtual is a valid choice and defaults to the first element when there
+ are no installed/available candidates."""
+ myslash=mycpv.split("/")
+ mysplit=pkgsplit(myslash[-1])
+ if len(myslash)>2:
+ # this is illegal case.
+ mysplit=[]
+ mykey=mycpv
+ elif len(myslash)==2:
+ if mysplit:
+ mykey=myslash[0]+"/"+mysplit[0]
+ else:
+ mykey=mycpv
+ if mydb:
+ writemsg("mydb.__class__: %s\n" % (mydb.__class__), 1)
+ if type(mydb)==types.InstanceType:
+ if (not mydb.cp_list(mykey,use_cache=use_cache)) and virts and virts.has_key(mykey):
+ writemsg("virts[%s]: %s\n" % (str(mykey),virts[mykey]), 1)
+ mykey_orig = mykey[:]
+ for vkey in virts[mykey]:
+ if mydb.cp_list(vkey,use_cache=use_cache):
+ mykey = vkey
+ writemsg("virts chosen: %s\n" % (mykey), 1)
+ break
+ if mykey == mykey_orig:
+ mykey=virts[mykey][0]
+ writemsg("virts defaulted: %s\n" % (mykey), 1)
+ #we only perform virtual expansion if we are passed a dbapi
+ else:
+ #specific cpv, no category, ie. "foo-1.0"
+ if mysplit:
+ myp=mysplit[0]
+ else:
+ # "foo" ?
+ myp=mycpv
+ mykey=None
+ matches=[]
+ if mydb:
+ for x in settings.categories:
+ if mydb.cp_list(x+"/"+myp,use_cache=use_cache):
+ matches.append(x+"/"+myp)
+ if (len(matches)>1):
+ raise ValueError, matches
+ elif matches:
+ mykey=matches[0]
+
+ if not mykey and type(mydb)!=types.ListType:
+ if virts_p.has_key(myp):
+ mykey=virts_p[myp][0]
+ #again, we only perform virtual expansion if we have a dbapi (not a list)
+ if not mykey:
+ mykey="null/"+myp
+ if mysplit:
+ if mysplit[2]=="r0":
+ return mykey+"-"+mysplit[1]
+ else:
+ return mykey+"-"+mysplit[1]+"-"+mysplit[2]
+ else:
+ return mykey
+
+def dep_transform(mydep,oldkey,newkey):
+ origdep=mydep
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ prefix=""
+ postfix=""
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ postfix="*"
+ if mydep[:2] in [ ">=", "<=" ]:
+ prefix=mydep[:2]
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~!":
+ prefix=mydep[:1]
+ mydep=mydep[1:]
+ if mydep==oldkey:
+ return prefix+newkey+postfix
+ else:
+ return origdep
+
+def dep_expand(mydep,mydb=None,use_cache=1):
+ if not len(mydep):
+ return mydep
+ if mydep[0]=="*":
+ mydep=mydep[1:]
+ prefix=""
+ postfix=""
+ if mydep[-1]=="*":
+ mydep=mydep[:-1]
+ postfix="*"
+ if mydep[:2] in [ ">=", "<=" ]:
+ prefix=mydep[:2]
+ mydep=mydep[2:]
+ elif mydep[:1] in "=<>~!":
+ prefix=mydep[:1]
+ mydep=mydep[1:]
+ return prefix+cpv_expand(mydep,mydb=mydb,use_cache=use_cache)+postfix
+
+def dep_check(depstring,mydbapi,mysettings,use="yes",mode=None,myuse=None,use_cache=1,use_binaries=0):
+ """Takes a depend string and parses the condition."""
+
+ #check_config_instance(mysettings)
+
+ if use=="all":
+ #enable everything (for repoman)
+ myusesplit=["*"]
+ elif use=="yes":
+ if myuse==None:
+ #default behavior
+ myusesplit = string.split(mysettings["USE"])
+ else:
+ myusesplit = myuse
+ # We've been given useflags to use.
+ #print "USE FLAGS PASSED IN."
+ #print myuse
+ #if "bindist" in myusesplit:
+ # print "BINDIST is set!"
+ #else:
+ # print "BINDIST NOT set."
+ else:
+ #we are being run by autouse(), don't consult USE vars yet.
+ # WE ALSO CANNOT USE SETTINGS
+ myusesplit=[]
+
+ #convert parenthesis to sublists
+ mysplit = portage_dep.paren_reduce(depstring)
+
+ if mysettings:
+ # XXX: use="all" is only used by repoman. Why would repoman checks want
+ # profile-masked USE flags to be enabled?
+ #if use=="all":
+ # mymasks=archlist[:]
+ #else:
+ mymasks=mysettings.usemask+archlist[:]
+
+ while mysettings["ARCH"] in mymasks:
+ del mymasks[mymasks.index(mysettings["ARCH"])]
+ mysplit = portage_dep.use_reduce(mysplit,uselist=myusesplit,masklist=mymasks,matchall=(use=="all"),excludeall=[mysettings["ARCH"]])
+ else:
+ mysplit = portage_dep.use_reduce(mysplit,uselist=myusesplit,matchall=(use=="all"))
+
+ # Do the || conversions
+ mysplit=portage_dep.dep_opconvert(mysplit)
+
+ #convert virtual dependencies to normal packages.
+ mysplit=dep_virtual(mysplit, mysettings)
+ #if mysplit==None, then we have a parse error (paren mismatch or misplaced ||)
+ #up until here, we haven't needed to look at the database tree
+
+ if mysplit==None:
+ return [0,"Parse Error (parentheses mismatch?)"]
+ elif mysplit==[]:
+ #dependencies were reduced to nothing
+ return [1,[]]
+ mysplit2=mysplit[:]
+ mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache)
+ if mysplit2==None:
+ return [0,"Invalid token"]
+
+ writemsg("\n\n\n", 1)
+ writemsg("mysplit: %s\n" % (mysplit), 1)
+ writemsg("mysplit2: %s\n" % (mysplit2), 1)
+ myeval=dep_eval(mysplit2)
+ writemsg("myeval: %s\n" % (myeval), 1)
+
+ if myeval:
+ return [1,[]]
+ else:
+ myzaps = dep_zapdeps(mysplit,mysplit2,vardbapi=mydbapi,use_binaries=use_binaries)
+ mylist = flatten(myzaps)
+ writemsg("myzaps: %s\n" % (myzaps), 1)
+ writemsg("mylist: %s\n" % (mylist), 1)
+ #remove duplicates
+ mydict={}
+ for x in mylist:
+ mydict[x]=1
+ writemsg("mydict: %s\n" % (mydict), 1)
+ return [1,mydict.keys()]
+
+def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
+ "Reduces the deplist to ones and zeros"
+ mypos=0
+ deplist=mydeplist[:]
+ while mypos<len(deplist):
+ if type(deplist[mypos])==types.ListType:
+ #recurse
+ deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache)
+ elif deplist[mypos]=="||":
+ pass
+ else:
+ mykey = dep_getkey(deplist[mypos])
+ if mysettings and mysettings.pprovideddict.has_key(mykey) and \
+ match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
+ deplist[mypos]=True
+ else:
+ if mode:
+ mydep=mydbapi.xmatch(mode,deplist[mypos])
+ else:
+ mydep=mydbapi.match(deplist[mypos],use_cache=use_cache)
+ if mydep!=None:
+ tmp=(len(mydep)>=1)
+ if deplist[mypos][0]=="!":
+ #tmp=not tmp
+ # This is ad-hoc code. We should rewrite this later.. (See #52377)
+ # The reason is that portage uses fakedb when --update option now.
+ # So portage considers that a block package doesn't exist even if it exists.
+ # Then, #52377 happens.
+ # ==== start
+ # emerge checks if it's block or not, so we can always set tmp=False.
+ # but it's not clean..
+ tmp=False
+ # ==== end
+ deplist[mypos]=tmp
+ else:
+ #encountered invalid string
+ return None
+ mypos=mypos+1
+ return deplist
+
+def getmaskingreason(mycpv):
+ global portdb
+ mysplit = catpkgsplit(mycpv)
+ if not mysplit:
+ raise ValueError("invalid CPV: %s" % mycpv)
+ if not portdb.cpv_exists(mycpv):
+ raise KeyError("CPV %s does not exist" % mycpv)
+ mycp=mysplit[0]+"/"+mysplit[1]
+
+ if settings.pmaskdict.has_key(mycp):
+ for x in settings.pmaskdict[mycp]:
+ if mycpv in portdb.xmatch("match-all", x):
+ pmaskfile = open(settings["PORTDIR"]+"/profiles/package.mask")
+ comment = ""
+ l = "\n"
+ while len(l) > 0:
+ l = pmaskfile.readline()
+ if len(l) == 0:
+ pmaskfile.close()
+ return None
+ if l[0] == "#":
+ comment += l
+ elif l == "\n":
+ comment = ""
+ elif l.strip() == x:
+ pmaskfile.close()
+ return comment
+ pmaskfile.close()
+ return None
+
+def getmaskingstatus(mycpv):
+ global portdb
+ mysplit = catpkgsplit(mycpv)
+ if not mysplit:
+ raise ValueError("invalid CPV: %s" % mycpv)
+ if not portdb.cpv_exists(mycpv):
+ raise KeyError("CPV %s does not exist" % mycpv)
+ mycp=mysplit[0]+"/"+mysplit[1]
+
+ rValue = []
+
+ # profile checking
+ revmaskdict=settings.prevmaskdict
+ if revmaskdict.has_key(mycp):
+ for x in revmaskdict[mycp]:
+ if x[0]=="*":
+ myatom = x[1:]
+ else:
+ myatom = x
+ if not match_to_list(mycpv, [myatom]):
+ rValue.append("profile")
+ break
+
+ # package.mask checking
+ maskdict=settings.pmaskdict
+ unmaskdict=settings.punmaskdict
+ if maskdict.has_key(mycp):
+ for x in maskdict[mycp]:
+ if mycpv in portdb.xmatch("match-all", x):
+ unmask=0
+ if unmaskdict.has_key(mycp):
+ for z in unmaskdict[mycp]:
+ if mycpv in portdb.xmatch("match-all",z):
+ unmask=1
+ break
+ if unmask==0:
+ rValue.append("package.mask")
+
+ # keywords checking
+ mygroups = portdb.aux_get(mycpv, ["KEYWORDS"])[0].split()
+ pgroups=groups[:]
+ myarch = settings["ARCH"]
+ pkgdict = settings.pkeywordsdict
+
+ cp = dep_getkey(mycpv)
+ if pkgdict.has_key(cp):
+ matches = match_to_list(mycpv, pkgdict[cp].keys())
+ for match in matches:
+ pgroups.extend(pkgdict[cp][match])
+
+ kmask = "missing"
+
+ for keyword in pgroups:
+ if keyword in mygroups:
+ kmask=None
+
+ if kmask:
+ fallback = None
+ for gp in mygroups:
+ if gp=="*":
+ kmask=None
+ break
+ elif gp=="-*":
+ fallback="-*"
+ elif gp=="-"+myarch:
+ kmask="-"+myarch
+ break
+ elif gp=="~"+myarch:
+ kmask="~"+myarch
+ break
+ if kmask == "missing" and fallback:
+ kmask = fallback
+
+ if kmask:
+ rValue.append(kmask+" keyword")
+ return rValue
+
+def fixdbentries(old_value, new_value, dbdir):
+ """python replacement for the fixdbentries script, replaces old_value
+ with new_value for package names in files in dbdir."""
+ for myfile in [f for f in os.listdir(dbdir) if not f == "CONTENTS"]:
+ f = open(dbdir+"/"+myfile, "r")
+ mycontent = f.read()
+ f.close()
+ if not mycontent.count(old_value):
+ continue
+ old_value = re.escape(old_value);
+ mycontent = re.sub(old_value+"$", new_value, mycontent)
+ mycontent = re.sub(old_value+"(\\s)", new_value+"\\1", mycontent)
+ mycontent = re.sub(old_value+"(-[^a-zA-Z])", new_value+"\\1", mycontent)
+ mycontent = re.sub(old_value+"([^a-zA-Z0-9-])", new_value+"\\1", mycontent)
+ f = open(dbdir+"/"+myfile, "w")
+ f.write(mycontent)
+ f.close()
+
+class packagetree:
+ def __init__(self,virtual,clone=None):
+ if clone:
+ self.tree=clone.tree.copy()
+ self.populated=clone.populated
+ self.virtual=clone.virtual
+ self.dbapi=None
+ else:
+ self.tree={}
+ self.populated=0
+ self.virtual=virtual
+ self.dbapi=None
+
+ def resolve_key(self,mykey):
+ return key_expand(mykey,mydb=self.dbapi)
+
+ def dep_nomatch(self,mypkgdep):
+ mykey=dep_getkey(mypkgdep)
+ nolist=self.dbapi.cp_list(mykey)
+ mymatch=self.dbapi.match(mypkgdep)
+ if not mymatch:
+ return nolist
+ for x in mymatch:
+ if x in nolist:
+ nolist.remove(x)
+ return nolist
+
+ def depcheck(self,mycheck,use="yes",myusesplit=None):
+ return dep_check(mycheck,self.dbapi,use=use,myuse=myusesplit)
+
+ def populate(self):
+ "populates the tree with values"
+ populated=1
+ pass
+
+def best(mymatches):
+ "accepts None arguments; assumes matches are valid."
+ global bestcount
+ if mymatches==None:
+ return ""
+ if not len(mymatches):
+ return ""
+ bestmatch=mymatches[0]
+ p2=catpkgsplit(bestmatch)[1:]
+ for x in mymatches[1:]:
+ p1=catpkgsplit(x)[1:]
+ if pkgcmp(p1,p2)>0:
+ bestmatch=x
+ p2=catpkgsplit(bestmatch)[1:]
+ return bestmatch
+
+def match_to_list(mypkg,mylist):
+ """(pkgname,list)
+ Searches list for entries that matches the package.
+ """
+ matches=[]
+ for x in mylist:
+ if match_from_list(x,[mypkg]):
+ if x not in matches:
+ matches.append(x)
+ return matches
+
+def best_match_to_list(mypkg,mylist):
+ """(pkgname,list)
+ Returns the most specific entry (assumed to be the longest one)
+ that matches the package given.
+ """
+ # XXX Assumption is wrong sometimes.
+ maxlen = 0
+ bestm = None
+ for x in match_to_list(mypkg,mylist):
+ if len(x) > maxlen:
+ maxlen = len(x)
+ bestm = x
+ return bestm
+
+def catsplit(mydep):
+ return mydep.split("/", 1)
+
+def get_operator(mydep):
+ """
+ returns '~', '=', '>', '<', '=*', '>=', or '<='
+ """
+ if mydep[0] == "~":
+ operator = "~"
+ elif mydep[0] == "=":
+ if mydep[-1] == "*":
+ operator = "=*"
+ else:
+ operator = "="
+ elif mydep[0] in "><":
+ if len(mydep) > 1 and mydep[1] == "=":
+ operator = mydep[0:2]
+ else:
+ operator = mydep[0]
+ else:
+ operator = None
+
+ return operator
+
+
+def match_from_list(mydep,candidate_list):
+ if mydep[0] == "!":
+ mydep = mydep[1:]
+
+ mycpv = dep_getcpv(mydep)
+ mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
+
+ if not mycpv_cps:
+ cat,pkg = catsplit(mycpv)
+ ver = None
+ rev = None
+ else:
+ cat,pkg,ver,rev = mycpv_cps
+ if mydep == mycpv:
+ raise KeyError, "Specific key requires an operator (%s) (try adding an '=')" % (mydep)
+
+ if ver and rev:
+ operator = get_operator(mydep)
+ if not operator:
+ writemsg("!!! Invalid atom: %s\n" % mydep)
+ return []
+ else:
+ operator = None
+
+ mylist = []
+
+ if operator == None:
+ for x in candidate_list:
+ xs = pkgsplit(x)
+ if xs == None:
+ if x != mycpv:
+ continue
+ elif xs[0] != mycpv:
+ continue
+ mylist.append(x)
+
+ elif operator == "=": # Exact match
+ if mycpv in candidate_list:
+ mylist = [mycpv]
+
+ elif operator == "=*": # glob match
+ # The old verion ignored _tag suffixes... This one doesn't.
+ for x in candidate_list:
+ if x[0:len(mycpv)] == mycpv:
+ mylist.append(x)
+
+ elif operator == "~": # version, any revision, match
+ for x in candidate_list:
+ xs = catpkgsplit(x)
+ if xs[0:2] != mycpv_cps[0:2]:
+ continue
+ if xs[2] != ver:
+ continue
+ mylist.append(x)
+
+ elif operator in [">", ">=", "<", "<="]:
+ for x in candidate_list:
+ try:
+ result = pkgcmp(pkgsplit(x), [cat+"/"+pkg,ver,rev])
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("\nInvalid package name: %s\n" % x)
+ sys.exit(73)
+ if result == None:
+ continue
+ elif operator == ">":
+ if result > 0:
+ mylist.append(x)
+ elif operator == ">=":
+ if result >= 0:
+ mylist.append(x)
+ elif operator == "<":
+ if result < 0:
+ mylist.append(x)
+ elif operator == "<=":
+ if result <= 0:
+ mylist.append(x)
+ else:
+ raise KeyError, "Unknown operator: %s" % mydep
+ else:
+ raise KeyError, "Unknown operator: %s" % mydep
+
+
+ return mylist
+
+
+def match_from_list_original(mydep,mylist):
+ """(dep,list)
+ Reduces the list down to those that fit the dep
+ """
+ mycpv=dep_getcpv(mydep)
+ if isspecific(mycpv):
+ cp_key=catpkgsplit(mycpv)
+ if cp_key==None:
+ return []
+ else:
+ cp_key=None
+ #Otherwise, this is a special call; we can only select out of the ebuilds specified in the specified mylist
+ if (mydep[0]=="="):
+ if cp_key==None:
+ return []
+ if mydep[-1]=="*":
+ #example: "=sys-apps/foo-1.0*"
+ try:
+ #now, we grab the version of our dependency...
+ mynewsplit=string.split(cp_key[2],'.')
+ #split it...
+ mynewsplit[-1]=`int(mynewsplit[-1])+1`
+ #and increment the last digit of the version by one.
+ #We don't need to worry about _pre and friends because they're not supported with '*' deps.
+ new_v=string.join(mynewsplit,".")+"_alpha0"
+ #new_v will be used later in the code when we do our comparisons using pkgcmp()
+ except SystemExit, e:
+ raise
+ except:
+ #erp, error.
+ return []
+ mynodes=[]
+ cmp1=cp_key[1:]
+ cmp1[1]=cmp1[1]+"_alpha0"
+ cmp2=[cp_key[1],new_v,"r0"]
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #hrm, invalid entry. Continue.
+ continue
+ #skip entries in our list that do not have matching categories
+ if cp_key[0]!=cp_x[0]:
+ continue
+ # ok, categories match. Continue to next step.
+ if ((pkgcmp(cp_x[1:],cmp1)>=0) and (pkgcmp(cp_x[1:],cmp2)<0)):
+ # entry is >= the version in specified in our dependency, and <= the version in our dep + 1; add it:
+ mynodes.append(x)
+ return mynodes
+ else:
+ # Does our stripped key appear literally in our list? If so, we have a match; if not, we don't.
+ if mycpv in mylist:
+ return [mycpv]
+ else:
+ return []
+ elif (mydep[0]==">") or (mydep[0]=="<"):
+ if cp_key==None:
+ return []
+ if (len(mydep)>1) and (mydep[1]=="="):
+ cmpstr=mydep[0:2]
+ else:
+ cmpstr=mydep[0]
+ mynodes=[]
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #invalid entry; continue.
+ continue
+ if cp_key[0]!=cp_x[0]:
+ continue
+ if eval("pkgcmp(cp_x[1:],cp_key[1:])"+cmpstr+"0"):
+ mynodes.append(x)
+ return mynodes
+ elif mydep[0]=="~":
+ if cp_key==None:
+ return []
+ myrev=-1
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #invalid entry; continue
+ continue
+ if cp_key[0]!=cp_x[0]:
+ continue
+ if cp_key[2]!=cp_x[2]:
+ #if version doesn't match, skip it
+ continue
+ myint = int(cp_x[3][1:])
+ if myint > myrev:
+ myrev = myint
+ mymatch = x
+ if myrev == -1:
+ return []
+ else:
+ return [mymatch]
+ elif cp_key==None:
+ if mydep[0]=="!":
+ return []
+ #we check ! deps in emerge itself, so always returning [] is correct.
+ mynodes=[]
+ cp_key=mycpv.split("/")
+ for x in mylist:
+ cp_x=catpkgsplit(x)
+ if cp_x==None:
+ #invalid entry; continue
+ continue
+ if cp_key[0]!=cp_x[0]:
+ continue
+ if cp_key[1]!=cp_x[1]:
+ continue
+ mynodes.append(x)
+ return mynodes
+ else:
+ return []
+
+
+class portagetree:
+ def __init__(self,root="/",virtual=None,clone=None):
+ global portdb
+ if clone:
+ self.root=clone.root
+ self.portroot=clone.portroot
+ self.pkglines=clone.pkglines
+ else:
+ self.root=root
+ self.portroot=settings["PORTDIR"]
+ self.virtual=virtual
+ self.dbapi=portdb
+
+ def dep_bestmatch(self,mydep):
+ "compatibility method"
+ mymatch=self.dbapi.xmatch("bestmatch-visible",mydep)
+ if mymatch==None:
+ return ""
+ return mymatch
+
+ def dep_match(self,mydep):
+ "compatibility method"
+ mymatch=self.dbapi.xmatch("match-visible",mydep)
+ if mymatch==None:
+ return []
+ return mymatch
+
+ def exists_specific(self,cpv):
+ return self.dbapi.cpv_exists(cpv)
+
+ def getallnodes(self):
+ """new behavior: these are all *unmasked* nodes. There may or may not be available
+ masked package for nodes in this nodes list."""
+ return self.dbapi.cp_all()
+
+ def getname(self,pkgname):
+ "returns file location for this particular package (DEPRECATED)"
+ if not pkgname:
+ return ""
+ mysplit=string.split(pkgname,"/")
+ psplit=pkgsplit(mysplit[1])
+ return self.portroot+"/"+mysplit[0]+"/"+psplit[0]+"/"+mysplit[1]+".ebuild"
+
+ def resolve_specific(self,myspec):
+ cps=catpkgsplit(myspec)
+ if not cps:
+ return None
+ mykey=key_expand(cps[0]+"/"+cps[1],mydb=self.dbapi)
+ mykey=mykey+"-"+cps[2]
+ if cps[3]!="r0":
+ mykey=mykey+"-"+cps[3]
+ return mykey
+
+ def depcheck(self,mycheck,use="yes",myusesplit=None):
+ return dep_check(mycheck,self.dbapi,use=use,myuse=myusesplit)
+
+ def getslot(self,mycatpkg):
+ "Get a slot for a catpkg; assume it exists."
+ myslot = ""
+ try:
+ myslot=self.dbapi.aux_get(mycatpkg,["SLOT"])[0]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+ return myslot
+
+
+class dbapi:
+ def __init__(self):
+ pass
+
+ def close_caches(self):
+ pass
+
+ def cp_list(self,cp,use_cache=1):
+ return
+
+ def aux_get(self,mycpv,mylist):
+ "stub code for returning auxiliary db information, such as SLOT, DEPEND, etc."
+ 'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
+ 'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or [] if mycpv not found'
+ raise NotImplementedError
+
+ def match(self,origdep,use_cache=1):
+ mydep=dep_expand(origdep,mydb=self)
+ mykey=dep_getkey(mydep)
+ mycat=mykey.split("/")[0]
+ return match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+
+ def match2(self,mydep,mykey,mylist):
+ writemsg("DEPRECATED: dbapi.match2\n")
+ match_from_list(mydep,mylist)
+
+ def counter_tick(self,myroot,mycpv=None):
+ return self.counter_tick_core(myroot,incrementing=1,mycpv=mycpv)
+
+ def get_counter_tick_core(self,myroot,mycpv=None):
+ return self.counter_tick_core(myroot,incrementing=0,mycpv=mycpv)+1
+
+ def counter_tick_core(self,myroot,incrementing=1,mycpv=None):
+ "This method will grab the next COUNTER value and record it back to the global file. Returns new counter value."
+ cpath=myroot+"var/cache/edb/counter"
+ changed=0
+ min_counter = 0
+ if mycpv:
+ mysplit = pkgsplit(mycpv)
+ for x in self.match(mysplit[0],use_cache=0):
+ # fixed bug #41062
+ if x==mycpv:
+ continue
+ try:
+ old_counter = long(self.aux_get(x,["COUNTER"])[0])
+ writemsg("COUNTER '%d' '%s'\n" % (old_counter, x),1)
+ except SystemExit, e:
+ raise
+ except:
+ old_counter = 0
+ writemsg("!!! BAD COUNTER in '%s'\n" % (x))
+ if old_counter > min_counter:
+ min_counter = old_counter
+
+ # We write our new counter value to a new file that gets moved into
+ # place to avoid filesystem corruption.
+ if os.path.exists(cpath):
+ cfile=open(cpath, "r")
+ try:
+ counter=long(cfile.readline())
+ except (ValueError,OverflowError):
+ try:
+ counter=long(commands.getoutput("for FILE in $(find /"+VDB_PATH+" -type f -name COUNTER); do echo $(<${FILE}); done | sort -n | tail -n1 | tr -d '\n'"))
+ writemsg("!!! COUNTER was corrupted; resetting to value of %d\n" % counter)
+ changed=1
+ except (ValueError,OverflowError):
+ writemsg("!!! COUNTER data is corrupt in pkg db. The values need to be\n")
+ writemsg("!!! corrected/normalized so that portage can operate properly.\n")
+ writemsg("!!! A simple solution is not yet available so try #gentoo on IRC.\n")
+ sys.exit(2)
+ cfile.close()
+ else:
+ try:
+ counter=long(commands.getoutput("for FILE in $(find /"+VDB_PATH+" -type f -name COUNTER); do echo $(<${FILE}); done | sort -n | tail -n1 | tr -d '\n'"))
+ writemsg("!!! Global counter missing. Regenerated from counter files to: %s\n" % counter)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("!!! Initializing global counter.\n")
+ counter=long(0)
+ changed=1
+
+ if counter < min_counter:
+ counter = min_counter+1000
+ changed = 1
+
+ if incrementing or changed:
+
+ #increment counter
+ counter += 1
+ # update new global counter file
+ newcpath=cpath+".new"
+ newcfile=open(newcpath,"w")
+ newcfile.write(str(counter))
+ newcfile.close()
+ # now move global counter file into place
+ os.rename(newcpath,cpath)
+ return counter
+
+ def invalidentry(self, mypath):
+ if re.search("portage_lockfile$",mypath):
+ if not os.environ.has_key("PORTAGE_MASTER_PID"):
+ writemsg("Lockfile removed: %s\n" % mypath, 1)
+ portage_locks.unlockfile((mypath,None,None))
+ else:
+ # Nothing we can do about it. We're probably sandboxed.
+ pass
+ elif re.search(".*/-MERGING-(.*)",mypath):
+ if os.path.exists(mypath):
+ writemsg(red("INCOMPLETE MERGE:")+" "+mypath+"\n")
+ else:
+ writemsg("!!! Invalid db entry: %s\n" % mypath)
+
+
+
+class fakedbapi(dbapi):
+ "This is a dbapi to use for the emptytree function. It's empty, but things can be added to it."
+ def __init__(self):
+ self.cpvdict={}
+ self.cpdict={}
+
+ def cpv_exists(self,mycpv):
+ return self.cpvdict.has_key(mycpv)
+
+ def cp_list(self,mycp,use_cache=1):
+ if not self.cpdict.has_key(mycp):
+ return []
+ else:
+ return self.cpdict[mycp]
+
+ def cp_all(self):
+ returnme=[]
+ for x in self.cpdict.keys():
+ returnme.extend(self.cpdict[x])
+ return returnme
+
+ def cpv_inject(self,mycpv):
+ """Adds a cpv from the list of available packages."""
+ mycp=cpv_getkey(mycpv)
+ self.cpvdict[mycpv]=1
+ if not self.cpdict.has_key(mycp):
+ self.cpdict[mycp]=[]
+ if not mycpv in self.cpdict[mycp]:
+ self.cpdict[mycp].append(mycpv)
+
+ #def cpv_virtual(self,oldcpv,newcpv):
+ # """Maps a cpv to the list of available packages."""
+ # mycp=cpv_getkey(newcpv)
+ # self.cpvdict[newcpv]=1
+ # if not self.virtdict.has_key(mycp):
+ # self.virtdict[mycp]=[]
+ # if not mycpv in self.virtdict[mycp]:
+ # self.virtdict[mycp].append(oldcpv)
+ # cpv_remove(oldcpv)
+
+ def cpv_remove(self,mycpv):
+ """Removes a cpv from the list of available packages."""
+ mycp=cpv_getkey(mycpv)
+ if self.cpvdict.has_key(mycpv):
+ del self.cpvdict[mycpv]
+ if not self.cpdict.has_key(mycp):
+ return
+ while mycpv in self.cpdict[mycp]:
+ del self.cpdict[mycp][self.cpdict[mycp].index(mycpv)]
+ if not len(self.cpdict[mycp]):
+ del self.cpdict[mycp]
+
+class bindbapi(fakedbapi):
+ def __init__(self,mybintree=None):
+ self.bintree = mybintree
+ self.cpvdict={}
+ self.cpdict={}
+
+ def aux_get(self,mycpv,wants):
+ mysplit = string.split(mycpv,"/")
+ mylist = []
+ tbz2name = mysplit[1]+".tbz2"
+ if self.bintree and not self.bintree.isremote(mycpv):
+ tbz2 = xpak.tbz2(self.bintree.getname(mycpv))
+ for x in wants:
+ if self.bintree and self.bintree.isremote(mycpv):
+ # We use the cache for remote packages
+ if self.bintree.remotepkgs[tbz2name].has_key(x):
+ mylist.append(self.bintree.remotepkgs[tbz2name][x][:]) # [:] Copy String
+ else:
+ mylist.append("")
+ else:
+ myval = tbz2.getfile(x)
+ if myval == None:
+ myval = ""
+ else:
+ myval = string.join(myval.split(),' ')
+ mylist.append(myval)
+
+ return mylist
+
+
+cptot=0
+class vardbapi(dbapi):
+ def __init__(self,root,categories=None):
+ self.root = root[:]
+ #cache for category directory mtimes
+ self.mtdircache = {}
+ #cache for dependency checks
+ self.matchcache = {}
+ #cache for cp_list results
+ self.cpcache = {}
+ self.blockers = None
+ self.categories = copy.deepcopy(categories)
+
+ def cpv_exists(self,mykey):
+ "Tells us whether an actual ebuild exists on disk (no masking)"
+ return os.path.exists(self.root+VDB_PATH+"/"+mykey)
+
+ def cpv_counter(self,mycpv):
+ "This method will grab the COUNTER. Returns a counter value."
+ cdir=self.root+VDB_PATH+"/"+mycpv
+ cpath=self.root+VDB_PATH+"/"+mycpv+"/COUNTER"
+
+ # We write our new counter value to a new file that gets moved into
+ # place to avoid filesystem corruption on XFS (unexpected reboot.)
+ corrupted=0
+ if os.path.exists(cpath):
+ cfile=open(cpath, "r")
+ try:
+ counter=long(cfile.readline())
+ except ValueError:
+ print "portage: COUNTER for",mycpv,"was corrupted; resetting to value of 0"
+ counter=long(0)
+ corrupted=1
+ cfile.close()
+ elif os.path.exists(cdir):
+ mys = pkgsplit(mycpv)
+ myl = self.match(mys[0],use_cache=0)
+ print mys,myl
+ if len(myl) == 1:
+ try:
+ # Only one package... Counter doesn't matter.
+ myf = open(cpath, "w")
+ myf.write("1")
+ myf.flush()
+ myf.close()
+ counter = 1
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! COUNTER file is missing for "+str(mycpv)+" in /var/db.\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.pl or\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.py or\n")
+ writemsg("!!! unmerge this exact version.\n")
+ writemsg("!!! %s\n" % e)
+ sys.exit(1)
+ else:
+ writemsg("!!! COUNTER file is missing for "+str(mycpv)+" in /var/db.\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.pl or\n")
+ writemsg("!!! Please run /usr/lib/portage/bin/fix-db.py or\n")
+ writemsg("!!! remerge the package.\n")
+ sys.exit(1)
+ else:
+ counter=long(0)
+ if corrupted:
+ newcpath=cpath+".new"
+ # update new global counter file
+ newcfile=open(newcpath,"w")
+ newcfile.write(str(counter))
+ newcfile.close()
+ # now move global counter file into place
+ os.rename(newcpath,cpath)
+ return counter
+
+ def cpv_inject(self,mycpv):
+ "injects a real package into our on-disk database; assumes mycpv is valid and doesn't already exist"
+ os.makedirs(self.root+VDB_PATH+"/"+mycpv)
+ counter=db[self.root]["vartree"].dbapi.counter_tick(self.root,mycpv=mycpv)
+ # write local package counter so that emerge clean does the right thing
+ lcfile=open(self.root+VDB_PATH+"/"+mycpv+"/COUNTER","w")
+ lcfile.write(str(counter))
+ lcfile.close()
+
+ def isInjected(self,mycpv):
+ if self.cpv_exists(mycpv):
+ if os.path.exists(self.root+VDB_PATH+"/"+mycpv+"/INJECTED"):
+ return True
+ if not os.path.exists(self.root+VDB_PATH+"/"+mycpv+"/CONTENTS"):
+ return True
+ return False
+
+ def move_ent(self,mylist):
+ origcp=mylist[1]
+ newcp=mylist[2]
+ origmatches=self.match(origcp,use_cache=0)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+ mycpsplit=catpkgsplit(mycpv)
+ mynewcpv=newcp+"-"+mycpsplit[2]
+ mynewcat=newcp.split("/")[0]
+ if mycpsplit[3]!="r0":
+ mynewcpv += "-"+mycpsplit[3]
+ mycpsplit_new = catpkgsplit(mynewcpv)
+ origpath=self.root+VDB_PATH+"/"+mycpv
+ if not os.path.exists(origpath):
+ continue
+ writemsg("@")
+ if not os.path.exists(self.root+VDB_PATH+"/"+mynewcat):
+ #create the directory
+ os.makedirs(self.root+VDB_PATH+"/"+mynewcat)
+ newpath=self.root+VDB_PATH+"/"+mynewcpv
+ if os.path.exists(newpath):
+ #dest already exists; keep this puppy where it is.
+ continue
+ spawn(MOVE_BINARY+" "+origpath+" "+newpath,settings, free=1)
+
+ # We need to rename the ebuild now.
+ old_eb_path = newpath+"/"+mycpsplit[1] +"-"+mycpsplit[2]
+ new_eb_path = newpath+"/"+mycpsplit_new[1]+"-"+mycpsplit[2]
+ if mycpsplit[3] != "r0":
+ old_eb_path += "-"+mycpsplit[3]
+ new_eb_path += "-"+mycpsplit[3]
+ if os.path.exists(old_eb_path+".ebuild"):
+ os.rename(old_eb_path+".ebuild", new_eb_path+".ebuild")
+
+ catfile=open(newpath+"/CATEGORY", "w")
+ catfile.write(mynewcat+"\n")
+ catfile.close()
+
+ dbdir = self.root+VDB_PATH
+ for catdir in listdir(dbdir):
+ catdir = dbdir+"/"+catdir
+ if os.path.isdir(catdir):
+ for pkgdir in listdir(catdir):
+ pkgdir = catdir+"/"+pkgdir
+ if os.path.isdir(pkgdir):
+ fixdbentries(origcp, newcp, pkgdir)
+
+ def move_slot_ent(self,mylist):
+ pkg=mylist[1]
+ origslot=mylist[2]
+ newslot=mylist[3]
+
+ origmatches=self.match(pkg,use_cache=0)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+ origpath=self.root+VDB_PATH+"/"+mycpv
+ if not os.path.exists(origpath):
+ continue
+
+ slot=grabfile(origpath+"/SLOT");
+ if (not slot):
+ continue
+
+ if (slot[0]!=origslot):
+ continue
+
+ writemsg("s")
+ slotfile=open(origpath+"/SLOT", "w")
+ slotfile.write(newslot+"\n")
+ slotfile.close()
+
+ def cp_list(self,mycp,use_cache=1):
+ mysplit=mycp.split("/")
+ if mysplit[0] == '*':
+ mysplit[0] = mysplit[0][1:]
+ try:
+ mystat=os.stat(self.root+VDB_PATH+"/"+mysplit[0])[stat.ST_MTIME]
+ except OSError:
+ mystat=0
+ if use_cache and self.cpcache.has_key(mycp):
+ cpc=self.cpcache[mycp]
+ if cpc[0]==mystat:
+ return cpc[1]
+ list=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+
+ if (list==None):
+ return []
+ returnme=[]
+ for x in list:
+ if x[0] == '-':
+ #writemsg(red("INCOMPLETE MERGE:")+str(x[len("-MERGING-"):])+"\n")
+ continue
+ ps=pkgsplit(x)
+ if not ps:
+ self.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+ continue
+ if len(mysplit) > 1:
+ if ps[0]==mysplit[1]:
+ returnme.append(mysplit[0]+"/"+x)
+ if use_cache:
+ self.cpcache[mycp]=[mystat,returnme]
+ elif self.cpcache.has_key(mycp):
+ del self.cpcache[mycp]
+ return returnme
+
+ def cpv_all(self,use_cache=1):
+ returnme=[]
+ basepath = self.root+VDB_PATH+"/"
+
+ mycats = self.categories
+ if mycats == None:
+ # XXX: CIRCULAR DEP! This helps backwards compat. --NJ (10 Sept 2004)
+ mycats = settings.categories
+
+ for x in mycats:
+ for y in listdir(basepath+x,EmptyOnError=1):
+ subpath = x+"/"+y
+ # -MERGING- should never be a cpv, nor should files.
+ if os.path.isdir(basepath+subpath) and (pkgsplit(y) is not None):
+ returnme += [subpath]
+ return returnme
+
+ def cp_all(self,use_cache=1):
+ mylist = self.cpv_all(use_cache=use_cache)
+ d={}
+ for y in mylist:
+ if y[0] == '*':
+ y = y[1:]
+ mysplit=catpkgsplit(y)
+ if not mysplit:
+ self.invalidentry(self.root+VDB_PATH+"/"+y)
+ continue
+ d[mysplit[0]+"/"+mysplit[1]] = None
+ return d.keys()
+
+ def checkblockers(self,origdep):
+ pass
+
+ def match(self,origdep,use_cache=1):
+ "caching match function"
+ mydep=dep_expand(origdep,mydb=self,use_cache=use_cache)
+ mykey=dep_getkey(mydep)
+ mycat=mykey.split("/")[0]
+ if not use_cache:
+ if self.matchcache.has_key(mycat):
+ del self.mtdircache[mycat]
+ del self.matchcache[mycat]
+ return match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+ try:
+ curmtime=os.stat(self.root+VDB_PATH+"/"+mycat)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except:
+ curmtime=0
+
+ if not self.matchcache.has_key(mycat) or not self.mtdircache[mycat]==curmtime:
+ # clear cache entry
+ self.mtdircache[mycat]=curmtime
+ self.matchcache[mycat]={}
+ if not self.matchcache[mycat].has_key(mydep):
+ mymatch=match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+ self.matchcache[mycat][mydep]=mymatch
+ return self.matchcache[mycat][mydep][:]
+
+ def aux_get(self, mycpv, wants):
+ global auxdbkeys
+ results = []
+ if not self.cpv_exists(mycpv):
+ return []
+ for x in wants:
+ myfn = self.root+VDB_PATH+"/"+str(mycpv)+"/"+str(x)
+ if os.access(myfn,os.R_OK):
+ myf = open(myfn, "r")
+ myd = myf.read()
+ myf.close()
+ myd = re.sub("[\n\r\t]+"," ",myd)
+ myd = re.sub(" +"," ",myd)
+ myd = string.strip(myd)
+ else:
+ myd = ""
+ results.append(myd)
+ return results
+
+
+class vartree(packagetree):
+ "this tree will scan a var/db/pkg database located at root (passed to init)"
+ def __init__(self,root="/",virtual=None,clone=None,categories=None):
+ if clone:
+ self.root = clone.root[:]
+ self.dbapi = copy.deepcopy(clone.dbapi)
+ self.populated = 1
+ else:
+ self.root = root[:]
+ self.dbapi = vardbapi(self.root,categories=categories)
+ self.populated = 1
+
+ def zap(self,mycpv):
+ return
+
+ def inject(self,mycpv):
+ return
+
+ def get_provide(self,mycpv):
+ myprovides=[]
+ try:
+ mylines = grabfile(self.root+VDB_PATH+"/"+mycpv+"/PROVIDE")
+ if mylines:
+ myuse = grabfile(self.root+VDB_PATH+"/"+mycpv+"/USE")
+ myuse = string.split(string.join(myuse))
+ mylines = string.join(mylines)
+ mylines = flatten(portage_dep.use_reduce(portage_dep.paren_reduce(mylines), uselist=myuse))
+ for myprovide in mylines:
+ mys = catpkgsplit(myprovide)
+ if not mys:
+ mys = string.split(myprovide, "/")
+ myprovides += [mys[0] + "/" + mys[1]]
+ return myprovides
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print
+ print "Check " + self.root+VDB_PATH+"/"+mycpv+"/PROVIDE and USE."
+ print "Possibly Invalid: " + str(mylines)
+ print "Exception: "+str(e)
+ print
+ return []
+
+ def get_all_provides(self):
+ myprovides = {}
+ for node in self.getallcpv():
+ for mykey in self.get_provide(node):
+ if myprovides.has_key(mykey):
+ myprovides[mykey] += [node]
+ else:
+ myprovides[mykey] = [node]
+ return myprovides
+
+ def dep_bestmatch(self,mydep,use_cache=1):
+ "compatibility method -- all matches, not just visible ones"
+ #mymatch=best(match(dep_expand(mydep,self.dbapi),self.dbapi))
+ mymatch=best(self.dbapi.match(dep_expand(mydep,mydb=self.dbapi),use_cache=use_cache))
+ if mymatch==None:
+ return ""
+ else:
+ return mymatch
+
+ def dep_match(self,mydep,use_cache=1):
+ "compatibility method -- we want to see all matches, not just visible ones"
+ #mymatch=match(mydep,self.dbapi)
+ mymatch=self.dbapi.match(mydep,use_cache=use_cache)
+ if mymatch==None:
+ return []
+ else:
+ return mymatch
+
+ def exists_specific(self,cpv):
+ return self.dbapi.cpv_exists(cpv)
+
+ def getallcpv(self):
+ """temporary function, probably to be renamed --- Gets a list of all
+ category/package-versions installed on the system."""
+ return self.dbapi.cpv_all()
+
+ def getallnodes(self):
+ """new behavior: these are all *unmasked* nodes. There may or may not be available
+ masked package for nodes in this nodes list."""
+ return self.dbapi.cp_all()
+
+ def exists_specific_cat(self,cpv,use_cache=1):
+ cpv=key_expand(cpv,mydb=self.dbapi,use_cache=use_cache)
+ a=catpkgsplit(cpv)
+ if not a:
+ return 0
+ mylist=listdir(self.root+VDB_PATH+"/"+a[0],EmptyOnError=1)
+ for x in mylist:
+ b=pkgsplit(x)
+ if not b:
+ self.dbapi.invalidentry(self.root+VDB_PATH+"/"+a[0]+"/"+x)
+ continue
+ if a[1]==b[0]:
+ return 1
+ return 0
+
+ def getebuildpath(self,fullpackage):
+ cat,package=fullpackage.split("/")
+ return self.root+VDB_PATH+"/"+fullpackage+"/"+package+".ebuild"
+
+ def getnode(self,mykey,use_cache=1):
+ mykey=key_expand(mykey,mydb=self.dbapi,use_cache=use_cache)
+ if not mykey:
+ return []
+ mysplit=mykey.split("/")
+ mydirlist=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+ returnme=[]
+ for x in mydirlist:
+ mypsplit=pkgsplit(x)
+ if not mypsplit:
+ self.dbapi.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+ continue
+ if mypsplit[0]==mysplit[1]:
+ appendme=[mysplit[0]+"/"+x,[mysplit[0],mypsplit[0],mypsplit[1],mypsplit[2]]]
+ returnme.append(appendme)
+ return returnme
+
+
+ def getslot(self,mycatpkg):
+ "Get a slot for a catpkg; assume it exists."
+ myslot = ""
+ try:
+ myslot=string.join(grabfile(self.root+VDB_PATH+"/"+mycatpkg+"/SLOT"))
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+ return myslot
+
+ def hasnode(self,mykey,use_cache):
+ """Does the particular node (cat/pkg key) exist?"""
+ mykey=key_expand(mykey,mydb=self.dbapi,use_cache=use_cache)
+ mysplit=mykey.split("/")
+ mydirlist=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+ for x in mydirlist:
+ mypsplit=pkgsplit(x)
+ if not mypsplit:
+ self.dbapi.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+ continue
+ if mypsplit[0]==mysplit[1]:
+ return 1
+ return 0
+
+ def populate(self):
+ self.populated=1
+
+# ----------------------------------------------------------------------------
+class eclass_cache:
+ """Maintains the cache information about eclasses used in ebuild."""
+ def __init__(self,porttree_root,settings):
+ self.porttree_root = porttree_root
+ self.settings = settings
+ self.depcachedir = self.settings.depcachedir[:]
+
+ self.dbmodule = self.settings.load_best_module("eclass_cache.dbmodule")
+
+ self.packages = {} # {"PV": {"eclass1": ["location", "_mtime_"]}}
+ self.eclasses = {} # {"Name": ["location","_mtime_"]}
+
+ # don't fool with porttree ordering unless you *ensure* that ebuild.sh's inherit
+ # ordering is *exactly* the same
+ self.porttrees=[self.porttree_root]
+ self.porttrees.extend(self.settings["PORTDIR_OVERLAY"].split())
+ #normalize the path now, so it's not required later.
+ self.porttrees = [os.path.normpath(x) for x in self.porttrees]
+ self.update_eclasses()
+
+ def close_caches(self):
+ for x in self.packages.keys():
+ for y in self.packages[x].keys():
+ try:
+ self.packages[x][y].sync()
+ self.packages[x][y].close()
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ writemsg("Exception when closing DB: %s: %s\n" % (Exception,e))
+ del self.packages[x][y]
+ del self.packages[x]
+
+ def flush_cache(self):
+ self.packages = {}
+ self.eclasses = {}
+ self.update_eclasses()
+
+ def update_eclasses(self):
+ self.eclasses = {}
+ for x in suffix_array(self.porttrees, "/eclass"):
+ if x and os.path.exists(x):
+ dirlist = listdir(x)
+ for y in dirlist:
+ if y[-len(".eclass"):]==".eclass":
+ try:
+ ys=y[:-len(".eclass")]
+ ymtime=os.stat(x+"/"+y)[stat.ST_MTIME]
+ except SystemExit, e:
+ raise
+ except:
+ continue
+ self.eclasses[ys] = [x, ymtime]
+
+ def setup_package(self, location, cat, pkg):
+ if not self.packages.has_key(location):
+ self.packages[location] = {}
+
+ if not self.packages[location].has_key(cat):
+ try:
+ self.packages[location][cat] = self.dbmodule(self.depcachedir+"/"+location, cat+"-eclass", [], uid, portage_gid)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("\n!!! Failed to open the dbmodule for eclass caching.\n")
+ writemsg("!!! Generally these are permission problems. Caught exception follows:\n")
+ writemsg("!!! "+str(e)+"\n")
+ writemsg("!!! Dirname: "+str(self.depcachedir+"/"+location)+"\n")
+ writemsg("!!! Basename: "+str(cat+"-eclass")+"\n\n")
+ sys.exit(123)
+
+ def sync(self, location, cat, pkg):
+ if self.packages[location].has_key(cat):
+ self.packages[location][cat].sync()
+
+ def update_package(self, location, cat, pkg, eclass_list):
+ self.setup_package(location, cat, pkg)
+ if not eclass_list:
+ return 1
+
+ data = {}
+ for x in eclass_list:
+ if x not in self.eclasses:
+ writemsg("Eclass '%s' does not exist for '%s'\n" % (x, cat+"/"+pkg))
+ return 0
+ data[x] = [self.eclasses[x][0],self.eclasses[x][1]]
+
+ self.packages[location][cat][pkg] = data
+ self.sync(location,cat,pkg)
+ return 1
+
+ def is_current(self, location, cat, pkg, eclass_list):
+ self.setup_package(location, cat, pkg)
+
+ if not eclass_list:
+ return 1
+
+ if not (self.packages[location][cat].has_key(pkg) and self.packages[location][cat][pkg] and eclass_list):
+ return 0
+
+ myp = self.packages[location][cat][pkg]
+ for x in eclass_list:
+ if not (x in self.eclasses and x in myp and myp[x] == self.eclasses[x]):
+ return 0
+
+ return 1
+
+# ----------------------------------------------------------------------------
+
+auxdbkeys=[
+ 'DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
+ 'RESTRICT', 'HOMEPAGE', 'LICENSE', 'DESCRIPTION',
+ 'KEYWORDS', 'INHERITED', 'IUSE', 'CDEPEND',
+ 'PDEPEND', 'PROVIDE',
+ 'UNUSED_01', 'UNUSED_02', 'UNUSED_03', 'UNUSED_04',
+ 'UNUSED_05', 'UNUSED_06', 'UNUSED_07', 'UNUSED_08',
+ ]
+auxdbkeylen=len(auxdbkeys)
+
+def close_portdbapi_caches():
+ for i in portdbapi.portdbapi_instances:
+ i.close_caches()
+class portdbapi(dbapi):
+ """this tree will scan a portage directory located at root (passed to init)"""
+ portdbapi_instances = []
+
+ def __init__(self,porttree_root,mysettings=None):
+ portdbapi.portdbapi_instances.append(self)
+ self.lock_held = 0;
+
+ if mysettings:
+ self.mysettings = mysettings
+ else:
+ self.mysettings = config(clone=settings)
+
+ self.manifestVerifyLevel = None
+ self.manifestVerifier = None
+ self.manifestCache = {} # {location: [stat, md5]}
+ self.manifestMissingCache = []
+
+ if "gpg" in self.mysettings.features:
+ self.manifestVerifyLevel = portage_gpg.EXISTS
+ if "strict" in self.mysettings.features:
+ self.manifestVerifyLevel = portage_gpg.MARGINAL
+ self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", minimumTrust=self.manifestVerifyLevel)
+ elif "severe" in self.mysettings.features:
+ self.manifestVerifyLevel = portage_gpg.TRUSTED
+ self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", requireSignedRing=True, minimumTrust=self.manifestVerifyLevel)
+ else:
+ self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", minimumTrust=self.manifestVerifyLevel)
+
+ #self.root=settings["PORTDIR"]
+ self.porttree_root = porttree_root
+
+ self.depcachedir = self.mysettings.depcachedir[:]
+
+ self.tmpfs = self.mysettings["PORTAGE_TMPFS"]
+ if self.tmpfs and not os.path.exists(self.tmpfs):
+ self.tmpfs = None
+ if self.tmpfs and not os.access(self.tmpfs, os.W_OK):
+ self.tmpfs = None
+ if self.tmpfs and not os.access(self.tmpfs, os.R_OK):
+ self.tmpfs = None
+
+ self.eclassdb = eclass_cache(self.porttree_root, self.mysettings)
+
+ self.metadb = {}
+ self.metadbmodule = self.mysettings.load_best_module("portdbapi.metadbmodule")
+
+ self.auxdb = {}
+ self.auxdbmodule = self.mysettings.load_best_module("portdbapi.auxdbmodule")
+
+ #if the portdbapi is "frozen", then we assume that we can cache everything (that no updates to it are happening)
+ self.xcache={}
+ self.frozen=0
+
+ self.porttrees=[self.porttree_root]+self.mysettings["PORTDIR_OVERLAY"].split()
+
+ def close_caches(self):
+ for x in self.auxdb.keys():
+ for y in self.auxdb[x].keys():
+ self.auxdb[x][y].sync()
+ self.auxdb[x][y].close()
+ del self.auxdb[x][y]
+ del self.auxdb[x]
+ self.eclassdb.close_caches()
+
+ def flush_cache(self):
+ self.metadb = {}
+ self.auxdb = {}
+ self.eclassdb.flush_cache()
+
+ def finddigest(self,mycpv):
+ try:
+ mydig = self.findname2(mycpv)[0]
+ mydigs = string.split(mydig, "/")[:-1]
+ mydig = string.join(mydigs, "/")
+
+ mysplit = mycpv.split("/")
+ except SystemExit, e:
+ raise
+ except:
+ return ""
+ return mydig+"/files/digest-"+mysplit[-1]
+
+ def findname(self,mycpv):
+ return self.findname2(mycpv)[0]
+
+ def findname2(self,mycpv):
+ "returns file location for this particular package and in_overlay flag"
+ if not mycpv:
+ return "",0
+ mysplit=mycpv.split("/")
+
+ psplit=pkgsplit(mysplit[1])
+ ret=None
+ if psplit:
+ for x in self.porttrees:
+ # XXX Why are there errors here? XXX
+ try:
+ file=x+"/"+mysplit[0]+"/"+psplit[0]+"/"+mysplit[1]+".ebuild"
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ print
+ print "!!! Problem with determining the name/location of an ebuild."
+ print "!!! Please report this on IRC and bugs if you are not causing it."
+ print "!!! mycpv: ",mycpv
+ print "!!! mysplit:",mysplit
+ print "!!! psplit: ",psplit
+ print "!!! error: ",e
+ print
+ sys.exit(17)
+
+ if os.access(file, os.R_OK):
+ # when found
+ ret=[file, x]
+ if ret:
+ return ret[0], ret[1]
+
+ # when not found
+ return None, 0
+
+ def aux_get(self,mycpv,mylist,strict=0,metacachedir=None,debug=0):
+ "stub code for returning auxilliary db information, such as SLOT, DEPEND, etc."
+ 'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
+ 'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or raise KeyError if error'
+ global auxdbkeys,auxdbkeylen
+
+ cat,pkg = string.split(mycpv, "/", 1)
+
+ if metacachedir:
+ if cat not in self.metadb:
+ self.metadb[cat] = self.metadbmodule(metacachedir,cat,auxdbkeys,uid,portage_gid)
+
+ myebuild, mylocation=self.findname2(mycpv)
+
+ if not myebuild:
+ writemsg("!!! aux_get(): ebuild path for '%(cpv)s' not specified:\n" % {"cpv":mycpv})
+ writemsg("!!! %s\n" % myebuild)
+ raise KeyError, "'%(cpv)s' at %(path)s" % {"cpv":mycpv,"path":myebuild}
+
+ myManifestPath = string.join(myebuild.split("/")[:-1],"/")+"/Manifest"
+ if "gpg" in self.mysettings.features:
+ try:
+ mys = portage_gpg.fileStats(myManifestPath)
+ if (myManifestPath in self.manifestCache) and \
+ (self.manifestCache[myManifestPath] == mys):
+ pass
+ elif self.manifestVerifier:
+ if not self.manifestVerifier.verify(myManifestPath):
+ # Verification failed the desired level.
+ raise portage_exception.UntrustedSignature, "Untrusted Manifest: %(manifest)s" % {"manifest":myManifestPath}
+
+ if ("severe" in self.mysettings.features) and \
+ (mys != portage_gpg.fileStats(myManifestPath)):
+ raise portage_exception.SecurityViolation, "Manifest changed: %(manifest)s" % {"manifest":myManifestPath}
+
+ except portage_exception.InvalidSignature, e:
+ if ("strict" in self.mysettings.features) or \
+ ("severe" in self.mysettings.features):
+ raise
+ writemsg("!!! INVALID MANIFEST SIGNATURE DETECTED: %(manifest)s\n" % {"manifest":myManifestPath})
+ except portage_exception.MissingSignature, e:
+ if ("severe" in self.mysettings.features):
+ raise
+ if ("strict" in self.mysettings.features):
+ if myManifestPath not in self.manifestMissingCache:
+ writemsg("!!! WARNING: Missing signature in: %(manifest)s\n" % {"manifest":myManifestPath})
+ self.manifestMissingCache.insert(0,myManifestPath)
+ except (OSError,portage_exception.FileNotFound), e:
+ if ("strict" in self.mysettings.features) or \
+ ("severe" in self.mysettings.features):
+ raise portage_exception.SecurityViolation, "Error in verification of signatures: %(errormsg)s" % {"errormsg":str(e)}
+ writemsg("!!! Manifest is missing or inaccessable: %(manifest)s\n" % {"manifest":myManifestPath})
+
+ if mylocation not in self.auxdb:
+ self.auxdb[mylocation] = {}
+
+ if not self.auxdb[mylocation].has_key(cat):
+ self.auxdb[mylocation][cat] = self.auxdbmodule(self.depcachedir+"/"+mylocation,cat,auxdbkeys,uid,portage_gid)
+
+ if os.access(myebuild, os.R_OK):
+ emtime=os.stat(myebuild)[stat.ST_MTIME]
+ else:
+ writemsg("!!! aux_get(): ebuild for '%(cpv)s' does not exist at:\n" % {"cpv":mycpv})
+ writemsg("!!! %s\n" % myebuild)
+ raise KeyError
+
+ # when mylocation is not overlay directorys and metacachedir is set,
+ # we use cache files, which is usually on /usr/portage/metadata/cache/.
+ if mylocation==self.mysettings["PORTDIR"] and metacachedir and self.metadb[cat].has_key(pkg):
+ metadata=self.metadb[cat][pkg]
+ self.eclassdb.update_package(mylocation,cat,pkg,metadata["INHERITED"].split())
+ self.auxdb[mylocation][cat][pkg] = metadata
+ self.auxdb[mylocation][cat].sync()
+ else:
+
+ try:
+ auxdb_is_valid = self.auxdb[mylocation][cat].has_key(pkg) and \
+ self.auxdb[mylocation][cat][pkg].has_key("_mtime_") and \
+ self.auxdb[mylocation][cat][pkg]["_mtime_"] == emtime
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ auxdb_is_valid = 0
+ writemsg("auxdb exception: [%(loc)s]: %(exception)s\n" % {"loc":mylocation+"::"+cat+"/"+pkg, "exception":str(e)})
+ if self.auxdb[mylocation][cat].has_key(pkg):
+ self.auxdb[mylocation][cat].del_key(pkg)
+ self.auxdb[mylocation][cat].sync()
+
+ writemsg("auxdb is valid: "+str(auxdb_is_valid)+" "+str(pkg)+"\n", 2)
+ if auxdb_is_valid:
+ doregen=0
+ else:
+ doregen=1
+
+ if doregen or not self.eclassdb.is_current(mylocation,cat,pkg,self.auxdb[mylocation][cat][pkg]["INHERITED"].split()):
+ writemsg("doregen: %s %s\n" % (doregen,mycpv), 2)
+ writemsg("Generating cache entry(0) for: "+str(myebuild)+"\n",1)
+
+ if self.tmpfs:
+ mydbkey = self.tmpfs+"/aux_db_key_temp"
+ else:
+ mydbkey = self.depcachedir+"/aux_db_key_temp"
+
+ # XXX: Part of the gvisible hack/fix to prevent deadlock
+ # XXX: through doebuild. Need to isolate this somehow...
+ self.mysettings.reset()
+
+ if self.lock_held:
+ raise "Lock is already held by me?"
+ self.lock_held = 1
+ mylock = portage_locks.lockfile(mydbkey, wantnewlockfile=1)
+
+ if os.path.exists(mydbkey):
+ try:
+ os.unlink(mydbkey)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ writemsg("Uncaught handled exception: %(exception)s\n" % {"exception":str(e)})
+ raise
+
+ myret=doebuild(myebuild,"depend","/",self.mysettings,dbkey=mydbkey)
+ if myret:
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ #depend returned non-zero exit code...
+ writemsg(str(red("\naux_get():")+" (0) Error in "+mycpv+" ebuild. ("+str(myret)+")\n"
+ " Check for syntax error or corruption in the ebuild. (--debug)\n\n"))
+ raise KeyError
+
+ try:
+ mycent=open(mydbkey,"r")
+ os.unlink(mydbkey)
+ mylines=mycent.readlines()
+ mycent.close()
+ except SystemExit, e:
+ raise
+ except (IOError, OSError):
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ writemsg(str(red("\naux_get():")+" (1) Error in "+mycpv+" ebuild.\n"
+ " Check for syntax error or corruption in the ebuild. (--debug)\n\n"))
+ raise KeyError
+ except Exception, e:
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+ writemsg("Uncaught handled exception: %(exception)s\n" % {"exception":str(e)})
+ raise
+
+ portage_locks.unlockfile(mylock)
+ self.lock_held = 0
+
+ mydata = {}
+ for x in range(0,len(mylines)):
+ if mylines[x][-1] == '\n':
+ mylines[x] = mylines[x][:-1]
+ mydata[auxdbkeys[x]] = mylines[x]
+ mydata["_mtime_"] = emtime
+
+ self.auxdb[mylocation][cat][pkg] = mydata
+ self.auxdb[mylocation][cat].sync()
+ if not self.eclassdb.update_package(mylocation, cat, pkg, mylines[auxdbkeys.index("INHERITED")].split()):
+ sys.exit(1)
+
+ #finally, we look at our internal cache entry and return the requested data.
+ mydata = self.auxdb[mylocation][cat][pkg]
+ returnme = []
+ for x in mylist:
+ if mydata.has_key(x):
+ returnme.append(mydata[x])
+ else:
+ returnme.append("")
+
+ return returnme
+
+ def getfetchlist(self,mypkg,useflags=None,mysettings=None,all=0):
+ if mysettings == None:
+ mysettings = self.mysettings
+ try:
+ myuris = self.aux_get(mypkg,["SRC_URI"])[0]
+ except (IOError,KeyError):
+ print red("getfetchlist():")+" aux_get() error reading "+mypkg+"; aborting."
+ sys.exit(1)
+
+ useflags = string.split(mysettings["USE"])
+
+ myurilist = portage_dep.paren_reduce(myuris)
+ myurilist = portage_dep.use_reduce(myurilist,uselist=useflags,matchall=all)
+ newuris = flatten(myurilist)
+
+ myfiles = []
+ for x in newuris:
+ mya = os.path.basename(x)
+ if not mya in myfiles:
+ myfiles.append(mya)
+ return [newuris, myfiles]
+
+ def getfetchsizes(self,mypkg,useflags=None,debug=0):
+ # returns a filename:size dictionnary of remaining downloads
+ mydigest=self.finddigest(mypkg)
+ mymd5s=digestParseFile(mydigest)
+ if not mymd5s:
+ if debug: print "[empty/missing/bad digest]: "+mypkg
+ return None
+ filesdict={}
+ if useflags == None:
+ myuris, myfiles = self.getfetchlist(mypkg,all=1)
+ else:
+ myuris, myfiles = self.getfetchlist(mypkg,useflags=useflags)
+ #XXX: maybe this should be improved: take partial downloads
+ # into account? check md5sums?
+ for myfile in myfiles:
+ if debug and myfile not in mymd5s.keys():
+ print "[bad digest]: missing",myfile,"for",mypkg
+ elif myfile in mymd5s.keys():
+ distfile=settings["DISTDIR"]+"/"+myfile
+ if not os.access(distfile, os.R_OK):
+ filesdict[myfile]=int(mymd5s[myfile]["size"])
+ return filesdict
+
+ def fetch_check(self, mypkg, useflags=None, mysettings=None, all=False):
+ if not useflags:
+ if mysettings:
+ useflags = mysettings["USE"].split()
+ myuri, myfiles = self.getfetchlist(mypkg, useflags=useflags, mysettings=mysettings, all=all)
+ mydigest = self.finddigest(mypkg)
+ mysums = digestParseFile(mydigest)
+
+ failures = {}
+ for x in myfiles:
+ if not mysums or x not in mysums:
+ ok = False
+ reason = "digest missing"
+ else:
+ ok,reason = portage_checksum.verify_all(self.mysettings["DISTDIR"]+"/"+x, mysums[x])
+ if not ok:
+ failures[x] = reason
+ if failures:
+ return False
+ return True
+
+ def getsize(self,mypkg,useflags=None,debug=0):
+ # returns the total size of remaining downloads
+ #
+ # we use getfetchsizes() now, so this function would be obsoleted
+ #
+ filesdict=self.getfetchsizes(mypkg,useflags=useflags,debug=debug)
+ if filesdict==None:
+ return "[empty/missing/bad digest]"
+ mysize=0
+ for myfile in filesdict.keys():
+ mysum+=filesdict[myfile]
+ return mysum
+
+ def cpv_exists(self,mykey):
+ "Tells us whether an actual ebuild exists on disk (no masking)"
+ cps2=mykey.split("/")
+ cps=catpkgsplit(mykey,silent=0)
+ if not cps:
+ #invalid cat/pkg-v
+ return 0
+ if self.findname(cps[0]+"/"+cps2[1]):
+ return 1
+ else:
+ return 0
+
+ def cp_all(self):
+ "returns a list of all keys in our tree"
+ d={}
+ for x in self.mysettings.categories:
+ for oroot in self.porttrees:
+ for y in listdir(oroot+"/"+x,EmptyOnError=1,ignorecvs=1):
+ mykey=x+"/"+y
+ d[x+"/"+y] = None
+ l = d.keys()
+ l.sort()
+ return l
+
+ def p_list(self,mycp):
+ d={}
+ for oroot in self.porttrees:
+ for x in listdir(oroot+"/"+mycp,EmptyOnError=1,ignorecvs=1):
+ if x[-7:]==".ebuild":
+ d[x[:-7]] = None
+ return d.keys()
+
+ def cp_list(self,mycp,use_cache=1):
+ mysplit=mycp.split("/")
+ d={}
+ for oroot in self.porttrees:
+ for x in listdir(oroot+"/"+mycp,EmptyOnError=1,ignorecvs=1):
+ if x[-7:]==".ebuild":
+ d[mysplit[0]+"/"+x[:-7]] = None
+ return d.keys()
+
+ def freeze(self):
+ for x in ["list-visible","bestmatch-visible","match-visible","match-all"]:
+ self.xcache[x]={}
+ self.frozen=1
+
+ def melt(self):
+ self.xcache={}
+ self.frozen=0
+
+ def xmatch(self,level,origdep,mydep=None,mykey=None,mylist=None):
+ "caching match function; very trick stuff"
+ #if no updates are being made to the tree, we can consult our xcache...
+ if self.frozen:
+ try:
+ return self.xcache[level][origdep]
+ except KeyError:
+ pass
+
+ if not mydep:
+ #this stuff only runs on first call of xmatch()
+ #create mydep, mykey from origdep
+ mydep=dep_expand(origdep,mydb=self)
+ mykey=dep_getkey(mydep)
+
+ if level=="list-visible":
+ #a list of all visible packages, not called directly (just by xmatch())
+ #myval=self.visible(self.cp_list(mykey))
+ myval=self.gvisible(self.visible(self.cp_list(mykey)))
+ elif level=="bestmatch-visible":
+ #dep match -- best match of all visible packages
+ myval=best(self.xmatch("match-visible",None,mydep=mydep,mykey=mykey))
+ #get all visible matches (from xmatch()), then choose the best one
+ elif level=="bestmatch-list":
+ #dep match -- find best match but restrict search to sublist
+ myval=best(match_from_list(mydep,mylist))
+ #no point is calling xmatch again since we're not caching list deps
+ elif level=="match-list":
+ #dep match -- find all matches but restrict search to sublist (used in 2nd half of visible())
+ myval=match_from_list(mydep,mylist)
+ elif level=="match-visible":
+ #dep match -- find all visible matches
+ myval=match_from_list(mydep,self.xmatch("list-visible",None,mydep=mydep,mykey=mykey))
+ #get all visible packages, then get the matching ones
+ elif level=="match-all":
+ #match *all* visible *and* masked packages
+ myval=match_from_list(mydep,self.cp_list(mykey))
+ else:
+ print "ERROR: xmatch doesn't handle",level,"query!"
+ raise KeyError
+ if self.frozen and (level not in ["match-list","bestmatch-list"]):
+ self.xcache[level][mydep]=myval
+ return myval
+
+ def match(self,mydep,use_cache=1):
+ return self.xmatch("match-visible",mydep)
+
+ def visible(self,mylist):
+ """two functions in one. Accepts a list of cpv values and uses the package.mask *and*
+ packages file to remove invisible entries, returning remaining items. This function assumes
+ that all entries in mylist have the same category and package name."""
+ if (mylist==None) or (len(mylist)==0):
+ return []
+ newlist=mylist[:]
+ #first, we mask out packages in the package.mask file
+ mykey=newlist[0]
+ cpv=catpkgsplit(mykey)
+ if not cpv:
+ #invalid cat/pkg-v
+ print "visible(): invalid cat/pkg-v:",mykey
+ return []
+ mycp=cpv[0]+"/"+cpv[1]
+ maskdict=self.mysettings.pmaskdict
+ unmaskdict=self.mysettings.punmaskdict
+ if maskdict.has_key(mycp):
+ for x in maskdict[mycp]:
+ mymatches=self.xmatch("match-all",x)
+ if mymatches==None:
+ #error in package.mask file; print warning and continue:
+ print "visible(): package.mask entry \""+x+"\" is invalid, ignoring..."
+ continue
+ for y in mymatches:
+ unmask=0
+ if unmaskdict.has_key(mycp):
+ for z in unmaskdict[mycp]:
+ mymatches_unmask=self.xmatch("match-all",z)
+ if y in mymatches_unmask:
+ unmask=1
+ break
+ if unmask==0:
+ try:
+ newlist.remove(y)
+ except ValueError:
+ pass
+
+ revmaskdict=self.mysettings.prevmaskdict
+ if revmaskdict.has_key(mycp):
+ for x in revmaskdict[mycp]:
+ #important: only match against the still-unmasked entries...
+ #notice how we pass "newlist" to the xmatch() call below....
+ #Without this, ~ deps in the packages files are broken.
+ mymatches=self.xmatch("match-list",x,mylist=newlist)
+ if mymatches==None:
+ #error in packages file; print warning and continue:
+ print "emerge: visible(): profile packages entry \""+x+"\" is invalid, ignoring..."
+ continue
+ pos=0
+ while pos<len(newlist):
+ if newlist[pos] not in mymatches:
+ del newlist[pos]
+ else:
+ pos += 1
+ return newlist
+
+ def gvisible(self,mylist):
+ "strip out group-masked (not in current group) entries"
+ global groups
+ if mylist==None:
+ return []
+ newlist=[]
+
+ pkgdict = self.mysettings.pkeywordsdict
+ for mycpv in mylist:
+ #we need to update this next line when we have fully integrated the new db api
+ auxerr=0
+ try:
+ myaux=db["/"]["porttree"].dbapi.aux_get(mycpv, ["KEYWORDS"])
+ except (KeyError,IOError,TypeError):
+ continue
+ if not myaux[0]:
+ # KEYWORDS=""
+ #print "!!! No KEYWORDS for "+str(mycpv)+" -- Untested Status"
+ continue
+ mygroups=myaux[0].split()
+ pgroups=groups[:]
+ match=0
+ cp = dep_getkey(mycpv)
+ if pkgdict.has_key(cp):
+ matches = match_to_list(mycpv, pkgdict[cp].keys())
+ for atom in matches:
+ pgroups.extend(pkgdict[cp][atom])
+ for gp in mygroups:
+ if gp=="*":
+ writemsg("--- WARNING: Package '%s' uses '*' keyword.\n" % mycpv)
+ match=1
+ break
+ elif "-"+gp in pgroups:
+ match=0
+ break
+ elif gp in pgroups:
+ match=1
+ break
+ if match:
+ newlist.append(mycpv)
+ return newlist
+
+class binarytree(packagetree):
+ "this tree scans for a list of all packages available in PKGDIR"
+ def __init__(self,root,pkgdir,virtual=None,clone=None):
+
+ if clone:
+ # XXX This isn't cloning. It's an instance of the same thing.
+ self.root=clone.root
+ self.pkgdir=clone.pkgdir
+ self.dbapi=clone.dbapi
+ self.populated=clone.populated
+ self.tree=clone.tree
+ self.remotepkgs=clone.remotepkgs
+ self.invalids=clone.invalids
+ else:
+ self.root=root
+ #self.pkgdir=settings["PKGDIR"]
+ self.pkgdir=pkgdir
+ self.dbapi=bindbapi(self)
+ self.populated=0
+ self.tree={}
+ self.remotepkgs={}
+ self.invalids=[]
+
+ def move_ent(self,mylist):
+ if not self.populated:
+ self.populate()
+ origcp=mylist[1]
+ newcp=mylist[2]
+ mynewcat=newcp.split("/")[0]
+ origmatches=self.dbapi.cp_list(origcp)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+
+ mycpsplit=catpkgsplit(mycpv)
+ mynewcpv=newcp+"-"+mycpsplit[2]
+ if mycpsplit[3]!="r0":
+ mynewcpv += "-"+mycpsplit[3]
+
+ myoldpkg=mycpv.split("/")[1]
+ mynewpkg=mynewcpv.split("/")[1]
+
+ if (mynewpkg != myoldpkg) and os.path.exists(self.getname(mynewcpv)):
+ writemsg("!!! Cannot update binary: Destination exists.\n")
+ writemsg("!!! "+mycpv+" -> "+mynewcpv+"\n")
+ continue
+
+ tbz2path=self.getname(mycpv)
+ if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+ writemsg("!!! Cannot update readonly binary: "+mycpv+"\n")
+ continue
+
+ #print ">>> Updating data in:",mycpv
+ sys.stdout.write("%")
+ sys.stdout.flush()
+ mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2"
+ mytbz2=xpak.tbz2(tbz2path)
+ mytbz2.decompose(mytmpdir, cleanup=1)
+
+ fixdbentries(origcp, newcp, mytmpdir)
+
+ catfile=open(mytmpdir+"/CATEGORY", "w")
+ catfile.write(mynewcat+"\n")
+ catfile.close()
+ try:
+ os.rename(mytmpdir+"/"+string.split(mycpv,"/")[1]+".ebuild", mytmpdir+"/"+string.split(mynewcpv, "/")[1]+".ebuild")
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+ mytbz2.recompose(mytmpdir, cleanup=1)
+
+ self.dbapi.cpv_remove(mycpv)
+ if (mynewpkg != myoldpkg):
+ os.rename(tbz2path,self.getname(mynewcpv))
+ self.dbapi.cpv_inject(mynewcpv)
+ return 1
+
+ def move_slot_ent(self,mylist,mytmpdir):
+ #mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2"
+ mytmpdir=mytmpdir+"/tbz2"
+ if not self.populated:
+ self.populate()
+ pkg=mylist[1]
+ origslot=mylist[2]
+ newslot=mylist[3]
+ origmatches=self.dbapi.match(pkg)
+ if not origmatches:
+ return
+ for mycpv in origmatches:
+ mycpsplit=catpkgsplit(mycpv)
+ myoldpkg=mycpv.split("/")[1]
+ tbz2path=self.getname(mycpv)
+ if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+ writemsg("!!! Cannot update readonly binary: "+mycpv+"\n")
+ continue
+
+ #print ">>> Updating data in:",mycpv
+ mytbz2=xpak.tbz2(tbz2path)
+ mytbz2.decompose(mytmpdir, cleanup=1)
+
+ slot=grabfile(mytmpdir+"/SLOT");
+ if (not slot):
+ continue
+
+ if (slot[0]!=origslot):
+ continue
+
+ sys.stdout.write("S")
+ sys.stdout.flush()
+
+ slotfile=open(mytmpdir+"/SLOT", "w")
+ slotfile.write(newslot+"\n")
+ slotfile.close()
+ mytbz2.recompose(mytmpdir, cleanup=1)
+ return 1
+
+ def update_ents(self,mybiglist,mytmpdir):
+ #XXX mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2"
+ if not self.populated:
+ self.populate()
+ for mycpv in self.dbapi.cp_all():
+ tbz2path=self.getname(mycpv)
+ if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+ writemsg("!!! Cannot update readonly binary: "+mycpv+"\n")
+ continue
+ #print ">>> Updating binary data:",mycpv
+ writemsg("*")
+ mytbz2=xpak.tbz2(tbz2path)
+ mytbz2.decompose(mytmpdir,cleanup=1)
+ for mylist in mybiglist:
+ mylist=string.split(mylist)
+ if mylist[0] != "move":
+ continue
+ fixdbentries(mylist[1], mylist[2], mytmpdir)
+ mytbz2.recompose(mytmpdir,cleanup=1)
+ return 1
+
+ def populate(self, getbinpkgs=0,getbinpkgsonly=0):
+ "populates the binarytree"
+ if (not os.path.isdir(self.pkgdir) and not getbinpkgs):
+ return 0
+ if (not os.path.isdir(self.pkgdir+"/All") and not getbinpkgs):
+ return 0
+
+ if (not getbinpkgsonly) and os.path.exists(self.pkgdir+"/All"):
+ for mypkg in listdir(self.pkgdir+"/All"):
+ if mypkg[-5:]!=".tbz2":
+ continue
+ mytbz2=xpak.tbz2(self.pkgdir+"/All/"+mypkg)
+ mycat=mytbz2.getfile("CATEGORY")
+ if not mycat:
+ #old-style or corrupt package
+ writemsg("!!! Invalid binary package: "+mypkg+"\n")
+ self.invalids.append(mypkg)
+ continue
+ mycat=string.strip(mycat)
+ fullpkg=mycat+"/"+mypkg[:-5]
+ mykey=dep_getkey(fullpkg)
+ try:
+ # invalid tbz2's can hurt things.
+ self.dbapi.cpv_inject(fullpkg)
+ except SystemExit, e:
+ raise
+ except:
+ continue
+
+ if getbinpkgs and not settings["PORTAGE_BINHOST"]:
+ writemsg(red("!!! PORTAGE_BINHOST unset, but use is requested.\n"))
+
+ if getbinpkgs and settings["PORTAGE_BINHOST"] and not self.remotepkgs:
+ try:
+ chunk_size = long(settings["PORTAGE_BINHOST_CHUNKSIZE"])
+ if chunk_size < 8:
+ chunk_size = 8
+ except SystemExit, e:
+ raise
+ except:
+ chunk_size = 3000
+
+ writemsg(green("Fetching binary packages info...\n"))
+ self.remotepkgs = getbinpkg.dir_get_metadata(settings["PORTAGE_BINHOST"], chunk_size=chunk_size)
+ writemsg(green(" -- DONE!\n\n"))
+
+ for mypkg in self.remotepkgs.keys():
+ if not self.remotepkgs[mypkg].has_key("CATEGORY"):
+ #old-style or corrupt package
+ writemsg("!!! Invalid remote binary package: "+mypkg+"\n")
+ del self.remotepkgs[mypkg]
+ continue
+ mycat=string.strip(self.remotepkgs[mypkg]["CATEGORY"])
+ fullpkg=mycat+"/"+mypkg[:-5]
+ mykey=dep_getkey(fullpkg)
+ try:
+ # invalid tbz2's can hurt things.
+ #print "cpv_inject("+str(fullpkg)+")"
+ self.dbapi.cpv_inject(fullpkg)
+ #print " -- Injected"
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("!!! Failed to inject remote binary package:"+str(fullpkg)+"\n")
+ del self.remotepkgs[mypkg]
+ continue
+ self.populated=1
+
+ def inject(self,cpv):
+ return self.dbapi.cpv_inject(cpv)
+
+ def exists_specific(self,cpv):
+ if not self.populated:
+ self.populate()
+ return self.dbapi.match(dep_expand("="+cpv,mydb=self.dbapi))
+
+ def dep_bestmatch(self,mydep):
+ "compatibility method -- all matches, not just visible ones"
+ if not self.populated:
+ self.populate()
+ writemsg("\n\n", 1)
+ writemsg("mydep: %s\n" % mydep, 1)
+ mydep=dep_expand(mydep,mydb=self.dbapi)
+ writemsg("mydep: %s\n" % mydep, 1)
+ mykey=dep_getkey(mydep)
+ writemsg("mykey: %s\n" % mykey, 1)
+ mymatch=best(match_from_list(mydep,self.dbapi.cp_list(mykey)))
+ writemsg("mymatch: %s\n" % mymatch, 1)
+ if mymatch==None:
+ return ""
+ return mymatch
+
+ def getname(self,pkgname):
+ "returns file location for this particular package"
+ mysplit=string.split(pkgname,"/")
+ if len(mysplit)==1:
+ return self.pkgdir+"/All/"+self.resolve_specific(pkgname)+".tbz2"
+ else:
+ return self.pkgdir+"/All/"+mysplit[1]+".tbz2"
+
+ def isremote(self,pkgname):
+ "Returns true if the package is kept remotely."
+ mysplit=string.split(pkgname,"/")
+ remote = (not os.path.exists(self.getname(pkgname))) and self.remotepkgs.has_key(mysplit[1]+".tbz2")
+ return remote
+
+ def get_use(self,pkgname):
+ mysplit=string.split(pkgname,"/")
+ if self.isremote(pkgname):
+ return string.split(self.remotepkgs[mysplit[1]+".tbz2"]["USE"][:])
+ tbz2=xpak.tbz2(self.getname(pkgname))
+ return string.split(tbz2.getfile("USE"))
+
+ def gettbz2(self,pkgname):
+ "fetches the package from a remote site, if necessary."
+ print "Fetching '"+str(pkgname)+"'"
+ mysplit = string.split(pkgname,"/")
+ tbz2name = mysplit[1]+".tbz2"
+ if not self.isremote(pkgname):
+ if (tbz2name not in self.invalids):
+ return
+ else:
+ writemsg("Resuming download of this tbz2, but it is possible that it is corrupt.\n")
+ mydest = self.pkgdir+"/All/"
+ try:
+ os.makedirs(mydest, 0775)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ getbinpkg.file_get(settings["PORTAGE_BINHOST"]+"/"+tbz2name, mydest, fcmd=settings["RESUMECOMMAND"])
+ return
+
+ def getslot(self,mycatpkg):
+ "Get a slot for a catpkg; assume it exists."
+ myslot = ""
+ try:
+ myslot=self.dbapi.aux_get(mycatpkg,["SLOT"])[0]
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+ return myslot
+
+class dblink:
+ "this class provides an interface to the standard text package database"
+ def __init__(self,cat,pkg,myroot,mysettings):
+ "create a dblink object for cat/pkg. This dblink entry may or may not exist"
+ self.cat = cat
+ self.pkg = pkg
+ self.mycpv = self.cat+"/"+self.pkg
+ self.mysplit = pkgsplit(self.mycpv)
+
+ self.dbroot = os.path.normpath(myroot+VDB_PATH)
+ self.dbcatdir = self.dbroot+"/"+cat
+ self.dbpkgdir = self.dbcatdir+"/"+pkg
+ self.dbtmpdir = self.dbcatdir+"/-MERGING-"+pkg
+ self.dbdir = self.dbpkgdir
+
+ self.lock_pkg = None
+ self.lock_tmp = None
+ self.lock_num = 0 # Count of the held locks on the db.
+
+ self.settings = mysettings
+ if self.settings==1:
+ raise ValueError
+
+ self.myroot=myroot
+ self.updateprotect()
+ self.contentscache=[]
+
+ def lockdb(self):
+ if self.lock_num == 0:
+ self.lock_pkg = portage_locks.lockdir(self.dbpkgdir)
+ self.lock_tmp = portage_locks.lockdir(self.dbtmpdir)
+ self.lock_num += 1
+
+ def unlockdb(self):
+ self.lock_num -= 1
+ if self.lock_num == 0:
+ portage_locks.unlockdir(self.lock_tmp)
+ portage_locks.unlockdir(self.lock_pkg)
+
+ def getpath(self):
+ "return path to location of db information (for >>> informational display)"
+ return self.dbdir
+
+ def exists(self):
+ "does the db entry exist? boolean."
+ return os.path.exists(self.dbdir)
+
+ def create(self):
+ "create the skeleton db directory structure. No contents, virtuals, provides or anything. Also will create /var/db/pkg if necessary."
+ # XXXXX Delete this eventually
+ raise Exception, "This is bad. Don't use it."
+ if not os.path.exists(self.dbdir):
+ os.makedirs(self.dbdir)
+
+ def delete(self):
+ "erase this db entry completely"
+ if not os.path.exists(self.dbdir):
+ return
+ try:
+ for x in listdir(self.dbdir):
+ os.unlink(self.dbdir+"/"+x)
+ os.rmdir(self.dbdir)
+ except OSError, e:
+ print "!!! Unable to remove db entry for this package."
+ print "!!! It is possible that a directory is in this one. Portage will still"
+ print "!!! register this package as installed as long as this directory exists."
+ print "!!! You may delete this directory with 'rm -Rf "+self.dbdir+"'"
+ print "!!! "+str(e)
+ print
+ sys.exit(1)
+
+ def clearcontents(self):
+ if os.path.exists(self.dbdir+"/CONTENTS"):
+ os.unlink(self.dbdir+"/CONTENTS")
+
+ def getcontents(self):
+ if not os.path.exists(self.dbdir+"/CONTENTS"):
+ return None
+ if self.contentscache != []:
+ return self.contentscache
+ pkgfiles={}
+ myc=open(self.dbdir+"/CONTENTS","r")
+ mylines=myc.readlines()
+ myc.close()
+ pos=1
+ for line in mylines:
+ mydat = string.split(line)
+ # we do this so we can remove from non-root filesystems
+ # (use the ROOT var to allow maintenance on other partitions)
+ try:
+ mydat[1]=os.path.normpath(root+mydat[1][1:])
+ if mydat[0]=="obj":
+ #format: type, mtime, md5sum
+ pkgfiles[string.join(mydat[1:-2]," ")]=[mydat[0], mydat[-1], mydat[-2]]
+ elif mydat[0]=="dir":
+ #format: type
+ pkgfiles[string.join(mydat[1:])]=[mydat[0] ]
+ elif mydat[0]=="sym":
+ #format: type, mtime, dest
+ x=len(mydat)-1
+ if (x >= 13) and (mydat[-1][-1]==')'): # Old/Broken symlink entry
+ mydat = mydat[:-10]+[mydat[-10:][stat.ST_MTIME][:-1]]
+ writemsg("FIXED SYMLINK LINE: %s\n" % mydat, 1)
+ x=len(mydat)-1
+ splitter=-1
+ while(x>=0):
+ if mydat[x]=="->":
+ splitter=x
+ break
+ x=x-1
+ if splitter==-1:
+ return None
+ pkgfiles[string.join(mydat[1:splitter]," ")]=[mydat[0], mydat[-1], string.join(mydat[(splitter+1):-1]," ")]
+ elif mydat[0]=="dev":
+ #format: type
+ pkgfiles[string.join(mydat[1:]," ")]=[mydat[0] ]
+ elif mydat[0]=="fif":
+ #format: type
+ pkgfiles[string.join(mydat[1:]," ")]=[mydat[0]]
+ else:
+ return None
+ except (KeyError,IndexError):
+ print "portage: CONTENTS line",pos,"corrupt!"
+ pos += 1
+ self.contentscache=pkgfiles
+ return pkgfiles
+
+ def updateprotect(self):
+ #do some config file management prep
+ self.protect=[]
+ for x in string.split(self.settings["CONFIG_PROTECT"]):
+ ppath=normalize_path(self.myroot+x)+"/"
+ if os.path.isdir(ppath):
+ self.protect.append(ppath)
+
+ self.protectmask=[]
+ for x in string.split(self.settings["CONFIG_PROTECT_MASK"]):
+ ppath=normalize_path(self.myroot+x)+"/"
+ if os.path.isdir(ppath):
+ self.protectmask.append(ppath)
+ #if it doesn't exist, silently skip it
+
+ def isprotected(self,obj):
+ """Checks if obj is in the current protect/mask directories. Returns
+ 0 on unprotected/masked, and 1 on protected."""
+ masked=0
+ protected=0
+ for ppath in self.protect:
+ if (len(ppath) > masked) and (obj[0:len(ppath)]==ppath):
+ protected=len(ppath)
+ #config file management
+ for pmpath in self.protectmask:
+ if (len(pmpath) >= protected) and (obj[0:len(pmpath)]==pmpath):
+ #skip, it's in the mask
+ masked=len(pmpath)
+ return (protected > masked)
+
+ def unmerge(self,pkgfiles=None,trimworld=1,cleanup=0):
+ global dircache
+ dircache={}
+
+ self.lockdb()
+
+ self.settings.load_infodir(self.dbdir)
+
+ if not pkgfiles:
+ print "No package files given... Grabbing a set."
+ pkgfiles=self.getcontents()
+
+ # Now, don't assume that the name of the ebuild is the same as the
+ # name of the dir; the package may have been moved.
+ myebuildpath=None
+
+ # We should use the environement file if possible,
+ # as it has all sourced files already included.
+ # XXX: Need to ensure it doesn't overwrite any important vars though.
+ if os.access(self.dbdir+"/environment.bz2", os.R_OK):
+ spawn("bzip2 -d "+self.dbdir+"/environment.bz2",self.settings,free=1)
+
+ if not myebuildpath:
+ mystuff=listdir(self.dbdir,EmptyOnError=1)
+ for x in mystuff:
+ if x[-7:]==".ebuild":
+ myebuildpath=self.dbdir+"/"+x
+ break
+
+ #do prerm script
+ if myebuildpath and os.path.exists(myebuildpath):
+ a=doebuild(myebuildpath,"prerm",self.myroot,self.settings,cleanup=cleanup,use_cache=0,tree="vartree")
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED prerm: "+str(a)+"\n")
+ sys.exit(123)
+
+ if pkgfiles:
+ mykeys=pkgfiles.keys()
+ mykeys.sort()
+ mykeys.reverse()
+
+ self.updateprotect()
+
+ #process symlinks second-to-last, directories last.
+ mydirs=[]
+ mysyms=[]
+ modprotect="/lib/modules/"
+ for obj in mykeys:
+ obj=os.path.normpath(obj)
+ if obj[:2]=="//":
+ obj=obj[1:]
+ if not os.path.exists(obj):
+ if not os.path.islink(obj):
+ #we skip this if we're dealing with a symlink
+ #because os.path.exists() will operate on the
+ #link target rather than the link itself.
+ print "--- !found "+str(pkgfiles[obj][0]), obj
+ continue
+ # next line includes a tweak to protect modules from being unmerged,
+ # but we don't protect modules from being overwritten if they are
+ # upgraded. We effectively only want one half of the config protection
+ # functionality for /lib/modules. For portage-ng both capabilities
+ # should be able to be independently specified.
+ if self.isprotected(obj) or ((len(obj) > len(modprotect)) and (obj[0:len(modprotect)]==modprotect)):
+ print "--- cfgpro "+str(pkgfiles[obj][0]), obj
+ continue
+
+ lstatobj=os.lstat(obj)
+ lmtime=str(lstatobj[stat.ST_MTIME])
+ if (pkgfiles[obj][0] not in ("dir","fif","dev","sym")) and (lmtime != pkgfiles[obj][1]):
+ print "--- !mtime", pkgfiles[obj][0], obj
+ continue
+
+ if pkgfiles[obj][0]=="dir":
+ if not os.path.isdir(obj):
+ print "--- !dir ","dir", obj
+ continue
+ mydirs.append(obj)
+ elif pkgfiles[obj][0]=="sym":
+ if not os.path.islink(obj):
+ print "--- !sym ","sym", obj
+ continue
+ mysyms.append(obj)
+ elif pkgfiles[obj][0]=="obj":
+ if not os.path.isfile(obj):
+ print "--- !obj ","obj", obj
+ continue
+ mymd5=portage_checksum.perform_md5(obj, calc_prelink=1)
+
+ # string.lower is needed because db entries used to be in upper-case. The
+ # string.lower allows for backwards compatibility.
+ if mymd5 != string.lower(pkgfiles[obj][2]):
+ print "--- !md5 ","obj", obj
+ continue
+ try:
+ os.unlink(obj)
+ except (OSError,IOError),e:
+ pass
+ print "<<< ","obj",obj
+ elif pkgfiles[obj][0]=="fif":
+ if not stat.S_ISFIFO(lstatobj[stat.ST_MODE]):
+ print "--- !fif ","fif", obj
+ continue
+ try:
+ os.unlink(obj)
+ except (OSError,IOError),e:
+ pass
+ print "<<< ","fif",obj
+ elif pkgfiles[obj][0]=="dev":
+ print "--- ","dev",obj
+
+ #Now, we need to remove symlinks and directories. We'll repeatedly
+ #remove dead symlinks, then directories until we stop making progress.
+ #This is how we'll clean up directories containing symlinks pointing to
+ #directories that are now empty. These cases will require several
+ #iterations through our two-stage symlink/directory cleaning loop.
+
+ #main symlink and directory removal loop:
+
+ #progress -- are we making progress? Initialized to 1 so loop will start
+ progress=1
+ while progress:
+ #let's see if we're able to make progress this iteration...
+ progress=0
+
+ #step 1: remove all the dead symlinks we can...
+
+ pos = 0
+ while pos<len(mysyms):
+ obj=mysyms[pos]
+ if os.path.exists(obj):
+ pos += 1
+ else:
+ #we have a dead symlink; remove it from our list, then from existence
+ del mysyms[pos]
+ #we've made progress!
+ progress = 1
+ try:
+ os.unlink(obj)
+ print "<<< ","sym",obj
+ except (OSError,IOError),e:
+ print "!!! ","sym",obj
+ #immutable?
+ pass
+
+ #step 2: remove all the empty directories we can...
+
+ pos = 0
+ while pos<len(mydirs):
+ obj=mydirs[pos]
+ objld=listdir(obj)
+
+ if objld == None:
+ print "mydirs["+str(pos)+"]",mydirs[pos]
+ print "obj",obj
+ print "objld",objld
+ # the directory doesn't exist yet, continue
+ pos += 1
+ continue
+
+ if len(objld)>0:
+ #we won't remove this directory (yet), continue
+ pos += 1
+ continue
+ elif (objld != None):
+ #zappo time
+ del mydirs[pos]
+ #we've made progress!
+ progress = 1
+ try:
+ os.rmdir(obj)
+ print "<<< ","dir",obj
+ except (OSError,IOError),e:
+ #immutable?
+ pass
+ #else:
+ # print "--- !empty","dir", obj
+ # continue
+
+ #step 3: if we've made progress, we'll give this another go...
+
+ #step 4: otherwise, we'll print out the remaining stuff that we didn't unmerge (and rightly so!)
+
+ #directories that aren't empty:
+ for x in mydirs:
+ print "--- !empty dir", x
+
+ #symlinks whose target still exists:
+ for x in mysyms:
+ print "--- !targe sym", x
+
+ #step 5: well, removal of package objects is complete, now for package *meta*-objects....
+
+ #remove self from vartree database so that our own virtual gets zapped if we're the last node
+ db[self.myroot]["vartree"].zap(self.mycpv)
+
+ # New code to remove stuff from the world and virtuals files when unmerged.
+ if trimworld:
+ worldlist=grabfile(self.myroot+WORLD_FILE)
+ mykey=cpv_getkey(self.mycpv)
+ newworldlist=[]
+ for x in worldlist:
+ if dep_getkey(x)==mykey:
+ matches=db[self.myroot]["vartree"].dbapi.match(x,use_cache=0)
+ if not matches:
+ #zap our world entry
+ pass
+ elif (len(matches)==1) and (matches[0]==self.mycpv):
+ #zap our world entry
+ pass
+ else:
+ #others are around; keep it.
+ newworldlist.append(x)
+ else:
+ #this doesn't match the package we're unmerging; keep it.
+ newworldlist.append(x)
+
+ # if the base dir doesn't exist, create it.
+ # (spanky noticed bug)
+ # XXX: dumb question, but abstracting the root uid might be wise/useful for
+ # 2nd pkg manager installation setups.
+ if not os.path.exists(os.path.dirname(self.myroot+WORLD_FILE)):
+ pdir = os.path.dirname(self.myroot + WORLD_FILE)
+ os.makedirs(pdir, mode=0755)
+ os.chown(pdir, 0, portage_gid)
+ os.chmod(pdir, 02770)
+
+ myworld=open(self.myroot+WORLD_FILE,"w")
+ for x in newworldlist:
+ myworld.write(x+"\n")
+ myworld.close()
+
+ #do original postrm
+ if myebuildpath and os.path.exists(myebuildpath):
+ # XXX: This should be the old config, not the current one.
+ # XXX: Use vardbapi to load up env vars.
+ a=doebuild(myebuildpath,"postrm",self.myroot,self.settings,use_cache=0,tree="vartree")
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED postrm: "+str(a)+"\n")
+ sys.exit(123)
+
+ self.unlockdb()
+
+ def isowner(self,filename,destroot):
+ """ check if filename is a new file or belongs to this package
+ (for this or a previous version)"""
+ destfile = os.path.normpath(destroot+"/"+filename)
+ if not os.path.exists(destfile):
+ return True
+ if self.getcontents() and filename in self.getcontents().keys():
+ return True
+
+ return False
+
+ def treewalk(self,srcroot,destroot,inforoot,myebuild,cleanup=0):
+ global db
+ # srcroot = ${D};
+ # destroot = where to merge, ie. ${ROOT},
+ # inforoot = root of db entry,
+ # secondhand = list of symlinks that have been skipped due to
+ # their target not existing (will merge later),
+
+ if not os.path.exists(self.dbcatdir):
+ os.makedirs(self.dbcatdir)
+
+ # This blocks until we can get the dirs to ourselves.
+ self.lockdb()
+
+ otherversions=[]
+ for v in db[self.myroot]["vartree"].dbapi.cp_list(self.mysplit[0]):
+ otherversions.append(v.split("/")[1])
+
+ # check for package collisions
+ if "collision-protect" in features:
+ myfilelist = listdir(srcroot, recursive=1, filesonly=1, followSymlinks=False)
+
+ # the linkcheck only works if we are in srcroot
+ mycwd = os.getcwd()
+ os.chdir(srcroot)
+ mysymlinks = filter(os.path.islink, listdir(srcroot, recursive=1, filesonly=0, followSymlinks=False))
+
+ stopmerge=False
+ starttime=time.time()
+ i=0
+
+ otherpkg=[]
+ mypkglist=[]
+
+ if self.pkg in otherversions:
+ otherversions.remove(self.pkg) # we already checked this package
+
+ for v in otherversions:
+ # should we check for same SLOT here ?
+ mypkglist.append(dblink(self.cat,v,destroot,self.settings))
+
+ print green("*")+" checking "+str(len(myfilelist))+" files for package collisions"
+ for f in myfilelist:
+ nocheck = False
+ # listdir isn't intelligent enough to exclude symlinked dirs,
+ # so we have to do it ourself
+ for s in mysymlinks:
+ # the length comparison makes sure that the symlink itself is checked
+ if f[:len(s)] == s and len(f) > len(s):
+ nocheck = True
+ if nocheck:
+ continue
+ i=i+1
+ if i % 1000 == 0:
+ print str(i)+" files checked ..."
+ if f[0] != "/":
+ f="/"+f
+ isowned = False
+ for ver in [self]+mypkglist:
+ if (ver.isowner(f, destroot) or ver.isprotected(f)):
+ isowned = True
+ break
+ if not isowned:
+ print "existing file "+f+" is not owned by this package"
+ stopmerge=True
+ print green("*")+" spent "+str(time.time()-starttime)+" seconds checking for file collisions"
+ if stopmerge:
+ print red("*")+" This package is blocked because it wants to overwrite"
+ print red("*")+" files belonging to other packages (see messages above)."
+ print red("*")+" If you have no clue what this is all about report it "
+ print red("*")+" as a bug for this package on http://bugs.gentoo.org"
+ print
+ print red("package "+self.cat+"/"+self.pkg+" NOT merged")
+ print
+ # Why is the package already merged here db-wise? Shouldn't be the case
+ # only unmerge if it ia new package and has no contents
+ if not self.getcontents():
+ self.unmerge()
+ self.delete()
+ self.unlockdb()
+ sys.exit(1)
+ try:
+ os.chdir(mycwd)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+
+ # get old contents info for later unmerging
+ oldcontents = self.getcontents()
+
+ self.dbdir = self.dbtmpdir
+ self.delete()
+ if not os.path.exists(self.dbtmpdir):
+ os.makedirs(self.dbtmpdir)
+
+ print ">>> Merging",self.mycpv,"to",destroot
+
+ # run preinst script
+ if myebuild:
+ # if we are merging a new ebuild, use *its* pre/postinst rather than using the one in /var/db/pkg
+ # (if any).
+ a=doebuild(myebuild,"preinst",root,self.settings,cleanup=cleanup,use_cache=0)
+ else:
+ a=doebuild(inforoot+"/"+self.pkg+".ebuild","preinst",root,self.settings,cleanup=cleanup,use_cache=0)
+
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED preinst: "+str(a)+"\n")
+ sys.exit(123)
+
+ # copy "info" files (like SLOT, CFLAGS, etc.) into the database
+ for x in listdir(inforoot):
+ self.copyfile(inforoot+"/"+x)
+
+ # get current counter value (counter_tick also takes care of incrementing it)
+ # XXX Need to make this destroot, but it needs to be initialized first. XXX
+ # XXX bis: leads to some invalidentry() call through cp_all().
+ counter = db["/"]["vartree"].dbapi.counter_tick(self.myroot,mycpv=self.mycpv)
+ # write local package counter for recording
+ lcfile = open(self.dbtmpdir+"/COUNTER","w")
+ lcfile.write(str(counter))
+ lcfile.close()
+
+ # open CONTENTS file (possibly overwriting old one) for recording
+ outfile=open(self.dbtmpdir+"/CONTENTS","w")
+
+ self.updateprotect()
+
+ #if we have a file containing previously-merged config file md5sums, grab it.
+ if os.path.exists(destroot+CONFIG_MEMORY_FILE):
+ cfgfiledict=grabdict(destroot+CONFIG_MEMORY_FILE)
+ else:
+ cfgfiledict={}
+ if self.settings.has_key("NOCONFMEM"):
+ cfgfiledict["IGNORE"]=1
+ else:
+ cfgfiledict["IGNORE"]=0
+
+ # set umask to 0 for merging; back up umask, save old one in prevmask (since this is a global change)
+ mymtime = long(time.time())
+ prevmask = os.umask(0)
+ secondhand = []
+
+ # we do a first merge; this will recurse through all files in our srcroot but also build up a
+ # "second hand" of symlinks to merge later
+ if self.mergeme(srcroot,destroot,outfile,secondhand,"",cfgfiledict,mymtime):
+ return 1
+
+ # now, it's time for dealing our second hand; we'll loop until we can't merge anymore. The rest are
+ # broken symlinks. We'll merge them too.
+ lastlen=0
+ while len(secondhand) and len(secondhand)!=lastlen:
+ # clear the thirdhand. Anything from our second hand that
+ # couldn't get merged will be added to thirdhand.
+
+ thirdhand=[]
+ self.mergeme(srcroot,destroot,outfile,thirdhand,secondhand,cfgfiledict,mymtime)
+
+ #swap hands
+ lastlen=len(secondhand)
+
+ # our thirdhand now becomes our secondhand. It's ok to throw
+ # away secondhand since thirdhand contains all the stuff that
+ # couldn't be merged.
+ secondhand = thirdhand
+
+ if len(secondhand):
+ # force merge of remaining symlinks (broken or circular; oh well)
+ self.mergeme(srcroot,destroot,outfile,None,secondhand,cfgfiledict,mymtime)
+
+ #restore umask
+ os.umask(prevmask)
+
+ #if we opened it, close it
+ outfile.flush()
+ outfile.close()
+
+ if (oldcontents):
+ print ">>> Safely unmerging already-installed instance..."
+ self.dbdir = self.dbpkgdir
+ self.unmerge(oldcontents,trimworld=0)
+ self.dbdir = self.dbtmpdir
+ print ">>> original instance of package unmerged safely."
+
+ # We hold both directory locks.
+ self.dbdir = self.dbpkgdir
+ self.delete()
+ movefile(self.dbtmpdir, self.dbpkgdir, mysettings=self.settings)
+
+ self.unlockdb()
+
+ #write out our collection of md5sums
+ if cfgfiledict.has_key("IGNORE"):
+ del cfgfiledict["IGNORE"]
+
+ # XXXX: HACK! PathSpec is very necessary here.
+ if not os.path.exists(destroot+PRIVATE_PATH):
+ os.makedirs(destroot+PRIVATE_PATH)
+ os.chown(destroot+PRIVATE_PATH,os.getuid(),portage_gid)
+ os.chmod(destroot+PRIVATE_PATH,02770)
+ dirlist = prefix_array(listdir(destroot+PRIVATE_PATH),destroot+PRIVATE_PATH+"/")
+ while dirlist:
+ dirlist.sort()
+ dirlist.reverse() # Gets them in file-before basedir order
+ x = dirlist[0]
+ if os.path.isdir(x):
+ dirlist += prefix_array(listdir(x),x+"/")
+ continue
+ os.unlink(destroot+PRIVATE_PATH+"/"+x)
+
+ mylock = portage_locks.lockfile(destroot+CONFIG_MEMORY_FILE)
+ writedict(cfgfiledict,destroot+CONFIG_MEMORY_FILE)
+ portage_locks.unlockfile(mylock)
+
+ #do postinst script
+ if myebuild:
+ # if we are merging a new ebuild, use *its* pre/postinst rather than using the one in /var/db/pkg
+ # (if any).
+ a=doebuild(myebuild,"postinst",root,self.settings,use_cache=0)
+ else:
+ a=doebuild(inforoot+"/"+self.pkg+".ebuild","postinst",root,self.settings,use_cache=0)
+
+ # XXX: Decide how to handle failures here.
+ if a != 0:
+ writemsg("!!! FAILED postinst: "+str(a)+"\n")
+ sys.exit(123)
+
+ downgrade = False
+ for v in otherversions:
+ if pkgcmp(catpkgsplit(self.pkg)[1:], catpkgsplit(v)[1:]) < 0:
+ downgrade = True
+
+ #update environment settings, library paths. DO NOT change symlinks.
+ env_update(makelinks=(not downgrade))
+ #dircache may break autoclean because it remembers the -MERGING-pkg file
+ global dircache
+ if dircache.has_key(self.dbcatdir):
+ del dircache[self.dbcatdir]
+ print ">>>",self.mycpv,"merged."
+ return 0
+
+ def mergeme(self,srcroot,destroot,outfile,secondhand,stufftomerge,cfgfiledict,thismtime):
+ srcroot=os.path.normpath("///"+srcroot)+"/"
+ destroot=os.path.normpath("///"+destroot)+"/"
+ # this is supposed to merge a list of files. There will be 2 forms of argument passing.
+ if type(stufftomerge)==types.StringType:
+ #A directory is specified. Figure out protection paths, listdir() it and process it.
+ mergelist=listdir(srcroot+stufftomerge)
+ offset=stufftomerge
+ # We need mydest defined up here to calc. protection paths. This is now done once per
+ # directory rather than once per file merge. This should really help merge performance.
+ # Trailing / ensures that protects/masks with trailing /'s match.
+ mytruncpath="/"+offset+"/"
+ myppath=self.isprotected(mytruncpath)
+ else:
+ mergelist=stufftomerge
+ offset=""
+ for x in mergelist:
+ mysrc=os.path.normpath("///"+srcroot+offset+x)
+ mydest=os.path.normpath("///"+destroot+offset+x)
+ # myrealdest is mydest without the $ROOT prefix (makes a difference if ROOT!="/")
+ myrealdest="/"+offset+x
+ # stat file once, test using S_* macros many times (faster that way)
+ try:
+ mystat=os.lstat(mysrc)
+ except SystemExit, e:
+ raise
+ except OSError, e:
+ writemsg("\n")
+ writemsg(red("!!! ERROR: There appears to be ")+bold("FILE SYSTEM CORRUPTION.")+red(" A file that is listed\n"))
+ writemsg(red("!!! as existing is not capable of being stat'd. If you are using an\n"))
+ writemsg(red("!!! experimental kernel, please boot into a stable one, force an fsck,\n"))
+ writemsg(red("!!! and ensure your filesystem is in a sane state. ")+bold("'shutdown -Fr now'\n"))
+ writemsg(red("!!! File: ")+str(mysrc)+"\n")
+ writemsg(red("!!! Error: ")+str(e)+"\n")
+ sys.exit(1)
+ except Exception, e:
+ writemsg("\n")
+ writemsg(red("!!! ERROR: An unknown error has occurred during the merge process.\n"))
+ writemsg(red("!!! A stat call returned the following error for the following file:"))
+ writemsg( "!!! Please ensure that your filesystem is intact, otherwise report\n")
+ writemsg( "!!! this as a portage bug at bugs.gentoo.org. Append 'emerge info'.\n")
+ writemsg( "!!! File: "+str(mysrc)+"\n")
+ writemsg( "!!! Error: "+str(e)+"\n")
+ sys.exit(1)
+
+
+ mymode=mystat[stat.ST_MODE]
+ # handy variables; mydest is the target object on the live filesystems;
+ # mysrc is the source object in the temporary install dir
+ try:
+ mydmode=os.lstat(mydest)[stat.ST_MODE]
+ except SystemExit, e:
+ raise
+ except:
+ #dest file doesn't exist
+ mydmode=None
+
+ if stat.S_ISLNK(mymode):
+ # we are merging a symbolic link
+ myabsto=abssymlink(mysrc)
+ if myabsto[0:len(srcroot)]==srcroot:
+ myabsto=myabsto[len(srcroot):]
+ if myabsto[0]!="/":
+ myabsto="/"+myabsto
+ myto=os.readlink(mysrc)
+ if self.settings and self.settings["D"]:
+ if myto.find(self.settings["D"])==0:
+ myto=myto[len(self.settings["D"]):]
+ # myrealto contains the path of the real file to which this symlink points.
+ # we can simply test for existence of this file to see if the target has been merged yet
+ myrealto=os.path.normpath(os.path.join(destroot,myabsto))
+ if mydmode!=None:
+ #destination exists
+ if not stat.S_ISLNK(mydmode):
+ if stat.S_ISDIR(mydmode):
+ # directory in the way: we can't merge a symlink over a directory
+ # we won't merge this, continue with next file...
+ continue
+ if self.isprotected(mydest):
+ # Use md5 of the target in ${D} if it exists...
+ if os.path.exists(os.path.normpath(srcroot+myabsto)):
+ try:
+ mydest = new_protect_filename(myrealdest, newmd5=portage_checksum.perform_md5(srcroot+myabsto))
+ except IOError:
+ print "========================================"
+ print "mysrc",mysrc
+ print "mymode",mymode
+ print "myabsto",myabsto
+ print "myto",myto
+ print "myrealto",myrealto
+ print "mydest",mydest
+ print "mydmode",mydmode
+ print "========================================"
+ print "Please file the above in bug #71787"
+ sys.exit(1)
+ else:
+ mydest = new_protect_filename(myrealdest, newmd5=portage_checksum.perform_md5(myabsto))
+
+ # if secondhand==None it means we're operating in "force" mode and should not create a second hand.
+ if (secondhand!=None) and (not os.path.exists(myrealto)):
+ # either the target directory doesn't exist yet or the target file doesn't exist -- or
+ # the target is a broken symlink. We will add this file to our "second hand" and merge
+ # it later.
+ secondhand.append(mysrc[len(srcroot):])
+ continue
+ # unlinking no longer necessary; "movefile" will overwrite symlinks atomically and correctly
+ mymtime=movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)
+ if mymtime!=None:
+ print ">>>",mydest,"->",myto
+ outfile.write("sym "+myrealdest+" -> "+myto+" "+str(mymtime)+"\n")
+ else:
+ print "!!! Failed to move file."
+ print "!!!",mydest,"->",myto
+ sys.exit(1)
+ elif stat.S_ISDIR(mymode):
+ # we are merging a directory
+ if mydmode!=None:
+ # destination exists
+
+ if bsd_chflags:
+ # Save then clear flags on dest.
+ dflags=bsd_chflags.lgetflags(mydest)
+ if(bsd_chflags.lchflags(mydest, 0)<0):
+ writemsg("!!! Couldn't clear flags on '"+mydest+"'.\n")
+
+ if not os.access(mydest, os.W_OK):
+ pkgstuff = pkgsplit(self.pkg)
+ writemsg("\n!!! Cannot write to '"+mydest+"'.\n")
+ writemsg("!!! Please check permissions and directories for broken symlinks.\n")
+ writemsg("!!! You may start the merge process again by using ebuild:\n")
+ writemsg("!!! ebuild "+self.settings["PORTDIR"]+"/"+self.cat+"/"+pkgstuff[0]+"/"+self.pkg+".ebuild merge\n")
+ writemsg("!!! And finish by running this: env-update\n\n")
+ return 1
+
+ if stat.S_ISLNK(mydmode) or stat.S_ISDIR(mydmode):
+ # a symlink to an existing directory will work for us; keep it:
+ print "---",mydest+"/"
+ if bsd_chflags:
+ bsd_chflags.lchflags(mydest, dflags)
+ else:
+ # a non-directory and non-symlink-to-directory. Won't work for us. Move out of the way.
+ if movefile(mydest,mydest+".backup", mysettings=self.settings) == None:
+ sys.exit(1)
+ print "bak",mydest,mydest+".backup"
+ #now create our directory
+ if selinux_enabled:
+ sid = selinux.get_sid(mysrc)
+ selinux.secure_mkdir(mydest,sid)
+ else:
+ os.mkdir(mydest)
+ if bsd_chflags:
+ bsd_chflags.lchflags(mydest, dflags)
+ os.chmod(mydest,mystat[0])
+ lchown(mydest,mystat[4],mystat[5])
+ print ">>>",mydest+"/"
+ else:
+ #destination doesn't exist
+ if selinux_enabled:
+ sid = selinux.get_sid(mysrc)
+ selinux.secure_mkdir(mydest,sid)
+ else:
+ os.mkdir(mydest)
+ os.chmod(mydest,mystat[0])
+ if bsd_chflags:
+ bsd_chflags.lchflags(mydest, bsd_chflags.lgetflags(mysrc))
+ lchown(mydest,mystat[4],mystat[5])
+ print ">>>",mydest+"/"
+ outfile.write("dir "+myrealdest+"\n")
+ # recurse and merge this directory
+ if self.mergeme(srcroot,destroot,outfile,secondhand,offset+x+"/",cfgfiledict,thismtime):
+ return 1
+ elif stat.S_ISREG(mymode):
+ # we are merging a regular file
+ mymd5=portage_checksum.perform_md5(mysrc,calc_prelink=1)
+ # calculate config file protection stuff
+ mydestdir=os.path.dirname(mydest)
+ moveme=1
+ zing="!!!"
+ if mydmode!=None:
+ # destination file exists
+ if stat.S_ISDIR(mydmode):
+ # install of destination is blocked by an existing directory with the same name
+ moveme=0
+ print "!!!",mydest
+ elif stat.S_ISREG(mydmode) or (stat.S_ISLNK(mydmode) and os.path.exists(mydest) and stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])):
+ cfgprot=0
+ # install of destination is blocked by an existing regular file,
+ # or by a symlink to an existing regular file;
+ # now, config file management may come into play.
+ # we only need to tweak mydest if cfg file management is in play.
+ if myppath:
+ # we have a protection path; enable config file management.
+ destmd5=portage_checksum.perform_md5(mydest,calc_prelink=1)
+ cycled=0
+ if cfgfiledict.has_key(myrealdest):
+ if destmd5 in cfgfiledict[myrealdest]:
+ #cycle
+ print "cycle"
+ del cfgfiledict[myrealdest]
+ cycled=1
+ if mymd5==destmd5:
+ #file already in place; simply update mtimes of destination
+ os.utime(mydest,(thismtime,thismtime))
+ zing="---"
+ moveme=0
+ elif cycled:
+ #mymd5!=destmd5 and we've cycled; move mysrc into place as a ._cfg file
+ moveme=1
+ cfgfiledict[myrealdest]=[mymd5]
+ cfgprot=1
+ elif cfgfiledict.has_key(myrealdest) and (mymd5 in cfgfiledict[myrealdest]):
+ #myd5!=destmd5, we haven't cycled, and the file we're merging has been already merged previously
+ zing="-o-"
+ moveme=cfgfiledict["IGNORE"]
+ cfgprot=cfgfiledict["IGNORE"]
+ else:
+ #mymd5!=destmd5, we haven't cycled, and the file we're merging hasn't been merged before
+ moveme=1
+ cfgprot=1
+ if not cfgfiledict.has_key(myrealdest):
+ cfgfiledict[myrealdest]=[]
+ if mymd5 not in cfgfiledict[myrealdest]:
+ cfgfiledict[myrealdest].append(mymd5)
+ #don't record more than 16 md5sums
+ if len(cfgfiledict[myrealdest])>16:
+ del cfgfiledict[myrealdest][0]
+
+ if cfgprot:
+ mydest = new_protect_filename(myrealdest, newmd5=mymd5)
+
+ # whether config protection or not, we merge the new file the
+ # same way. Unless moveme=0 (blocking directory)
+ if moveme:
+ mymtime=movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)
+ if mymtime == None:
+ sys.exit(1)
+ zing=">>>"
+ else:
+ mymtime=thismtime
+ # We need to touch the destination so that on --update the
+ # old package won't yank the file with it. (non-cfgprot related)
+ os.utime(myrealdest,(thismtime,thismtime))
+ zing="---"
+ if self.settings["USERLAND"] == "Darwin" and myrealdest[-2:] == ".a":
+
+ # XXX kludge, bug #58848; can be killed when portage stops relying on
+ # md5+mtime, and uses refcounts
+ # alright, we've fooled w/ mtime on the file; this pisses off static archives
+ # basically internal mtime != file's mtime, so the linker (falsely) thinks
+ # the archive is stale, and needs to have it's toc rebuilt.
+
+ myf=open(myrealdest,"r+")
+
+ # ar mtime field is digits padded with spaces, 12 bytes.
+ lms=str(thismtime+5).ljust(12)
+ myf.seek(0)
+ magic=myf.read(8)
+ if magic != "!<arch>\n":
+ # not an archive (dolib.a from portage.py makes it here fex)
+ myf.close()
+ else:
+ st=os.stat(myrealdest)
+ while myf.tell() < st.st_size - 12:
+ # skip object name
+ myf.seek(16,1)
+
+ # update mtime
+ myf.write(lms)
+
+ # skip uid/gid/mperm
+ myf.seek(20,1)
+
+ # read the archive member's size
+ x=long(myf.read(10))
+
+ # skip the trailing newlines, and add the potential
+ # extra padding byte if it's not an even size
+ myf.seek(x + 2 + (x % 2),1)
+
+ # and now we're at the end. yay.
+ myf.close()
+ mymd5=portage_checksum.perform_md5(myrealdest,calc_prelink=1)
+ os.utime(myrealdest,(thismtime,thismtime))
+
+ if mymtime!=None:
+ zing=">>>"
+ outfile.write("obj "+myrealdest+" "+mymd5+" "+str(mymtime)+"\n")
+ print zing,mydest
+ else:
+ # we are merging a fifo or device node
+ zing="!!!"
+ if mydmode==None:
+ # destination doesn't exist
+ if movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)!=None:
+ zing=">>>"
+ if stat.S_ISFIFO(mymode):
+ # we don't record device nodes in CONTENTS,
+ # although we do merge them.
+ outfile.write("fif "+myrealdest+"\n")
+ else:
+ sys.exit(1)
+ print zing+" "+mydest
+
+ def merge(self,mergeroot,inforoot,myroot,myebuild=None,cleanup=0):
+ return self.treewalk(mergeroot,myroot,inforoot,myebuild,cleanup=cleanup)
+
+ def getstring(self,name):
+ "returns contents of a file with whitespace converted to spaces"
+ if not os.path.exists(self.dbdir+"/"+name):
+ return ""
+ myfile=open(self.dbdir+"/"+name,"r")
+ mydata=string.split(myfile.read())
+ myfile.close()
+ return string.join(mydata," ")
+
+ def copyfile(self,fname):
+ shutil.copyfile(fname,self.dbdir+"/"+os.path.basename(fname))
+
+ def getfile(self,fname):
+ if not os.path.exists(self.dbdir+"/"+fname):
+ return ""
+ myfile=open(self.dbdir+"/"+fname,"r")
+ mydata=myfile.read()
+ myfile.close()
+ return mydata
+
+ def setfile(self,fname,data):
+ myfile=open(self.dbdir+"/"+fname,"w")
+ myfile.write(data)
+ myfile.close()
+
+ def getelements(self,ename):
+ if not os.path.exists(self.dbdir+"/"+ename):
+ return []
+ myelement=open(self.dbdir+"/"+ename,"r")
+ mylines=myelement.readlines()
+ myreturn=[]
+ for x in mylines:
+ for y in string.split(x[:-1]):
+ myreturn.append(y)
+ myelement.close()
+ return myreturn
+
+ def setelements(self,mylist,ename):
+ myelement=open(self.dbdir+"/"+ename,"w")
+ for x in mylist:
+ myelement.write(x+"\n")
+ myelement.close()
+
+ def isregular(self):
+ "Is this a regular package (does it have a CATEGORY file? A dblink can be virtual *and* regular)"
+ return os.path.exists(self.dbdir+"/CATEGORY")
+
+def cleanup_pkgmerge(mypkg,origdir):
+ shutil.rmtree(settings["PORTAGE_TMPDIR"]+"/portage-pkg/"+mypkg)
+ if os.path.exists(settings["PORTAGE_TMPDIR"]+"/portage/"+mypkg+"/temp/environment"):
+ os.unlink(settings["PORTAGE_TMPDIR"]+"/portage/"+mypkg+"/temp/environment")
+ os.chdir(origdir)
+
+def pkgmerge(mytbz2,myroot,mysettings):
+ """will merge a .tbz2 file, returning a list of runtime dependencies
+ that must be satisfied, or None if there was a merge error. This
+ code assumes the package exists."""
+ if mytbz2[-5:]!=".tbz2":
+ print "!!! Not a .tbz2 file"
+ return None
+ mypkg=os.path.basename(mytbz2)[:-5]
+ xptbz2=xpak.tbz2(mytbz2)
+ pkginfo={}
+ mycat=xptbz2.getfile("CATEGORY")
+ if not mycat:
+ print "!!! CATEGORY info missing from info chunk, aborting..."
+ return None
+ mycat=mycat.strip()
+ mycatpkg=mycat+"/"+mypkg
+ tmploc=mysettings["PORTAGE_TMPDIR"]+"/portage-pkg/"
+ pkgloc=tmploc+"/"+mypkg+"/bin/"
+ infloc=tmploc+"/"+mypkg+"/inf/"
+ myebuild=tmploc+"/"+mypkg+"/inf/"+os.path.basename(mytbz2)[:-4]+"ebuild"
+ if os.path.exists(tmploc+"/"+mypkg):
+ shutil.rmtree(tmploc+"/"+mypkg,1)
+ os.makedirs(pkgloc)
+ os.makedirs(infloc)
+ print ">>> extracting info"
+ xptbz2.unpackinfo(infloc)
+ # run pkg_setup early, so we can bail out early
+ # (before extracting binaries) if there's a problem
+ origdir=getcwd()
+ os.chdir(pkgloc)
+
+ mysettings.configdict["pkg"]["CATEGORY"] = mycat;
+ a=doebuild(myebuild,"setup",myroot,mysettings,tree="bintree")
+ print ">>> extracting",mypkg
+ notok=spawn("bzip2 -dqc -- '"+mytbz2+"' | tar xpf -",mysettings,free=1)
+ if notok:
+ print "!!! Error extracting",mytbz2
+ cleanup_pkgmerge(mypkg,origdir)
+ return None
+
+ # the merge takes care of pre/postinst and old instance
+ # auto-unmerge, virtual/provides updates, etc.
+ mysettings.load_infodir(infloc)
+ mylink=dblink(mycat,mypkg,myroot,mysettings)
+ mylink.merge(pkgloc,infloc,myroot,myebuild,cleanup=1)
+
+ if not os.path.exists(infloc+"/RDEPEND"):
+ returnme=""
+ else:
+ #get runtime dependencies
+ a=open(infloc+"/RDEPEND","r")
+ returnme=string.join(string.split(a.read())," ")
+ a.close()
+ cleanup_pkgmerge(mypkg,origdir)
+ return returnme
+
+
+if os.environ.has_key("ROOT"):
+ root=os.environ["ROOT"]
+ if not len(root):
+ root="/"
+ elif root[-1]!="/":
+ root=root+"/"
+else:
+ root="/"
+if root != "/":
+ if not os.path.exists(root[:-1]):
+ writemsg("!!! Error: ROOT "+root+" does not exist. Please correct this.\n")
+ writemsg("!!! Exiting.\n\n")
+ sys.exit(1)
+ elif not os.path.isdir(root[:-1]):
+ writemsg("!!! Error: ROOT "+root[:-1]+" is not a directory. Please correct this.\n")
+ writemsg("!!! Exiting.\n\n")
+ sys.exit(1)
+
+#create tmp and var/tmp if they don't exist; read config
+os.umask(0)
+if not os.path.exists(root+"tmp"):
+ writemsg(">>> "+root+"tmp doesn't exist, creating it...\n")
+ os.mkdir(root+"tmp",01777)
+if not os.path.exists(root+"var/tmp"):
+ writemsg(">>> "+root+"var/tmp doesn't exist, creating it...\n")
+ try:
+ os.mkdir(root+"var",0755)
+ except (OSError,IOError):
+ pass
+ try:
+ os.mkdir(root+"var/tmp",01777)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("portage: couldn't create /var/tmp; exiting.\n")
+ sys.exit(1)
+if not os.path.exists(root+"var/lib/portage"):
+ writemsg(">>> "+root+"var/lib/portage doesn't exist, creating it...\n")
+ try:
+ os.mkdir(root+"var",0755)
+ except (OSError,IOError):
+ pass
+ try:
+ os.mkdir(root+"var/lib",0755)
+ except (OSError,IOError):
+ pass
+ try:
+ os.mkdir(root+"var/lib/portage",02750)
+ except SystemExit, e:
+ raise
+ except:
+ writemsg("portage: couldn't create /var/lib/portage; exiting.\n")
+ sys.exit(1)
+
+
+#####################################
+# Deprecation Checks
+
+os.umask(022)
+profiledir=None
+if "PORTAGE_CALLER" in os.environ and os.environ["PORTAGE_CALLER"] == "emerge" and os.path.isdir(PROFILE_PATH):
+ profiledir = PROFILE_PATH
+ if os.access(DEPRECATED_PROFILE_FILE, os.R_OK):
+ deprecatedfile = open(DEPRECATED_PROFILE_FILE, "r")
+ dcontent = deprecatedfile.readlines()
+ deprecatedfile.close()
+ newprofile = dcontent[0]
+ writemsg(red("\n!!! Your current profile is deprecated and not supported anymore.\n"))
+ writemsg(red("!!! Please upgrade to the following profile if possible:\n"))
+ writemsg(8*" "+green(newprofile)+"\n")
+ if len(dcontent) > 1:
+ writemsg("To upgrade do the following steps:\n")
+ for myline in dcontent[1:]:
+ writemsg(myline)
+ writemsg("\n\n")
+
+if os.path.exists(USER_VIRTUALS_FILE):
+ writemsg(red("\n!!! /etc/portage/virtuals is deprecated in favor of\n"))
+ writemsg(red("!!! /etc/portage/profile/virtuals. Please move it to\n"))
+ writemsg(red("!!! this new location.\n\n"))
+
+#
+#####################################
+
+db={}
+
+# =============================================================================
+# =============================================================================
+# -----------------------------------------------------------------------------
+# We're going to lock the global config to prevent changes, but we need
+# to ensure the global settings are right.
+settings=config(config_profile_path=PROFILE_PATH,config_incrementals=portage_const.INCREMENTALS)
+
+# useful info
+settings["PORTAGE_MASTER_PID"]=str(os.getpid())
+settings.backup_changes("PORTAGE_MASTER_PID")
+# We are disabling user-specific bashrc files.
+settings["BASH_ENV"] = INVALID_ENV_FILE
+settings.backup_changes("BASH_ENV")
+
+# gets virtual package settings
+def getvirtuals(myroot):
+ global settings
+ writemsg("--- DEPRECATED call to getvirtual\n")
+ return settings.getvirtuals(myroot)
+
+def do_vartree(mysettings):
+ global virts,virts_p
+ virts=mysettings.getvirtuals("/")
+ virts_p={}
+
+ if virts:
+ myvkeys=virts.keys()
+ for x in myvkeys:
+ vkeysplit=x.split("/")
+ if not virts_p.has_key(vkeysplit[1]):
+ virts_p[vkeysplit[1]]=virts[x]
+ db["/"]={"virtuals":virts,"vartree":vartree("/",virts)}
+ if root!="/":
+ virts=mysettings.getvirtuals(root)
+ db[root]={"virtuals":virts,"vartree":vartree(root,virts)}
+ #We need to create the vartree first, then load our settings, and then set up our other trees
+
+usedefaults=settings.use_defs
+
+# XXX: This is a circular fix.
+#do_vartree(settings)
+#settings.loadVirtuals('/')
+do_vartree(settings)
+#settings.loadVirtuals('/')
+
+settings.reset() # XXX: Regenerate use after we get a vartree -- GLOBAL
+
+
+# XXX: Might cause problems with root="/" assumptions
+portdb=portdbapi(settings["PORTDIR"])
+
+settings.lock()
+# -----------------------------------------------------------------------------
+# =============================================================================
+# =============================================================================
+
+
+if 'selinux' in settings["USE"].split(" "):
+ try:
+ import selinux
+ selinux_enabled=1
+ except OSError, e:
+ writemsg(red("!!! SELinux not loaded: ")+str(e)+"\n")
+ selinux_enabled=0
+ except ImportError:
+ writemsg(red("!!! SELinux module not found.")+" Please verify that it was installed.\n")
+ selinux_enabled=0
+else:
+ selinux_enabled=0
+
+cachedirs=[CACHE_PATH]
+if root!="/":
+ cachedirs.append(root+CACHE_PATH)
+if not os.environ.has_key("SANDBOX_ACTIVE"):
+ for cachedir in cachedirs:
+ if not os.path.exists(cachedir):
+ os.makedirs(cachedir,0755)
+ writemsg(">>> "+cachedir+" doesn't exist, creating it...\n")
+ if not os.path.exists(cachedir+"/dep"):
+ os.makedirs(cachedir+"/dep",2755)
+ writemsg(">>> "+cachedir+"/dep doesn't exist, creating it...\n")
+ try:
+ os.chown(cachedir,uid,portage_gid)
+ os.chmod(cachedir,0775)
+ except OSError:
+ pass
+ try:
+ mystat=os.lstat(cachedir+"/dep")
+ os.chown(cachedir+"/dep",uid,portage_gid)
+ os.chmod(cachedir+"/dep",02775)
+ if mystat[stat.ST_GID]!=portage_gid:
+ spawn("chown -R "+str(uid)+":"+str(portage_gid)+" "+cachedir+"/dep",settings,free=1)
+ spawn("chmod -R u+rw,g+rw "+cachedir+"/dep",settings,free=1)
+ except OSError:
+ pass
+
+def flushmtimedb(record):
+ if mtimedb:
+ if record in mtimedb.keys():
+ del mtimedb[record]
+ #print "mtimedb["+record+"] is cleared."
+ else:
+ writemsg("Invalid or unset record '"+record+"' in mtimedb.\n")
+
+#grab mtimes for eclasses and upgrades
+mtimedb={}
+mtimedbkeys=[
+"updates", "info",
+"version", "starttime",
+"resume", "ldpath"
+]
+mtimedbfile=root+"var/cache/edb/mtimedb"
+try:
+ mypickle=cPickle.Unpickler(open(mtimedbfile))
+ mypickle.find_global=None
+ mtimedb=mypickle.load()
+ if mtimedb.has_key("old"):
+ mtimedb["updates"]=mtimedb["old"]
+ del mtimedb["old"]
+ if mtimedb.has_key("cur"):
+ del mtimedb["cur"]
+except SystemExit, e:
+ raise
+except:
+ #print "!!!",e
+ mtimedb={"updates":{},"version":"","starttime":0}
+
+for x in mtimedb.keys():
+ if x not in mtimedbkeys:
+ writemsg("Deleting invalid mtimedb key: "+str(x)+"\n")
+ del mtimedb[x]
+
+#,"porttree":portagetree(root,virts),"bintree":binarytree(root,virts)}
+features=settings["FEATURES"].split()
+
+do_upgrade_packagesmessage=0
+def do_upgrade(mykey):
+ global do_upgrade_packagesmessage
+ writemsg("\n\n")
+ writemsg(green("Performing Global Updates: ")+bold(mykey)+"\n")
+ writemsg("(Could take a couple of minutes if you have a lot of binary packages.)\n")
+ writemsg(" "+bold(".")+"='update pass' "+bold("*")+"='binary update' "+bold("@")+"='/var/db move'\n"+" "+bold("s")+"='/var/db SLOT move' "+bold("S")+"='binary SLOT move' "+bold("p")+"='update /etc/portage/package.*'\n")
+ processed=1
+ #remove stale virtual entries (mappings for packages that no longer exist)
+
+ update_files={}
+ file_contents={}
+ myxfiles = ["package.mask","package.unmask","package.keywords","package.use"]
+ myxfiles = myxfiles + prefix_array(myxfiles, "profile/")
+ for x in myxfiles:
+ try:
+ myfile = open("/etc/portage/"+x,"r")
+ file_contents[x] = myfile.readlines()
+ myfile.close()
+ except IOError:
+ if file_contents.has_key(x):
+ del file_contents[x]
+ continue
+
+ worldlist=grabfile("/"+WORLD_FILE)
+ myupd=grabfile(mykey)
+ db["/"]["bintree"]=binarytree("/",settings["PKGDIR"],virts)
+ for myline in myupd:
+ mysplit=myline.split()
+ if not len(mysplit):
+ continue
+ if mysplit[0]!="move" and mysplit[0]!="slotmove":
+ writemsg("portage: Update type \""+mysplit[0]+"\" not recognized.\n")
+ processed=0
+ continue
+ if mysplit[0]=="move" and len(mysplit)!=3:
+ writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n")
+ processed=0
+ continue
+ if mysplit[0]=="slotmove" and len(mysplit)!=4:
+ writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n")
+ processed=0
+ continue
+ sys.stdout.write(".")
+ sys.stdout.flush()
+
+ if mysplit[0]=="move":
+ db["/"]["vartree"].dbapi.move_ent(mysplit)
+ db["/"]["bintree"].move_ent(mysplit)
+ #update world entries:
+ for x in range(0,len(worldlist)):
+ #update world entries, if any.
+ worldlist[x]=dep_transform(worldlist[x],mysplit[1],mysplit[2])
+
+ #update /etc/portage/packages.*
+ for x in file_contents:
+ for mypos in range(0,len(file_contents[x])):
+ line=file_contents[x][mypos]
+ if line[0]=="#" or string.strip(line)=="":
+ continue
+ key=dep_getkey(line.split()[0])
+ if key==mysplit[1]:
+ file_contents[x][mypos]=string.replace(line,mysplit[1],mysplit[2])
+ update_files[x]=1
+ sys.stdout.write("p")
+ sys.stdout.flush()
+
+ elif mysplit[0]=="slotmove":
+ db["/"]["vartree"].dbapi.move_slot_ent(mysplit)
+ db["/"]["bintree"].move_slot_ent(mysplit,settings["PORTAGE_TMPDIR"]+"/tbz2")
+
+ for x in update_files:
+ mydblink = dblink('','','/',settings)
+ if mydblink.isprotected("/etc/portage/"+x):
+ updating_file=new_protect_filename("/etc/portage/"+x)[0]
+ else:
+ updating_file="/etc/portage/"+x
+ try:
+ myfile=open(updating_file,"w")
+ myfile.writelines(file_contents[x])
+ myfile.close()
+ except IOError:
+ continue
+
+ # We gotta do the brute force updates for these now.
+ if (settings["PORTAGE_CALLER"] in ["fixpackages"]) or \
+ ("fixpackages" in features):
+ db["/"]["bintree"].update_ents(myupd,settings["PORTAGE_TMPDIR"]+"/tbz2")
+ else:
+ do_upgrade_packagesmessage = 1
+
+ if processed:
+ #update our internal mtime since we processed all our directives.
+ mtimedb["updates"][mykey]=os.stat(mykey)[stat.ST_MTIME]
+ myworld=open("/"+WORLD_FILE,"w")
+ for x in worldlist:
+ myworld.write(x+"\n")
+ myworld.close()
+ print ""
+
+def portageexit():
+ global uid,portage_gid,portdb,db
+ if secpass and not os.environ.has_key("SANDBOX_ACTIVE"):
+ # wait child process death
+ try:
+ while True:
+ os.wait()
+ except OSError:
+ #writemsg(">>> All child process are now dead.")
+ pass
+
+ close_portdbapi_caches()
+
+ if mtimedb:
+ # Store mtimedb
+ mymfn=mtimedbfile
+ try:
+ mtimedb["version"]=VERSION
+ cPickle.dump(mtimedb, open(mymfn,"w"), -1)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+ try:
+ os.chown(mymfn,uid,portage_gid)
+ os.chmod(mymfn,0664)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ pass
+
+atexit.register(portageexit)
+
+if (secpass==2) and (not os.environ.has_key("SANDBOX_ACTIVE")):
+ if settings["PORTAGE_CALLER"] in ["emerge","fixpackages"]:
+ #only do this if we're root and not running repoman/ebuild digest
+ updpath=os.path.normpath(settings["PORTDIR"]+"///profiles/updates")
+ didupdate=0
+ if not mtimedb.has_key("updates"):
+ mtimedb["updates"]={}
+ try:
+ mylist=listdir(updpath,EmptyOnError=1)
+ # resort the list
+ mylist=[myfile[3:]+"-"+myfile[:2] for myfile in mylist]
+ mylist.sort()
+ mylist=[myfile[5:]+"-"+myfile[:4] for myfile in mylist]
+ for myfile in mylist:
+ mykey=updpath+"/"+myfile
+ if not os.path.isfile(mykey):
+ continue
+ if (not mtimedb["updates"].has_key(mykey)) or \
+ (mtimedb["updates"][mykey] != os.stat(mykey)[stat.ST_MTIME]) or \
+ (settings["PORTAGE_CALLER"] == "fixpackages"):
+ didupdate=1
+ do_upgrade(mykey)
+ portageexit() # This lets us save state for C-c.
+ except OSError:
+ #directory doesn't exist
+ pass
+ if didupdate:
+ #make sure our internal databases are consistent; recreate our virts and vartree
+ do_vartree(settings)
+ if do_upgrade_packagesmessage and \
+ listdir(settings["PKGDIR"]+"/All/",EmptyOnError=1):
+ writemsg("\n\n\n ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the")
+ writemsg("\n tbz2's in the packages directory. "+bold("Note: This can take a very long time."))
+ writemsg("\n")
+
+
+
+
+
+#continue setting up other trees
+db["/"]["porttree"]=portagetree("/",virts)
+db["/"]["bintree"]=binarytree("/",settings["PKGDIR"],virts)
+if root!="/":
+ db[root]["porttree"]=portagetree(root,virts)
+ db[root]["bintree"]=binarytree(root,settings["PKGDIR"],virts)
+thirdpartymirrors=grabdict(settings["PORTDIR"]+"/profiles/thirdpartymirrors")
+
+if not os.path.exists(settings["PORTAGE_TMPDIR"]):
+ writemsg("portage: the directory specified in your PORTAGE_TMPDIR variable, \""+settings["PORTAGE_TMPDIR"]+",\"\n")
+ writemsg("does not exist. Please create this directory or correct your PORTAGE_TMPDIR setting.\n")
+ sys.exit(1)
+if not os.path.isdir(settings["PORTAGE_TMPDIR"]):
+ writemsg("portage: the directory specified in your PORTAGE_TMPDIR variable, \""+settings["PORTAGE_TMPDIR"]+",\"\n")
+ writemsg("is not a directory. Please correct your PORTAGE_TMPDIR setting.\n")
+ sys.exit(1)
+
+# COMPATABILITY -- This shouldn't be used.
+pkglines = settings.packages
+
+groups=settings["ACCEPT_KEYWORDS"].split()
+archlist=[]
+for myarch in grabfile(settings["PORTDIR"]+"/profiles/arch.list"):
+ archlist += [myarch,"~"+myarch]
+for group in groups:
+ if not archlist:
+ writemsg("--- 'profiles/arch.list' is empty or not available. Empty portage tree?\n")
+ break
+ elif (group not in archlist) and group[0]!='-':
+ writemsg("\n"+red("!!! INVALID ACCEPT_KEYWORDS: ")+str(group)+"\n")
+
+# Clear the cache
+dircache={}
+
+if not os.path.islink(PROFILE_PATH) and os.path.exists(settings["PORTDIR"]+"/profiles"):
+ writemsg(red("\a\n\n!!! "+PROFILE_PATH+" is not a symlink and will probably prevent most merges.\n"))
+ writemsg(red("!!! It should point into a profile within %s/profiles/\n" % settings["PORTDIR"]))
+ writemsg(red("!!! (You can safely ignore this message when syncing. It's harmless.)\n\n\n"))
+ time.sleep(3)
+
+# ============================================================================
+# ============================================================================
+
diff --git a/pym/portage_checksum.py b/pym/portage_checksum.py
new file mode 100644
index 00000000..cefcda6d
--- /dev/null
+++ b/pym/portage_checksum.py
@@ -0,0 +1,134 @@
+# portage_checksum.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_checksum.py,v 1.10.2.2 2005/08/10 05:42:03 ferringb Exp $
+cvs_id_string="$Id: portage_checksum.py,v 1.10.2.2 2005/08/10 05:42:03 ferringb Exp $"[5:-2]
+
+from portage_const import PRIVATE_PATH,PRELINK_BINARY
+import os
+import shutil
+import stat
+import portage_exec
+import portage_util
+import portage_locks
+import commands
+import sha
+
+prelink_capable = False
+if os.path.exists(PRELINK_BINARY):
+ results = commands.getstatusoutput(PRELINK_BINARY+" --version > /dev/null 2>&1")
+ if (results[0] >> 8) == 0:
+ prelink_capable=1
+ del results
+
+def perform_md5(x, calc_prelink=0):
+ return perform_checksum(x, md5hash, calc_prelink)[0]
+
+def perform_sha1(x, calc_prelink=0):
+ return perform_checksum(x, sha1hash, calc_prelink)[0]
+
+def perform_all(x, calc_prelink=0):
+ mydict = {}
+ mydict["SHA1"] = perform_sha1(x, calc_prelink)
+ mydict["MD5"] = perform_md5(x, calc_prelink)
+ return mydict
+
+def get_valid_checksum_keys():
+ return ["SHA1", "MD5"]
+
+def verify_all(filename, mydict, calc_prelink=0, strict=0):
+ # Dict relates to single file only.
+ # returns: (passed,reason)
+ file_is_ok = True
+ reason = "Reason unknown"
+ try:
+ if mydict["size"] != os.stat(filename)[stat.ST_SIZE]:
+ return False,"Filesize does not match recorded size"
+ except OSError, e:
+ return False, str(e)
+ for x in mydict.keys():
+ if x == "size":
+ continue
+ elif x == "SHA1":
+ if mydict[x] != perform_sha1(filename, calc_prelink=calc_prelink):
+ if strict:
+ raise portage_exception.DigestException, "Failed to verify '$(file)s' on checksum type '%(type)s'" % {"file":filename, "type":x}
+ else:
+ file_is_ok = False
+ reason = "Failed on %s verification" % (x,)
+ break
+ elif x == "MD5":
+ if mydict[x] != perform_md5(filename, calc_prelink=calc_prelink):
+ if strict:
+ raise portage_exception.DigestException, "Failed to verify '$(file)s' on checksum type '%(type)s'" % {"file":filename, "type":x}
+ else:
+ file_is_ok = False
+ reason = "Failed on %s verification" % (x,)
+ break
+ return file_is_ok,reason
+
+# We _try_ to load this module. If it fails we do the slow fallback.
+try:
+ import fchksum
+
+ def md5hash(filename):
+ return fchksum.fmd5t(filename)
+
+except ImportError:
+ import md5
+ def md5hash(filename):
+ f = open(filename, 'rb')
+ blocksize=32768
+ data = f.read(blocksize)
+ size = 0L
+ sum = md5.new()
+ while data:
+ sum.update(data)
+ size = size + len(data)
+ data = f.read(blocksize)
+ f.close()
+
+ return (sum.hexdigest(),size)
+
+def sha1hash(filename):
+ f = open(filename, 'rb')
+ blocksize=32768
+ data = f.read(blocksize)
+ size = 0L
+ sum = sha.new()
+ while data:
+ sum.update(data)
+ size = size + len(data)
+ data = f.read(blocksize)
+ f.close()
+
+ return (sum.hexdigest(),size)
+
+def perform_checksum(filename, hash_function=md5hash, calc_prelink=0):
+ myfilename = filename[:]
+ prelink_tmpfile = PRIVATE_PATH+"/prelink-checksum.tmp."+str(os.getpid())
+ mylock = None
+
+ if calc_prelink and prelink_capable:
+ mylock = portage_locks.lockfile(prelink_tmpfile, wantnewlockfile=1)
+ # Create non-prelinked temporary file to md5sum.
+ # Raw data is returned on stdout, errors on stderr.
+ # Non-prelinks are just returned.
+ try:
+ shutil.copy2(filename,prelink_tmpfile)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ portage_util.writemsg("!!! Unable to copy file '"+str(filename)+"'.\n")
+ portage_util.writemsg("!!! "+str(e)+"\n")
+ raise
+ portage_exec.spawn(PRELINK_BINARY+" --undo "+prelink_tmpfile,fd_pipes={})
+ myfilename=prelink_tmpfile
+
+ myhash, mysize = hash_function(myfilename)
+
+ if calc_prelink and prelink_capable:
+ os.unlink(prelink_tmpfile)
+ portage_locks.unlockfile(mylock)
+
+ return (myhash,mysize)
diff --git a/pym/portage_const.py b/pym/portage_const.py
new file mode 100644
index 00000000..40ad3cf1
--- /dev/null
+++ b/pym/portage_const.py
@@ -0,0 +1,48 @@
+# portage: Constants
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_const.py,v 1.3.2.3 2005/04/29 04:56:35 jstubbs Exp $
+cvs_id_string="$Id: portage_const.py,v 1.3.2.3 2005/04/29 04:56:35 jstubbs Exp $"[5:-2]
+
+# ===========================================================================
+# START OF CONSTANTS -- START OF CONSTANTS -- START OF CONSTANTS -- START OF
+# ===========================================================================
+
+VDB_PATH = "var/db/pkg"
+PRIVATE_PATH = "/var/lib/portage"
+CACHE_PATH = "/var/cache/edb"
+DEPCACHE_PATH = CACHE_PATH+"/dep"
+
+USER_CONFIG_PATH = "/etc/portage"
+MODULES_FILE_PATH = USER_CONFIG_PATH+"/modules"
+CUSTOM_PROFILE_PATH = USER_CONFIG_PATH+"/profile"
+
+PORTAGE_BASE_PATH = "/usr/lib/portage"
+PORTAGE_BIN_PATH = PORTAGE_BASE_PATH+"/bin"
+PORTAGE_PYM_PATH = PORTAGE_BASE_PATH+"/pym"
+PROFILE_PATH = "/etc/make.profile"
+LOCALE_DATA_PATH = PORTAGE_BASE_PATH+"/locale"
+
+EBUILD_SH_BINARY = PORTAGE_BIN_PATH+"/ebuild.sh"
+SANDBOX_BINARY = "/usr/bin/sandbox"
+BASH_BINARY = "/bin/bash"
+MOVE_BINARY = "/bin/mv"
+PRELINK_BINARY = "/usr/sbin/prelink"
+
+WORLD_FILE = PRIVATE_PATH+"/world"
+MAKE_CONF_FILE = "/etc/make.conf"
+MAKE_DEFAULTS_FILE = PROFILE_PATH + "/make.defaults"
+DEPRECATED_PROFILE_FILE = PROFILE_PATH+"/deprecated"
+USER_VIRTUALS_FILE = USER_CONFIG_PATH+"/virtuals"
+EBUILD_SH_ENV_FILE = USER_CONFIG_PATH+"/bashrc"
+INVALID_ENV_FILE = "/etc/spork/is/not/valid/profile.env"
+CUSTOM_MIRRORS_FILE = USER_CONFIG_PATH+"/mirrors"
+SANDBOX_PIDS_FILE = "/tmp/sandboxpids.tmp"
+CONFIG_MEMORY_FILE = PRIVATE_PATH + "/config"
+
+INCREMENTALS=["USE","FEATURES","ACCEPT_KEYWORDS","ACCEPT_LICENSE","CONFIG_PROTECT_MASK","CONFIG_PROTECT","PRELINK_PATH","PRELINK_PATH_MASK"]
+STICKIES=["KEYWORDS_ACCEPT","USE","CFLAGS","CXXFLAGS","MAKEOPTS","EXTRA_ECONF","EXTRA_EINSTALL","EXTRA_EMAKE"]
+
+# ===========================================================================
+# END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANT
+# ===========================================================================
diff --git a/pym/portage_contents.py b/pym/portage_contents.py
new file mode 100644
index 00000000..0f0b2420
--- /dev/null
+++ b/pym/portage_contents.py
@@ -0,0 +1,161 @@
+# portage_contents.py -- (Persistent) Contents File Management
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_contents.py,v 1.3.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_contents.py,v 1.3.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import os,string,types,sys,copy
+import portage_exception
+import portage_const
+
+#import gettext
+#gettext_t = gettext.translation('portage.contents', portage_const.LOCALE_DATA_PATH)
+#_ = gettext_t.ugettext
+def _(mystr):
+ return mystr
+
+
+FILES_KEY = "\0FILES\0"
+OWNER_KEY = "\0OWNER\0"
+
+
+def ContentsHandler(filename):
+ infile = open(filename)
+ myfiles = []
+ mydirs = []
+
+ mylines = infile.readlines()
+ infile.close()
+ for line in mylines:
+ if line[-1] == '\n':
+ line = line[:-1]
+ parts = string.split(line)
+
+ mytype = parts[0]
+ mytarget = None
+
+ if mytype in ["dir","dev","fif"]:
+ mypath = string.join(parts[1:])
+ elif mytype == "obj":
+ mypath = string.join(parts[1:-2])
+ elif mytype == "sym":
+ sl = string.join(parts[1:-1])
+ sl = string.split(sl, " -> ")
+
+ mypath = sl[0]
+ mytarget = sl[1]
+ else:
+ print _("Unknown type:"),mytype
+
+ if mytype in ["dir"]:
+ mydirs.append(mypath)
+ else:
+ myfiles.append(mypath)
+
+ mydirs.sort()
+ myfiles.sort()
+ return myfiles,mydirs
+
+class PathLookupTable:
+ """Creates a temporary lookup table for paths from files."""
+ def __init__(self,dbname):
+ #if not self.validLocation(dbname):
+ # raise portage_exception.InvalidLocation, dbname
+ #self.base = copy.deepcopy(dbname)
+
+ self.files = []
+ self.pathtree = {}
+
+ def addFromFile(self, filename, handler):
+ if type(handler) != types.FunctionType:
+ raise portage_exception.IncorrectParameter, _("Handler of type '%(type)s' not 'function'") % {"type": type(handler)}
+
+ filelist,dirlist = handler(filename)
+ filestat = os.stat(filename)
+
+ if type(filelist) != types.ListType:
+ raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid file list") % {"handler": handler.__name__}
+ if type(dirlist) != types.ListType:
+ raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid directory list") % {"handler": handler.__name__}
+
+ for x in filelist:
+ if not x:
+ continue
+ x = os.path.normpath(x)
+ if len(x) > 1:
+ if x[:2] == "//":
+ x = x[1:]
+ if type(x) != types.StringType:
+ raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid subelement in dataset") % {"handler": handler.__name__}
+ xs = string.split(x, "/")
+ self.addFilePath(xs,filename)
+
+ for x in dirlist:
+ if not x:
+ continue
+ x = os.path.normpath(x)
+ if len(x) > 1:
+ if x[:2] == "//":
+ x = x[1:]
+ if type(x) != types.StringType:
+ raise portage_exception.InvalidDataType, _("%(handler)s returned an invalid subelement in dataset") % {"handler": handler.__name__}
+ xs = string.split(x, "/")
+ self.addDirectoryPath(xs,filename)
+
+ def addDirectoryPath(self,split_path, owner):
+ pt = self.pathtree
+ for x in split_path:
+ if x not in pt.keys():
+ pt[x] = {FILES_KEY:{},OWNER_KEY:[]}
+ if owner not in pt[x][OWNER_KEY]:
+ pt[x][OWNER_KEY].append(owner[:])
+ pt = pt[x]
+ return pt
+
+ def addFilePath(self,split_path, owner):
+ pt = self.addDirectoryPath(split_path[:-1], owner)
+ if split_path[-1] not in pt[FILES_KEY]:
+ pt[FILES_KEY][split_path[-1][:]] = []
+ if owner not in pt[FILES_KEY][split_path[-1][:]]:
+ pt[FILES_KEY][split_path[-1][:]].append(owner[:])
+
+ def whoProvides(self,path):
+ if type(path) != types.StringType:
+ raise portage_exception.InvalidData, _("Path passed is not a string: %(path)s") % {"path": path}
+ x = os.path.normpath(path)
+ if x[0:2] == '//':
+ x = x[1:]
+
+ xs = x.split("/")
+ pt = self.pathtree
+ final_dir = xs.pop(-1)
+ for subpath in xs:
+ if subpath in pt.keys():
+ pt = pt[subpath]
+
+ owners = []
+ if final_dir in pt[FILES_KEY]:
+ for x in pt[FILES_KEY][final_dir]:
+ if x not in owners:
+ owners.append(x[:])
+ if final_dir in pt:
+ for x in pt[final_dir][OWNER_KEY]:
+ if x not in owners:
+ owners.append(x[:])
+
+ return owners
+
+
+
+def test():
+ import os
+ plt = PathLookupTable("spork")
+ for x in os.listdir("/var/db/pkg"):
+ for y in os.listdir("/var/db/pkg/"+x):
+ c_path = "/var/db/pkg/"+x+"/"+y+"/CONTENTS"
+ if os.path.exists(c_path):
+ plt.addFromFile(c_path, ContentsHandler)
+ print "/bin/bash:", plt.whoProvides("/bin/bash")
+ print "/var/spool:", plt.whoProvides("/var/spool")
+ print "/etc/init.d", plt.whoProvides("/etc/init.d")
+ return plt
diff --git a/pym/portage_data.py b/pym/portage_data.py
new file mode 100644
index 00000000..6854655a
--- /dev/null
+++ b/pym/portage_data.py
@@ -0,0 +1,85 @@
+# portage_data.py -- Calculated/Discovered Data Values
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_data.py,v 1.5.2.2 2005/02/26 11:22:38 carpaski Exp $
+cvs_id_string="$Id: portage_data.py,v 1.5.2.2 2005/02/26 11:22:38 carpaski Exp $"[5:-2]
+
+import os,pwd,grp
+from portage_util import writemsg
+from output import green,red
+
+ostype=os.uname()[0]
+
+lchown = None
+if ostype=="Linux" or ostype.lower().endswith("gnu"):
+ userland="GNU"
+ os.environ["XARGS"]="xargs -r"
+elif ostype == "Darwin":
+ userland="Darwin"
+ os.environ["XARGS"]="xargs"
+ lchown=os.chown
+elif ostype in ["FreeBSD","OpenBSD"]:
+ userland="BSD"
+ os.environ["XARGS"]="xargs"
+else:
+ writemsg(red("Operating system")+" \""+ostype+"\" "+red("currently unsupported. Exiting.")+"\n")
+ sys.exit(1)
+
+if not lchown:
+ if "lchown" in dir(os):
+ # Included in python-2.3
+ lchown = os.lchown
+ else:
+ import missingos
+ lchown = missingos.lchown
+
+
+
+os.environ["USERLAND"]=userland
+
+#Secpass will be set to 1 if the user is root or in the portage group.
+secpass=0
+
+uid=os.getuid()
+wheelgid=0
+
+if uid==0:
+ secpass=2
+try:
+ wheelgid=grp.getgrnam("wheel")[2]
+ if (not secpass) and (wheelgid in os.getgroups()):
+ secpass=1
+except KeyError:
+ writemsg("portage initialization: your system doesn't have a 'wheel' group.\n")
+ writemsg("Please fix this as it is a normal system requirement. 'wheel' is GID 10\n")
+ writemsg("'emerge baselayout' and an 'etc-update' should remedy this problem.\n")
+ pass
+
+#Discover the uid and gid of the portage user/group
+try:
+ portage_uid=pwd.getpwnam("portage")[2]
+ portage_gid=grp.getgrnam("portage")[2]
+ if (secpass==0):
+ secpass=1
+except KeyError:
+ portage_uid=0
+ portage_gid=wheelgid
+ writemsg("\n")
+ writemsg( red("portage: 'portage' user or group missing. Please update baselayout\n"))
+ writemsg( red(" and merge portage user(250) and group(250) into your passwd\n"))
+ writemsg( red(" and group files. Non-root compilation is disabled until then.\n"))
+ writemsg( " Also note that non-root/wheel users will need to be added to\n")
+ writemsg( " the portage group to do portage commands.\n")
+ writemsg("\n")
+ writemsg( " For the defaults, line 1 goes into passwd, and 2 into group.\n")
+ writemsg(green(" portage:x:250:250:portage:/var/tmp/portage:/bin/false\n"))
+ writemsg(green(" portage::250:portage\n"))
+ writemsg("\n")
+
+if (uid!=0) and (portage_gid not in os.getgroups()):
+ writemsg("\n")
+ writemsg(red("*** You are not in the portage group. You may experience cache problems\n"))
+ writemsg(red("*** due to permissions preventing the creation of the on-disk cache.\n"))
+ writemsg(red("*** Please add this user to the portage group if you wish to use portage.\n"))
+ writemsg("\n")
+
diff --git a/pym/portage_db_anydbm.py b/pym/portage_db_anydbm.py
new file mode 100644
index 00000000..2b0b298c
--- /dev/null
+++ b/pym/portage_db_anydbm.py
@@ -0,0 +1,64 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/Attic/portage_db_anydbm.py,v 1.11.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_db_anydbm.py,v 1.11.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import anydbm,cPickle,types,os
+
+import portage_db_template
+
+class database(portage_db_template.database):
+ def module_init(self):
+ prevmask=os.umask(0)
+ if not os.path.exists(self.path):
+ current_path="/"
+ for mydir in self.path.split("/"):
+ current_path += "/"+mydir
+ if not os.path.exists(current_path):
+ os.mkdir(current_path)
+
+ self.filename = self.path + "/" + self.category + ".anydbm"
+
+ try:
+ # open it read/write
+ self.db = anydbm.open(self.filename, "c", 0664)
+ except SystemExit, e:
+ raise
+ except:
+ # Create a new db... DB type not supported anymore?
+ self.db = anydbm.open(self.filename, "n", 0664)
+
+ os.umask(prevmask)
+
+ def has_key(self,key):
+ self.check_key(key)
+ if self.db.has_key(key):
+ return 1
+ return 0
+
+ def keys(self):
+ return self.db.keys()
+
+ def get_values(self,key):
+ self.check_key(key)
+ if self.db.has_key(key):
+ myval = cPickle.loads(self.db[key])
+ return myval
+ return None
+
+ def set_values(self,key,val):
+ self.check_key(key)
+ self.db[key] = cPickle.dumps(val,cPickle.HIGHEST_PROTOCOL)
+
+ def del_key(self,key):
+ if self.has_key(key):
+ del self.db[key]
+ return True
+ return False
+
+ def sync(self):
+ self.db.sync()
+
+ def close(self):
+ self.db.close()
+
diff --git a/pym/portage_db_cpickle.py b/pym/portage_db_cpickle.py
new file mode 100644
index 00000000..beaf4b61
--- /dev/null
+++ b/pym/portage_db_cpickle.py
@@ -0,0 +1,79 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/Attic/portage_db_cpickle.py,v 1.9.2.2 2005/04/23 07:26:04 jstubbs Exp $
+cvs_id_string="$Id: portage_db_cpickle.py,v 1.9.2.2 2005/04/23 07:26:04 jstubbs Exp $"[5:-2]
+
+import anydbm,cPickle,types
+from os import chown,access,R_OK,unlink
+import os
+
+import portage_db_template
+
+class database(portage_db_template.database):
+ def module_init(self):
+ self.modified = False
+
+ prevmask=os.umask(0)
+ if not os.path.exists(self.path):
+ os.makedirs(self.path, 02775)
+
+ self.filename = self.path + "/" + self.category + ".cpickle"
+
+ if access(self.filename, R_OK):
+ try:
+ mypickle=cPickle.Unpickler(open(self.filename,"r"))
+ mypickle.find_global=None
+ self.db = mypickle.load()
+ except SystemExit, e:
+ raise
+ except:
+ self.db = {}
+ else:
+ self.db = {}
+
+ os.umask(prevmask)
+
+ def has_key(self,key):
+ self.check_key(key)
+ if self.db.has_key(key):
+ return 1
+ return 0
+
+ def keys(self):
+ return self.db.keys()
+
+ def get_values(self,key):
+ self.check_key(key)
+ if self.db.has_key(key):
+ return self.db[key]
+ return None
+
+ def set_values(self,key,val):
+ self.modified = True
+ self.check_key(key)
+ self.db[key] = val
+
+ def del_key(self,key):
+ if self.has_key(key):
+ del self.db[key]
+ self.modified = True
+ return True
+ return False
+
+ def sync(self):
+ if self.modified:
+ try:
+ if os.path.exists(self.filename):
+ unlink(self.filename)
+ cPickle.dump(self.db, open(self.filename,"w"), -1)
+ os.chown(self.filename,self.uid,self.gid)
+ os.chmod(self.filename, 0664)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+ def close(self):
+ self.sync()
+ self.db = None;
+
diff --git a/pym/portage_db_flat.py b/pym/portage_db_flat.py
new file mode 100644
index 00000000..b6cb4641
--- /dev/null
+++ b/pym/portage_db_flat.py
@@ -0,0 +1,113 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/Attic/portage_db_flat.py,v 1.13.2.6 2005/04/19 07:14:17 ferringb Exp $
+cvs_id_string="$Id: portage_db_flat.py,v 1.13.2.6 2005/04/19 07:14:17 ferringb Exp $"[5:-2]
+
+import types
+import os
+import stat
+
+import portage_db_template
+
+class database(portage_db_template.database):
+ def module_init(self):
+ self.lastkey = None # Cache
+ self.lastval = None # Cache
+
+ self.fullpath = self.path + "/" + self.category + "/"
+
+ if not os.path.exists(self.fullpath):
+ prevmask=os.umask(0)
+ os.makedirs(self.fullpath, 02775)
+ os.umask(prevmask)
+ try:
+ os.chown(self.fullpath, self.uid, self.gid)
+ os.chmod(self.fullpath, 02775)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+ def has_key(self,key):
+ if os.path.exists(self.fullpath+key):
+ return 1
+ return 0
+
+ def keys(self):
+ # XXX: NEED TOOLS SEPERATED
+ # return portage.listdir(self.fullpath,filesonly=1)
+ mykeys = []
+ for x in os.listdir(self.fullpath):
+ if os.path.isfile(self.fullpath+x) and not x.startswith(".update."):
+ mykeys += [x]
+ return mykeys
+
+ def get_values(self,key):
+ if not key:
+ raise KeyError, "key is not set to a valid value"
+
+ try:
+ # give buffering a hint of the pretty much maximal cache size we deal with
+ myf = open(self.fullpath+key, "r", 8192)
+ except OSError, oe:
+ # either the file didn't exist, or it was removed under our feet.
+ return None
+
+
+ # nuke the newlines right off the batt.
+ data = myf.read().splitlines()
+ mdict = {}
+
+ # rely on exceptions to note differing line counts.
+ try:
+ for x in range(0, len(self.dbkeys)):
+ mdict[self.dbkeys[x]] = data[x]
+
+ # do this now, rather then earlier- possible that earlier it might have been wasted
+ # if key count mismatched
+ mdict["_mtime_"] = os.fstat(myf.fileno()).st_mtime
+
+ except IndexError:
+ myf.close()
+ raise ValueError, "Key count mistmatch"
+
+ myf.close()
+ return mdict
+
+ def set_values(self,key,val):
+ if not key:
+ raise KeyError, "No key provided. key:%s val:%s" % (key,val)
+ if not val:
+ raise ValueError, "No value provided. key:%s val:%s" % (key,val)
+
+ # XXX threaded cache updates won't play nice with this.
+ # need a synchronization primitive, or locking (of the fileno, not a seperate file)
+ # to correctly handle threading.
+
+ update_fp = self.fullpath + ".update." + str(os.getpid()) + "." + key
+ myf = open(update_fp,"w")
+ myf.writelines( [ val[x] +"\n" for x in self.dbkeys] )
+ myf.close()
+
+ os.chown(update_fp, self.uid, self.gid)
+ os.chmod(update_fp, 0664)
+ os.utime(update_fp, (-1,long(val["_mtime_"])))
+ os.rename(update_fp, self.fullpath+key)
+
+ def del_key(self,key):
+ try:
+ os.unlink(self.fullpath+key)
+ except OSError, oe:
+ # just attempt it without checking, due to the fact that
+ # a cache update could be in progress.
+ self.lastkey = None
+ self.lastval = None
+ return 0
+ return 1
+
+ def sync(self):
+ return
+
+ def close(self):
+ return
+
diff --git a/pym/portage_db_template.py b/pym/portage_db_template.py
new file mode 100644
index 00000000..ec602245
--- /dev/null
+++ b/pym/portage_db_template.py
@@ -0,0 +1,174 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/Attic/portage_db_template.py,v 1.11.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_db_template.py,v 1.11.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import os.path,string
+from portage_util import getconfig, ReadOnlyConfig
+from portage_exception import CorruptionError
+
+class database:
+ def __init__(self,path,category,dbkeys,uid,gid,config_path="/etc/portage/module_configs/"):
+ self.__cacheArray = [None, None, None]
+ self.__cacheKeyArray = [None, None, None]
+ self.__template_init_called = True
+ self.path = path
+ self.category = category
+ self.dbkeys = dbkeys
+ self.uid = uid
+ self.gid = gid
+
+ self.config = None
+ self.__load_config(config_path)
+
+ self.module_init()
+
+ def getModuleName(self):
+ return self.__module__+"."+self.__class__.__name__[:]
+
+ def __load_config(self,config_path):
+ config_file = config_path + "/" + self.getModuleName()
+ self.config = ReadOnlyConfig(config_file)
+
+ def __check_init(self):
+ try:
+ if self.__template_init_called:
+ pass
+ except SystemExit, e:
+ raise
+ except:
+ raise NotImplementedError("db_template.__init__ was overridden")
+
+ def check_key(self,key):
+ if (not key) or not isinstance(key, str):
+ raise KeyError, "No key provided. key: %s" % (key)
+
+ def clear(self):
+ for x in self.keys():
+ self.del_key(x)
+
+ def __addCache(self,key,val):
+ del self.__cacheArray[2]
+ self.__cacheArray.insert(0,val)
+ del self.__cacheKeyArray[2]
+ self.__cacheKeyArray.insert(0,key)
+
+ def __delCache(self,key):
+ i = self.__cacheKeyArray.index(key)
+ self.__cacheArray[i] = None
+ self.__cacheKeyArray[i] = None
+
+ def flushCache(self):
+ self.__cacheArray = [None, None, None]
+ self.__cacheKeyArray = [None, None, None]
+
+ def __getitem__(self,key):
+ if key in self.__cacheKeyArray:
+ i = self.__cacheKeyArray.index(key)
+ return self.__cacheArray[i]
+
+ self.check_key(key)
+ if self.has_key(key):
+ try:
+ values = self.get_values(key)
+ self.__addCache(key,values)
+ return values
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ raise CorruptionError("Corruption detected when reading key '%s': %s" % (key,str(e)))
+ raise KeyError("Key not in db: '%s'" % (key))
+
+ def __setitem__(self,key,values):
+ self.check_key(key)
+ self.__addCache(key,values)
+ return self.set_values(key,values)
+
+ def __delitem__(self,key):
+ self.__delCache(key)
+ return self.del_key(key)
+
+ def has_key(self,key):
+ raise NotImplementedError("Method not defined")
+
+ def keys(self):
+ raise NotImplementedError("Method not defined")
+
+ def get_values(self,key):
+ raise NotImplementedError("Method not defined")
+
+ def set_values(self,key,val):
+ raise NotImplementedError("Method not defined")
+
+ def del_key(self,key):
+ raise NotImplementedError("Method not defined")
+
+ def sync(self):
+ raise NotImplementedError("Method not defined")
+
+ def close(self):
+ raise NotImplementedError("Method not defined")
+
+
+
+def test_database(db_class,path,category,dbkeys,uid,gid):
+ if "_mtime_" not in dbkeys:
+ dbkeys+=["_mtime_"]
+ d = db_class(path,category,dbkeys,uid,gid)
+
+ print "Module: "+str(d.__module__)
+
+ # XXX: Need a way to do this that actually works.
+ for x in dir(database):
+ if x not in dir(d):
+ print "FUNCTION MISSING:",str(x)
+
+ list = d.keys()
+ if(len(list) == 0):
+ values = {}
+ for x in dbkeys:
+ values[x] = x[:]
+ values["_mtime_"] = "1079903037"
+ d.set_values("test-2.2.3-r1", values)
+ d.set_values("test-2.2.3-r2", values)
+ d.set_values("test-2.2.3-r3", values)
+ d.set_values("test-2.2.3-r4", values)
+
+ list = d.keys()
+ print "Key count:",len(list)
+
+ values = d.get_values(list[0])
+ print "value count:",len(values)
+
+ mykey = "foobar-1.2.3-r4"
+
+ d.check_key(mykey)
+ d.set_values(mykey, values)
+ d.sync()
+ del d
+
+ d = db_class(path,category,dbkeys,uid,gid)
+ new_vals = d.get_values(mykey)
+
+ if dbkeys and new_vals:
+ for x in dbkeys:
+ if x not in new_vals.keys():
+ print "---",x
+ for x in new_vals.keys():
+ if x not in dbkeys:
+ print "+++",x
+ else:
+ print "Mismatched:",dbkeys,new_vals
+
+ d.del_key(mykey)
+
+ print "Should be None:",d.get_values(mykey)
+
+ d.clear()
+
+ d.sync
+ d.close
+
+ del d
+
+ print "Done."
diff --git a/pym/portage_db_test.py b/pym/portage_db_test.py
new file mode 100644
index 00000000..d1a7ce5e
--- /dev/null
+++ b/pym/portage_db_test.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python -O
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/Attic/portage_db_test.py,v 1.3.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_db_test.py,v 1.3.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import portage
+import portage_db_template
+import portage_db_anydbm
+import portage_db_flat
+import portage_db_cpickle
+
+import os
+
+uid = os.getuid()
+gid = os.getgid()
+
+portage_db_template.test_database(portage_db_flat.database,"/var/cache/edb/dep", "sys-apps",portage.auxdbkeys,uid,gid)
+portage_db_template.test_database(portage_db_cpickle.database,"/var/cache/edb/dep","sys-apps",portage.auxdbkeys,uid,gid)
+portage_db_template.test_database(portage_db_anydbm.database,"/var/cache/edb/dep", "sys-apps",portage.auxdbkeys,uid,gid)
+
diff --git a/pym/portage_dep.py b/pym/portage_dep.py
new file mode 100644
index 00000000..3e7f2e8c
--- /dev/null
+++ b/pym/portage_dep.py
@@ -0,0 +1,155 @@
+# deps.py -- Portage dependency resolution functions
+# Copyright 2003-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_dep.py,v 1.15.2.3 2005/04/02 14:07:59 jstubbs Exp $
+cvs_id_string="$Id: portage_dep.py,v 1.15.2.3 2005/04/02 14:07:59 jstubbs Exp $"[5:-2]
+
+# DEPEND SYNTAX:
+#
+# 'use?' only affects the immediately following word!
+# Nesting is the only legal way to form multiple '[!]use?' requirements.
+#
+# Where: 'a' and 'b' are use flags, and 'z' is a depend atom.
+#
+# "a? z" -- If 'a' in [use], then b is valid.
+# "a? ( z )" -- Syntax with parenthesis.
+# "a? b? z" -- Deprecated.
+# "a? ( b? z )" -- Valid
+# "a? ( b? ( z ) ) -- Valid
+#
+
+import os,string,types,sys,copy
+import portage_exception
+
+def strip_empty(myarr):
+ for x in range(len(myarr)-1, -1, -1):
+ if not myarr[x]:
+ del myarr[x]
+ return myarr
+
+def paren_reduce(mystr,tokenize=1):
+ "Accepts a list of strings, and converts '(' and ')' surrounded items to sub-lists"
+ mylist = []
+ while mystr:
+ if ("(" not in mystr) and (")" not in mystr):
+ freesec = mystr
+ subsec = None
+ tail = ""
+ elif mystr[0] == ")":
+ return [mylist,mystr[1:]]
+ elif ("(" in mystr) and (mystr.index("(") < mystr.index(")")):
+ freesec,subsec = mystr.split("(",1)
+ subsec,tail = paren_reduce(subsec,tokenize)
+ else:
+ subsec,tail = mystr.split(")",1)
+ if tokenize:
+ subsec = strip_empty(subsec.split(" "))
+ return [mylist+subsec,tail]
+ return mylist+[subsec],tail
+ mystr = tail
+ if freesec:
+ if tokenize:
+ mylist = mylist + strip_empty(freesec.split(" "))
+ else:
+ mylist = mylist + [freesec]
+ if subsec is not None:
+ mylist = mylist + [subsec]
+ return mylist
+
+def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]):
+ """Takes a paren_reduce'd array and reduces the use? conditionals out
+ leaving an array with subarrays
+ """
+ # Quick validity checks
+ for x in range(1,len(deparray)):
+ if deparray[x] in ["||","&&"]:
+ if len(deparray) == x:
+ # Operator is the last element
+ raise portage_exception.InvalidDependString("INVALID "+deparray[x]+" DEPEND STRING: "+str(deparray))
+ if type(deparray[x+1]) != types.ListType:
+ # Operator is not followed by a list
+ raise portage_exception.InvalidDependString("INVALID "+deparray[x]+" DEPEND STRING: "+str(deparray))
+ if deparray and deparray[-1] and deparray[-1][-1] == "?":
+ # Conditional with no target
+ raise portage_exception.InvalidDependString("INVALID "+deparray[x]+" DEPEND STRING: "+str(deparray))
+
+ #XXX: Compatibility -- Still required?
+ if ("*" in uselist):
+ matchall=1
+
+ mydeparray = deparray[:]
+ rlist = []
+ while mydeparray:
+ head = mydeparray.pop(0)
+
+ if type(head) == types.ListType:
+ rlist = rlist + [use_reduce(head, uselist, masklist, matchall, excludeall)]
+
+ else:
+ if head[-1] == "?": # Use reduce next group on fail.
+ # Pull any other use conditions and the following atom or list into a separate array
+ newdeparray = [head]
+ while isinstance(newdeparray[-1], str) and newdeparray[-1][-1] == "?":
+ if mydeparray:
+ newdeparray.append(mydeparray.pop(0))
+ else:
+ raise ValueError, "Conditional with no target."
+
+ # Deprecation checks
+ warned = 0
+ if len(newdeparray[-1]) == 0:
+ sys.stderr.write("Note: Empty target in string. (Deprecated)\n")
+ warned = 1
+ if len(newdeparray) != 2:
+ sys.stderr.write("Note: Nested use flags without parenthesis (Deprecated)\n")
+ warned = 1
+ if warned:
+ sys.stderr.write(" --> "+string.join(map(str,[head]+newdeparray))+"\n")
+
+ # Check that each flag matches
+ ismatch = True
+ for head in newdeparray[:-1]:
+ head = head[:-1]
+ if head[0] == "!":
+ head = head[1:]
+ if not matchall and head in uselist or head in excludeall:
+ ismatch = False
+ break
+ elif head not in masklist:
+ if not matchall and head not in uselist:
+ ismatch = False
+ break
+ else:
+ ismatch = False
+
+ # If they all match, process the target
+ if ismatch:
+ target = newdeparray[-1]
+ if isinstance(target, list):
+ rlist += [use_reduce(target, uselist, masklist, matchall, excludeall)]
+ else:
+ rlist += [target]
+
+ else:
+ rlist += [head]
+
+ return rlist
+
+
+def dep_opconvert(deplist):
+ """Move || and && to the beginning of the following arrays"""
+ # Hack in management of the weird || for dep_wordreduce, etc.
+ # dep_opconvert: [stuff, ["||", list, of, things]]
+ # At this point: [stuff, "||", [list, of, things]]
+ retlist = []
+ x = 0
+ while x != len(deplist):
+ if isinstance(deplist[x], list):
+ retlist.append(dep_opconvert(deplist[x]))
+ elif deplist[x] == "||" or deplist[x] == "&&":
+ retlist.append([deplist[x]] + dep_opconvert(deplist[x+1]))
+ x += 1
+ else:
+ retlist.append(deplist[x])
+ x += 1
+ return retlist
diff --git a/pym/portage_exception.py b/pym/portage_exception.py
new file mode 100644
index 00000000..b37f7caa
--- /dev/null
+++ b/pym/portage_exception.py
@@ -0,0 +1,163 @@
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_exception.py,v 1.8.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_exception.py,v 1.8.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+class PortageException(Exception):
+ """General superclass for portage exceptions"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class CorruptionError(PortageException):
+ """Corruption indication"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class InvalidDependString(PortageException):
+ """An invalid depend string has been encountered"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class InvalidVersionString(PortageException):
+ """An invalid version string has been encountered"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class SecurityViolation(PortageException):
+ """An incorrect formatting was passed instead of the expected one"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class IncorrectParameter(PortageException):
+ """An parameter of the wrong type was passed"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class MissingParameter(PortageException):
+ """An parameter is required for the action requested but was not passed"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+
+class InvalidData(PortageException):
+ """An incorrect formatting was passed instead of the expected one"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class InvalidDataType(PortageException):
+ """An incorrect type was passed instead of the expected one"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+
+
+
+class InvalidLocation(PortageException):
+ """Data was not found when it was expected to exist or was specified incorrectly"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class FileNotFound(InvalidLocation):
+ """A file was not found when it was expected to exist"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class DirectoryNotFound(InvalidLocation):
+ """A directory was not found when it was expected to exist"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+
+
+class CommandNotFound(PortageException):
+ """A required binary was not available or executable"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+
+
+class PortagePackageException(PortageException):
+ """Malformed or missing package data"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class PackageNotFound(PortagePackageException):
+ """Missing Ebuild or Binary"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class InvalidPackageName(PortagePackageException):
+ """Malformed package name"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+
+
+
+class SignatureException(PortageException):
+ """Signature was not present in the checked file"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class DigestException(SignatureException):
+ """A problem exists in the digest"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class MissingSignature(SignatureException):
+ """Signature was not present in the checked file"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class InvalidSignature(SignatureException):
+ """Signature was checked and was not a valid, current, nor trusted signature"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
+class UntrustedSignature(SignatureException):
+ """Signature was not certified to the desired security level"""
+ def __init__(self,value):
+ self.value = value[:]
+ def __str__(self):
+ return repr(self.value)
+
diff --git a/pym/portage_exec.py b/pym/portage_exec.py
new file mode 100644
index 00000000..c613ab23
--- /dev/null
+++ b/pym/portage_exec.py
@@ -0,0 +1,215 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_exec.py,v 1.13.2.4 2005/04/17 09:01:56 jstubbs Exp $
+cvs_id_string="$Id: portage_exec.py,v 1.13.2.4 2005/04/17 09:01:56 jstubbs Exp $"[5:-2]
+
+import os,types,atexit,string,stat
+import signal
+import portage_data
+import portage_util
+
+try:
+ import resource
+ max_fd_limit=resource.getrlimit(RLIMIT_NOFILE)
+except SystemExit, e:
+ raise
+except:
+ # hokay, no resource module.
+ max_fd_limit=256
+
+spawned_pids = []
+def cleanup():
+ global spawned_pids
+ while spawned_pids:
+ pid = spawned_pids.pop()
+ try:
+ os.kill(pid,SIGKILL)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+atexit.register(cleanup)
+
+from portage_const import BASH_BINARY,SANDBOX_BINARY,SANDBOX_PIDS_FILE
+
+sandbox_capable = (os.path.exists(SANDBOX_BINARY) and os.access(SANDBOX_BINARY, os.X_OK))
+
+def spawn_bash(mycommand,env={},debug=False,opt_name=None,**keywords):
+ args=[BASH_BINARY]
+ if not opt_name:
+ opt_name=mycommand.split()[0]
+ if not env.has_key("BASH_ENV"):
+ env["BASH_ENV"] = "/etc/spork/is/not/valid/profile.env"
+ if debug:
+ args.append("-x")
+ args.append("-c")
+ args.append(mycommand)
+ return spawn(args,env=env,opt_name=opt_name,**keywords)
+
+def spawn_sandbox(mycommand,uid=None,opt_name=None,**keywords):
+ if not sandbox_capable:
+ return spawn_bash(mycommand,opt_name=opt_name,**keywords)
+ args=[SANDBOX_BINARY]
+ if not opt_name:
+ opt_name=mycommand.split()[0]
+ args.append(mycommand)
+ if not uid:
+ uid=os.getuid()
+ try:
+ os.chown(SANDBOX_PIDS_FILE,uid,portage_data.portage_gid)
+ os.chmod(SANDBOX_PIDS_FILE,0664)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ return spawn(args,uid=uid,opt_name=opt_name,**keywords)
+
+# base spawn function
+def spawn(mycommand,env={},opt_name=None,fd_pipes=None,returnpid=False,uid=None,gid=None,groups=None,umask=None,logfile=None,path_lookup=True):
+ if type(mycommand)==types.StringType:
+ mycommand=mycommand.split()
+ myc = mycommand[0]
+ if not os.access(myc, os.X_OK):
+ if not path_lookup:
+ return None
+ myc = find_binary(myc)
+ if myc == None:
+ return None
+
+ mypid=[]
+ if logfile:
+ pr,pw=os.pipe()
+ mypid.extend(spawn(('tee','-i','-a',logfile),returnpid=True,fd_pipes={0:pr,1:1,2:2}))
+ retval=os.waitpid(mypid[-1],os.WNOHANG)[1]
+ if retval != 0:
+ # he's dead jim.
+ if (retval & 0xff)==0:
+ return (retval >> 8) # exit code
+ else:
+ return ((retval & 0xff) << 8) # signal
+ if not fd_pipes:
+ fd_pipes={}
+ fd_pipes[0] = 0
+ fd_pipes[1]=pw
+ fd_pipes[2]=pw
+
+ if not opt_name:
+ opt_name = mycommand[0]
+ myargs=[opt_name]
+ myargs.extend(mycommand[1:])
+ mypid.append(os.fork())
+ if mypid[-1] == 0:
+ # this may look ugly, but basically it moves file descriptors around to ensure no
+ # handles that are needed are accidentally closed during the final dup2 calls.
+ trg_fd=[]
+ if type(fd_pipes)==types.DictType:
+ src_fd=[]
+ k=fd_pipes.keys()
+ k.sort()
+ for x in k:
+ trg_fd.append(x)
+ src_fd.append(fd_pipes[x])
+ for x in range(0,len(trg_fd)):
+ if trg_fd[x] == src_fd[x]:
+ continue
+ if trg_fd[x] in src_fd[x+1:]:
+ new=os.dup2(trg_fd[x],max(src_fd) + 1)
+ os.close(trg_fd[x])
+ try:
+ while True:
+ src_fd[s.index(trg_fd[x])]=new
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ for x in range(0,len(trg_fd)):
+ if trg_fd[x] != src_fd[x]:
+ os.dup2(src_fd[x], trg_fd[x])
+ else:
+ trg_fd=[0,1,2]
+ for x in range(0,max_fd_limit):
+ if x not in trg_fd:
+ try:
+ os.close(x)
+ except SystemExit, e:
+ raise
+ except:
+ pass
+ # note this order must be preserved- can't change gid/groups if you change uid first.
+ if gid:
+ os.setgid(gid)
+ if groups:
+ os.setgroups(groups)
+ if uid:
+ os.setuid(uid)
+ if umask:
+ os.umask(umask)
+ try:
+ # XXX: We would do this to stop ebuild.sh from getting any
+ # XXX: output, and consequently, we'd get to handle the sigINT.
+ #os.close(sys.stdin.fileno())
+ pass
+ except SystemExit, e:
+ raise
+ except:
+ pass
+
+ try:
+ #print "execing", myc, myargs
+ os.execve(myc,myargs,env)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ raise str(e)+":\n "+myc+" "+string.join(myargs)
+ # If the execve fails, we need to report it, and exit
+ # *carefully* --- report error here
+ os._exit(1)
+ sys.exit(1)
+ return # should never get reached
+
+ if logfile:
+ os.close(pr)
+ os.close(pw)
+
+ if returnpid:
+ global spawned_pids
+ spawned_pids.append(mypid[-1])
+ return mypid
+ while len(mypid):
+ retval=os.waitpid(mypid[-1],0)[1]
+ if retval != 0:
+ for x in mypid[0:-1]:
+ try:
+ os.kill(x,signal.SIGTERM)
+ if os.waitpid(x,os.WNOHANG)[1] == 0:
+ # feisty bugger, still alive.
+ os.kill(x,signal.SIGKILL)
+ os.waitpid(x,0)
+ except OSError, oe:
+ if oe.errno not in (10,3):
+ raise oe
+
+ # at this point we've killed all other kid pids generated via this call.
+ # return now.
+
+ if (retval & 0xff)==0:
+ return (retval >> 8) # return exit code
+ else:
+ return ((retval & 0xff) << 8) # interrupted by signal
+ else:
+ mypid.pop(-1)
+ return 0
+
+def find_binary(myc):
+ p=os.getenv("PATH")
+ if p == None:
+ return None
+ for x in p.split(":"):
+ # if it exists, and is executable
+ if os.access("%s/%s" % (x,myc), os.X_OK):
+ return "%s/%s" % (x,myc)
+
+ return None
+
+
diff --git a/pym/portage_file.py b/pym/portage_file.py
new file mode 100644
index 00000000..5cee6458
--- /dev/null
+++ b/pym/portage_file.py
@@ -0,0 +1,62 @@
+# portage_data.py -- Calculated/Discovered Data Values
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_file.py,v 1.3.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_file.py,v 1.3.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import os
+import portage_data
+import portage_exception
+from portage_localization import _
+
+def normpath(mypath):
+ newpath = os.path.normpath(mypath)
+ if len(newpath) > 1:
+ if newpath[:2] == "//":
+ newpath = newpath[1:]
+ return newpath
+
+
+def makedirs(path, perms=0755, uid=None, gid=None, must_chown=False):
+ old_umask = os.umask(0)
+ if(uid == None):
+ uid = portage_data.portage_uid
+ if(gid == None):
+ gid = portage_data.portage_gid
+ if not path:
+ raise portage_exception.InvalidParameter, _("Invalid path: type: '%(type)s' value: '%(path)s'") % {"path": path, "type": type(path)}
+ if(perm > 1535) or (perm == 0):
+ raise portage_exception.InvalidParameter, _("Invalid permissions passed. Value is octal and no higher than 02777.")
+
+ mypath = normpath(path)
+ dirs = string.split(path, "/")
+
+ mypath = ""
+ if dirs and dirs[0] == "":
+ mypath = "/"
+ dirs = dirs[1:]
+ for x in dirs:
+ mypath += x+"/"
+ if not os.path.exists(mypath):
+ os.mkdir(mypath, perm)
+ try:
+ os.chown(mypath, uid, gid)
+ except SystemExit, e:
+ raise
+ except:
+ if must_chown:
+ os.umask(old_umask)
+ raise
+ portage_util.writemsg(_("Failed to chown: %(path)s to %(uid)s:%(gid)s\n") % {"path":mypath,"uid":uid,"gid":gid})
+
+ os.umask(old_umask)
+
+
+
+
+
+
+
+
+
+
diff --git a/pym/portage_gpg.py b/pym/portage_gpg.py
new file mode 100644
index 00000000..deaf36ad
--- /dev/null
+++ b/pym/portage_gpg.py
@@ -0,0 +1,149 @@
+# portage_gpg.py -- core Portage functionality
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_gpg.py,v 1.6.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_gpg.py,v 1.6.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import os
+import copy
+import types
+import commands
+import portage_exception
+import portage_checksum
+
+GPG_BINARY = "/usr/bin/gpg"
+GPG_OPTIONS = " --lock-never --no-random-seed-file --no-greeting --no-sig-cache "
+GPG_VERIFY_FLAGS = " --verify "
+GPG_KEYDIR = " --homedir '%s' "
+GPG_KEYRING = " --keyring '%s' "
+
+UNTRUSTED = 0
+EXISTS = UNTRUSTED + 1
+MARGINAL = EXISTS + 1
+TRUSTED = MARGINAL + 1
+
+def fileStats(filepath):
+ mya = []
+ for x in os.stat(filepath):
+ mya.append(x)
+ mya.append(portage_checksum.perform_checksum(filepath))
+ return mya
+
+
+class FileChecker:
+ def __init__(self,keydir=None,keyring=None,requireSignedRing=False,minimumTrust=EXISTS):
+ self.minimumTrust = TRUSTED # Default we require trust. For rings.
+ self.keydir = None
+ self.keyring = None
+ self.keyringPath = None
+ self.keyringStats = None
+ self.keyringIsTrusted = False
+
+ if (keydir != None):
+ # Verify that the keydir is valid.
+ if type(keydir) != types.StringType:
+ raise portage_exception.InvalidDataType, "keydir argument: %s" % keydir
+ if not os.path.isdir(keydir):
+ raise portage_exception.DirectoryNotFound, "keydir: %s" % keydir
+ self.keydir = copy.deepcopy(keydir)
+
+ if (keyring != None):
+ # Verify that the keyring is a valid filename and exists.
+ if type(keyring) != types.StringType:
+ raise portage_exception.InvalidDataType, "keyring argument: %s" % keyring
+ if keyring.find("/") != -1:
+ raise portage_exception.InvalidData, "keyring: %s" % keyring
+ pathname = ""
+ if keydir:
+ pathname = keydir + "/" + keyring
+ if not os.path.isfile(pathname):
+ raise portage_exception.FileNotFound, "keyring missing: %s (dev.gentoo.org/~carpaski/gpg/)" % pathname
+
+ keyringPath = keydir+"/"+keyring
+
+ if not keyring or not keyringPath and requireSignedRing:
+ raise portage_exception.MissingParameter
+
+ self.keyringStats = fileStats(keyringPath)
+ self.minimumTrust = TRUSTED
+ if not self.verify(keyringPath, keyringPath+".asc"):
+ self.keyringIsTrusted = False
+ if requireSignedRing:
+ raise portage_exception.InvalidSignature, "Required keyring verification: "+keyringPath
+ else:
+ self.keyringIsTrusted = True
+
+ self.keyring = copy.deepcopy(keyring)
+ self.keyringPath = self.keydir+"/"+self.keyring
+ self.minimumTrust = minimumTrust
+
+ def _verifyKeyring(self):
+ if self.keyringStats and self.keyringPath:
+ new_stats = fileStats(self.keyringPath)
+ if new_stats != self.keyringStats:
+ raise portage_exception.SecurityViolation, "GPG keyring changed!"
+
+ def verify(self, filename, sigfile=None):
+ """Uses minimumTrust to determine if it is Valid/True or Invalid/False"""
+ self._verifyKeyring()
+
+ if not os.path.isfile(filename):
+ raise portage_exception.FileNotFound, filename
+
+ if sigfile and not os.path.isfile(sigfile):
+ raise portage_exception.FileNotFound, sigfile
+
+ if self.keydir and not os.path.isdir(self.keydir):
+ raise portage_exception.DirectoryNotFound, filename
+
+ if self.keyringPath:
+ if not os.path.isfile(self.keyringPath):
+ raise portage_exception.FileNotFound, self.keyringPath
+
+ if not os.path.isfile(filename):
+ raise portage_exception.CommandNotFound, filename
+
+ command = GPG_BINARY + GPG_VERIFY_FLAGS + GPG_OPTIONS
+ if self.keydir:
+ command += GPG_KEYDIR % (self.keydir)
+ if self.keyring:
+ command += GPG_KEYRING % (self.keyring)
+
+ if sigfile:
+ command += " '"+sigfile+"'"
+ command += " '"+filename+"'"
+
+ result,output = commands.getstatusoutput(command)
+
+ signal = result & 0xff
+ result = (result >> 8)
+
+ if signal:
+ raise SignalCaught, "Signal: %d" % (signal)
+
+ trustLevel = UNTRUSTED
+ if result == 0:
+ trustLevel = TRUSTED
+ #if output.find("WARNING") != -1:
+ # trustLevel = MARGINAL
+ if output.find("BAD") != -1:
+ raise portage_exception.InvalidSignature, filename
+ elif result == 1:
+ trustLevel = EXISTS
+ if output.find("BAD") != -1:
+ raise portage_exception.InvalidSignature, filename
+ elif result == 2:
+ trustLevel = UNTRUSTED
+ if output.find("could not be verified") != -1:
+ raise portage_exception.MissingSignature, filename
+ if output.find("public key not found") != -1:
+ if self.keyringIsTrusted: # We trust the ring, but not the key specifically.
+ trustLevel = MARGINAL
+ else:
+ raise portage_exception.InvalidSignature, filename+" (Unknown Signature)"
+ else:
+ raise portage_exception.UnknownCondition, "GPG returned unknown result: %d" % (result)
+
+ if trustLevel >= self.minimumTrust:
+ return True
+ return False
diff --git a/pym/portage_localization.py b/pym/portage_localization.py
new file mode 100644
index 00000000..8aafc510
--- /dev/null
+++ b/pym/portage_localization.py
@@ -0,0 +1,21 @@
+# portage_localization.py -- Code to manage/help portage localization.
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_localization.py,v 1.2.2.1 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_localization.py,v 1.2.2.1 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+# We define this to make the transition easier for us.
+def _(mystr):
+ return mystr
+
+
+def localization_example():
+ # Dict references allow translators to rearrange word order.
+ print _("You can use this string for translating.")
+ print _("Strings can be formatted with %(mystr)s like this.") % {"mystr": "VALUES"}
+
+ a_value = "value.of.a"
+ b_value = 123
+ c_value = [1,2,3,4]
+ print _("A: %(a)s -- B: %(b)s -- C: %(c)s") % {"a":a_value,"b":b_value,"c":c_value}
+
diff --git a/pym/portage_locks.py b/pym/portage_locks.py
new file mode 100644
index 00000000..cf248e4b
--- /dev/null
+++ b/pym/portage_locks.py
@@ -0,0 +1,360 @@
+# portage: Lock management code
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_locks.py,v 1.18.2.2 2005/01/16 02:35:33 carpaski Exp $
+cvs_id_string="$Id: portage_locks.py,v 1.18.2.2 2005/01/16 02:35:33 carpaski Exp $"[5:-2]
+
+import atexit
+import errno
+import os
+import stat
+import string
+import time
+import types
+import portage_exception
+import portage_file
+import portage_util
+import portage_data
+from portage_localization import _
+
+HARDLINK_FD = -2
+
+hardlock_path_list = []
+def clean_my_hardlocks():
+ for x in hardlock_path_list:
+ hardlock_cleanup(x)
+def add_hardlock_file_to_cleanup(path):
+ mypath = portage_file.normpath(path)
+ if os.path.isfile(mypath):
+ mypath = os.path.dirname(mypath)
+ if os.path.isdir(mypath):
+ hardlock_path_list = mypath[:]
+
+atexit.register(clean_my_hardlocks)
+
+def lockdir(mydir):
+ return lockfile(mydir,wantnewlockfile=1)
+def unlockdir(mylock):
+ return unlockfile(mylock)
+
+def lockfile(mypath,wantnewlockfile=0,unlinkfile=0):
+ """Creates all dirs upto, the given dir. Creates a lockfile
+ for the given directory as the file: directoryname+'.portage_lockfile'."""
+ import fcntl
+
+ if not mypath:
+ raise portage_exception.InvalidData, "Empty path given"
+
+ if type(mypath) == types.StringType and mypath[-1] == '/':
+ mypath = mypath[:-1]
+
+ if type(mypath) == types.FileType:
+ mypath = mypath.fileno()
+ if type(mypath) == types.IntType:
+ lockfilename = mypath
+ wantnewlockfile = 0
+ unlinkfile = 0
+ elif wantnewlockfile:
+ lockfilename = mypath+".portage_lockfile"
+ unlinkfile = 1
+ else:
+ lockfilename = mypath
+
+ if type(mypath) == types.StringType:
+ if not os.path.exists(os.path.dirname(mypath)):
+ raise portage_exception.DirectoryNotFound, os.path.dirname(mypath)
+ if not os.path.exists(lockfilename):
+ old_mask=os.umask(000)
+ myfd = os.open(lockfilename, os.O_CREAT|os.O_RDWR,0660)
+ try:
+ if os.stat(lockfilename).st_gid != portage_data.portage_gid:
+ os.chown(lockfilename,os.getuid(),portage_data.portage_gid)
+ except SystemExit, e:
+ raise
+ except OSError, e:
+ if e[0] == 2: # No such file or directory
+ return lockfile(mypath,wantnewlockfile,unlinkfile)
+ else:
+ portage_util.writemsg("Cannot chown a lockfile. This could cause inconvenience later.\n");
+ os.umask(old_mask)
+ else:
+ myfd = os.open(lockfilename, os.O_CREAT|os.O_RDWR,0660)
+
+ elif type(mypath) == types.IntType:
+ myfd = mypath
+
+ else:
+ raise ValueError, "Unknown type passed in '%s': '%s'" % (type(mypath),mypath)
+
+ # try for a non-blocking lock, if it's held, throw a message
+ # we're waiting on lockfile and use a blocking attempt.
+ locking_method = fcntl.lockf
+ try:
+ fcntl.lockf(myfd,fcntl.LOCK_EX|fcntl.LOCK_NB)
+ except IOError, e:
+ if "errno" not in dir(e):
+ raise
+ if e.errno == errno.EAGAIN:
+ # resource temp unavailable; eg, someone beat us to the lock.
+ if type(mypath) == types.IntType:
+ print "waiting for lock on fd %i" % myfd
+ else:
+ print "waiting for lock on %s" % lockfilename
+ # try for the exclusive lock now.
+ fcntl.lockf(myfd,fcntl.LOCK_EX)
+ elif e.errno == errno.ENOLCK:
+ # We're not allowed to lock on this FS.
+ os.close(myfd)
+ link_success = False
+ if lockfilename == str(lockfilename):
+ if wantnewlockfile:
+ try:
+ if os.stat(lockfilename)[stat.ST_NLINK] == 1:
+ os.unlink(lockfilename)
+ except Exception, e:
+ pass
+ link_success = hardlink_lockfile(lockfilename)
+ if not link_success:
+ raise
+ locking_method = None
+ myfd = HARDLINK_FD
+ else:
+ raise
+
+
+ if type(lockfilename) == types.StringType and not os.path.exists(lockfilename):
+ # The file was deleted on us... Keep trying to make one...
+ os.close(myfd)
+ portage_util.writemsg("lockfile recurse\n",1)
+ lockfilename,myfd,unlinkfile,locking_method = lockfile(mypath,wantnewlockfile,unlinkfile)
+
+ portage_util.writemsg(str((lockfilename,myfd,unlinkfile))+"\n",1)
+ return (lockfilename,myfd,unlinkfile,locking_method)
+
+def unlockfile(mytuple):
+ import fcntl
+
+ #XXX: Compatability hack.
+ if len(mytuple) == 3:
+ lockfilename,myfd,unlinkfile = mytuple
+ locking_method = fcntl.flock
+ elif len(mytuple) == 4:
+ lockfilename,myfd,unlinkfile,locking_method = mytuple
+ else:
+ raise
+
+ if(myfd == HARDLINK_FD):
+ unhardlink_lockfile(lockfilename)
+ return True
+
+ if type(lockfilename) == types.StringType and not os.path.exists(lockfilename):
+ portage_util.writemsg("lockfile does not exist '%s'\n" % lockfilename,1)
+ if (myfd != None) and type(lockfilename) == types.StringType:
+ os.close(myfd)
+ return False
+
+ try:
+ if myfd == None:
+ myfd = os.open(lockfilename, os.O_WRONLY,0660)
+ unlinkfile = 1
+ locking_method(myfd,fcntl.LOCK_UN)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ if type(lockfilename) == types.StringType:
+ os.close(myfd)
+ raise IOError, "Failed to unlock file '%s'\n" % lockfilename
+
+ try:
+ # This sleep call was added to allow other processes that are
+ # waiting for a lock to be able to grab it before it is deleted.
+ # lockfile() already accounts for this situation, however, and
+ # the sleep here adds more time than is saved overall, so am
+ # commenting until it is proved necessary.
+ #time.sleep(0.0001)
+ if unlinkfile:
+ locking_method(myfd,fcntl.LOCK_EX|fcntl.LOCK_NB)
+ # We won the lock, so there isn't competition for it.
+ # We can safely delete the file.
+ portage_util.writemsg("Got the lockfile...\n",1)
+ #portage_util.writemsg("Unlinking...\n")
+ os.unlink(lockfilename)
+ portage_util.writemsg("Unlinked lockfile...\n",1)
+ locking_method(myfd,fcntl.LOCK_UN)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ # We really don't care... Someone else has the lock.
+ # So it is their problem now.
+ portage_util.writemsg("Failed to get lock... someone took it.\n",1)
+ portage_util.writemsg(str(e)+"\n",1)
+
+ # why test lockfilename? because we may have been handed an
+ # fd originally, and the caller might not like having their
+ # open fd closed automatically on them.
+ if type(lockfilename) == types.StringType:
+ os.close(myfd)
+
+ return True
+
+
+
+
+def hardlock_name(path):
+ return path+".hardlock-"+os.uname()[1]+"-"+str(os.getpid())
+
+def hardlink_active(lock):
+ if not os.path.exists(lock):
+ return False
+ # XXXXXXXXXXXXXXXXXXXXXXXXXX
+
+def hardlink_is_mine(link,lock):
+ try:
+ myhls = os.stat(link)
+ mylfs = os.stat(lock)
+ except SystemExit, e:
+ raise
+ except:
+ myhls = None
+ mylfs = None
+
+ if myhls:
+ if myhls[stat.ST_NLINK] == 2:
+ return True
+ if mylfs:
+ if mylfs[stat.ST_INO] == myhls[stat.ST_INO]:
+ return True
+ return False
+
+def hardlink_lockfile(lockfilename, max_wait=14400):
+ """Does the NFS, hardlink shuffle to ensure locking on the disk.
+ We create a PRIVATE lockfile, that is just a placeholder on the disk.
+ Then we HARDLINK the real lockfile to that private file.
+ If our file can 2 references, then we have the lock. :)
+ Otherwise we lather, rise, and repeat.
+ We default to a 4 hour timeout.
+ """
+
+ add_hardlock_file_to_cleanup(lockfilename)
+
+ start_time = time.time()
+ myhardlock = hardlock_name(lockfilename)
+ reported_waiting = False
+
+ while(time.time() < (start_time + max_wait)):
+ # We only need it to exist.
+ myfd = os.open(myhardlock, os.O_CREAT|os.O_RDWR,0660)
+ os.close(myfd)
+
+ if not os.path.exists(myhardlock):
+ raise portage_exception.FileNotFound, _("Created lockfile is missing: %(filename)s") % {"filename":myhardlock}
+
+ try:
+ res = os.link(myhardlock, lockfilename)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ #print "lockfile(): Hardlink: Link failed."
+ #print "Exception: ",e
+ pass
+
+ if hardlink_is_mine(myhardlock, lockfilename):
+ # We have the lock.
+ if reported_waiting:
+ print
+ return True
+
+ if reported_waiting:
+ portage_util.writemsg(".")
+ else:
+ reported_waiting = True
+ print
+ print "Waiting on (hardlink) lockfile: (one '.' per 3 seconds)"
+ print "This is a feature to prevent distfiles corruption."
+ print "/usr/lib/portage/bin/clean_locks can fix stuck locks."
+ print "Lockfile: " + lockfilename
+ time.sleep(3)
+
+ os.unlink(myhardlock)
+ return False
+
+def unhardlink_lockfile(lockfilename):
+ myhardlock = hardlock_name(lockfilename)
+ try:
+ if os.path.exists(myhardlock):
+ os.unlink(myhardlock)
+ if os.path.exists(lockfilename):
+ os.unlink(lockfilename)
+ except SystemExit, e:
+ raise
+ except:
+ portage_util.writemsg("Something strange happened to our hardlink locks.\n")
+
+def hardlock_cleanup(path, remove_all_locks=False):
+ mypid = str(os.getpid())
+ myhost = os.uname()[1]
+ mydl = os.listdir(path)
+
+ results = []
+ mycount = 0
+
+ mylist = {}
+ for x in mydl:
+ if os.path.isfile(path+"/"+x):
+ parts = string.split(x, ".hardlock-")
+ if len(parts) == 2:
+ filename = parts[0]
+ hostpid = string.split(parts[1],"-")
+ host = string.join(hostpid[:-1], "-")
+ pid = hostpid[-1]
+
+ if not mylist.has_key(filename):
+ mylist[filename] = {}
+ if not mylist[filename].has_key(host):
+ mylist[filename][host] = []
+ mylist[filename][host].append(pid)
+
+ mycount += 1
+
+
+ results.append("Found %(count)s locks" % {"count":mycount})
+
+ for x in mylist.keys():
+ if mylist[x].has_key(myhost) or remove_all_locks:
+ mylockname = hardlock_name(path+"/"+x)
+ if hardlink_is_mine(mylockname, path+"/"+x) or \
+ not os.path.exists(path+"/"+x) or \
+ remove_all_locks:
+ for y in mylist[x].keys():
+ for z in mylist[x][y]:
+ filename = path+"/"+x+".hardlock-"+y+"-"+z
+ if filename == mylockname:
+ continue
+ try:
+ # We're sweeping through, unlinking everyone's locks.
+ os.unlink(filename)
+ results.append(_("Unlinked: ") + filename)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ pass
+ try:
+ os.unlink(path+"/"+x)
+ results.append(_("Unlinked: ") + path+"/"+x)
+ os.unlink(mylockname)
+ results.append(_("Unlinked: ") + mylockname)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ pass
+ else:
+ try:
+ os.unlink(mylockname)
+ results.append(_("Unlinked: ") + mylockname)
+ except SystemExit, e:
+ raise
+ except Exception,e:
+ pass
+
+ return results
+
diff --git a/pym/portage_util.py b/pym/portage_util.py
new file mode 100644
index 00000000..ee1c38b3
--- /dev/null
+++ b/pym/portage_util.py
@@ -0,0 +1,459 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_util.py,v 1.11.2.6 2005/04/23 07:26:04 jstubbs Exp $
+cvs_id_string="$Id: portage_util.py,v 1.11.2.6 2005/04/23 07:26:04 jstubbs Exp $"[5:-2]
+
+import sys,string,shlex,os.path
+
+noiselimit = 0
+def writemsg(mystr,noiselevel=0):
+ """Prints out warning and debug messages based on the noiselimit setting"""
+ global noiselimit
+ if noiselevel <= noiselimit:
+ sys.stderr.write(mystr)
+ sys.stderr.flush()
+
+def grabfile(myfilename, compat_level=0):
+ """This function grabs the lines in a file, normalizes whitespace and returns lines in a list; if a line
+ begins with a #, it is ignored, as are empty lines"""
+
+ try:
+ myfile=open(myfilename,"r")
+ except IOError:
+ return []
+ mylines=myfile.readlines()
+ myfile.close()
+ newlines=[]
+ for x in mylines:
+ #the split/join thing removes leading and trailing whitespace, and converts any whitespace in the line
+ #into single spaces.
+ myline=string.join(string.split(x))
+ if not len(myline):
+ continue
+ if myline[0]=="#":
+ # Check if we have a compat-level string. BC-integration data.
+ # '##COMPAT==>N<==' 'some string attached to it'
+ mylinetest = string.split(myline, "<==", 1)
+ if len(mylinetest) == 2:
+ myline_potential = mylinetest[1]
+ mylinetest = string.split(mylinetest[0],"##COMPAT==>")
+ if len(mylinetest) == 2:
+ if compat_level >= int(mylinetest[1]):
+ # It's a compat line, and the key matches.
+ newlines.append(myline_potential)
+ continue
+ else:
+ continue
+ newlines.append(myline)
+ return newlines
+
+def map_dictlist_vals(func,myDict):
+ """Performs a function on each value of each key in a dictlist.
+ Returns a new dictlist."""
+ new_dl = {}
+ for key in myDict.keys():
+ new_dl[key] = []
+ new_dl[key] = map(func,myDict[key])
+ return new_dl
+
+def stack_dictlist(original_dicts, incremental=0, incrementals=[], ignore_none=0):
+ """Stacks an array of dict-types into one array. Optionally merging or
+ overwriting matching key/value pairs for the dict[key]->list.
+ Returns a single dict. Higher index in lists is preferenced."""
+ final_dict = None
+ kill_list = {}
+ for mydict in original_dicts:
+ if mydict == None:
+ continue
+ if final_dict == None:
+ final_dict = {}
+ for y in mydict.keys():
+ if not final_dict.has_key(y):
+ final_dict[y] = []
+ if not kill_list.has_key(y):
+ kill_list[y] = []
+
+ mydict[y].reverse()
+ for thing in mydict[y]:
+ if thing and (thing not in kill_list[y]) and ("*" not in kill_list[y]):
+ if (incremental or (y in incrementals)) and thing[0] == '-':
+ if thing[1:] not in kill_list[y]:
+ kill_list[y] += [thing[1:]]
+ else:
+ if thing not in final_dict[y]:
+ final_dict[y].append(thing[:])
+ mydict[y].reverse()
+ if final_dict.has_key(y) and not final_dict[y]:
+ del final_dict[y]
+ return final_dict
+
+def stack_dicts(dicts, incremental=0, incrementals=[], ignore_none=0):
+ """Stacks an array of dict-types into one array. Optionally merging or
+ overwriting matching key/value pairs for the dict[key]->string.
+ Returns a single dict."""
+ final_dict = None
+ for mydict in dicts:
+ if mydict == None:
+ if ignore_none:
+ continue
+ else:
+ return None
+ if final_dict == None:
+ final_dict = {}
+ for y in mydict.keys():
+ if mydict[y]:
+ if final_dict.has_key(y) and (incremental or (y in incrementals)):
+ final_dict[y] += " "+mydict[y][:]
+ else:
+ final_dict[y] = mydict[y][:]
+ mydict[y] = string.join(mydict[y].split()) # Remove extra spaces.
+ return final_dict
+
+def stack_lists(lists, incremental=1):
+ """Stacks an array of list-types into one array. Optionally removing
+ distinct values using '-value' notation. Higher index is preferenced."""
+ new_list = []
+ for x in lists:
+ for y in x:
+ if y:
+ if incremental and y[0]=='-':
+ while y[1:] in new_list:
+ del new_list[new_list.index(y[1:])]
+ else:
+ if y not in new_list:
+ new_list.append(y[:])
+ return new_list
+
+def grab_multiple(basename, locations, handler, all_must_exist=0):
+ mylist = []
+ for x in locations:
+ mylist.append(handler(x+"/"+basename))
+ return mylist
+
+def grabdict(myfilename,juststrings=0,empty=0):
+ """This function grabs the lines in a file, normalizes whitespace and returns lines in a dictionary"""
+ newdict={}
+ try:
+ myfile=open(myfilename,"r")
+ except IOError,e:
+ return newdict
+ mylines=myfile.readlines()
+ myfile.close()
+ for x in mylines:
+ #the split/join thing removes leading and trailing whitespace, and converts any whitespace in the line
+ #into single spaces.
+ if x[0] == "#":
+ continue
+ myline=string.split(x)
+ if len(myline)<2 and empty==0:
+ continue
+ if len(myline)<1 and empty==1:
+ continue
+ if juststrings:
+ newdict[myline[0]]=string.join(myline[1:])
+ else:
+ newdict[myline[0]]=myline[1:]
+ return newdict
+
+def grabdict_package(myfilename,juststrings=0):
+ pkgs=grabdict(myfilename, juststrings, empty=1)
+ for x in pkgs.keys():
+ if not isvalidatom(x):
+ del(pkgs[x])
+ writemsg("--- Invalid atom in %s: %s\n" % (myfilename, x))
+ return pkgs
+
+def grabfile_package(myfilename,compatlevel=0):
+ pkgs=grabfile(myfilename,compatlevel)
+ for x in range(len(pkgs)-1,-1,-1):
+ pkg = pkgs[x]
+ if pkg[0] == "-":
+ pkg = pkg[1:]
+ if pkg[0] == "*": # Kill this so we can deal the "packages" file too
+ pkg = pkg[1:]
+ if not isvalidatom(pkg):
+ writemsg("--- Invalid atom in %s: %s\n" % (myfilename, pkgs[x]))
+ del(pkgs[x])
+ return pkgs
+
+def grabints(myfilename):
+ newdict={}
+ try:
+ myfile=open(myfilename,"r")
+ except IOError:
+ return newdict
+ mylines=myfile.readlines()
+ myfile.close()
+ for x in mylines:
+ #the split/join thing removes leading and trailing whitespace, and converts any whitespace in the line
+ #into single spaces.
+ myline=string.split(x)
+ if len(myline)!=2:
+ continue
+ newdict[myline[0]]=string.atoi(myline[1])
+ return newdict
+
+def writeints(mydict,myfilename):
+ try:
+ myfile=open(myfilename,"w")
+ except IOError:
+ return 0
+ for x in mydict.keys():
+ myfile.write(x+" "+`mydict[x]`+"\n")
+ myfile.close()
+ return 1
+
+def writedict(mydict,myfilename,writekey=1):
+ """Writes out a dict to a file; writekey=0 mode doesn't write out
+ the key and assumes all values are strings, not lists."""
+ try:
+ myfile=open(myfilename,"w")
+ except IOError:
+ writemsg("Failed to open file for writedict(): "+str(myfilename)+"\n")
+ return 0
+ if not writekey:
+ for x in mydict.values():
+ myfile.write(x+"\n")
+ else:
+ for x in mydict.keys():
+ myfile.write(x+" ")
+ for y in mydict[x]:
+ myfile.write(y+" ")
+ myfile.write("\n")
+ myfile.close()
+ return 1
+
+def getconfig(mycfg,tolerant=0,allow_sourcing=False):
+ mykeys={}
+ try:
+ f=open(mycfg,'r')
+ except IOError:
+ return None
+ try:
+ lex=shlex.shlex(f)
+ lex.wordchars=string.digits+string.letters+"~!@#$%*_\:;?,./-+{}"
+ lex.quotes="\"'"
+ if allow_sourcing:
+ lex.source="source"
+ while 1:
+ key=lex.get_token()
+ if (key==''):
+ #normal end of file
+ break;
+ equ=lex.get_token()
+ if (equ==''):
+ #unexpected end of file
+ #lex.error_leader(self.filename,lex.lineno)
+ if not tolerant:
+ writemsg("!!! Unexpected end of config file: variable "+str(key)+"\n")
+ raise Exception("ParseError: Unexpected EOF: "+str(mycfg)+": on/before line "+str(lex.lineno))
+ else:
+ return mykeys
+ elif (equ!='='):
+ #invalid token
+ #lex.error_leader(self.filename,lex.lineno)
+ if not tolerant:
+ writemsg("!!! Invalid token (not \"=\") "+str(equ)+"\n")
+ raise Exception("ParseError: Invalid token (not '='): "+str(mycfg)+": line "+str(lex.lineno))
+ else:
+ return mykeys
+ val=lex.get_token()
+ if (val==''):
+ #unexpected end of file
+ #lex.error_leader(self.filename,lex.lineno)
+ if not tolerant:
+ writemsg("!!! Unexpected end of config file: variable "+str(key)+"\n")
+ raise portage_exception.CorruptionError("ParseError: Unexpected EOF: "+str(mycfg)+": line "+str(lex.lineno))
+ else:
+ return mykeys
+ mykeys[key]=varexpand(val,mykeys)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ raise e.__class__, str(e)+" in "+mycfg
+ return mykeys
+
+#cache expansions of constant strings
+cexpand={}
+def varexpand(mystring,mydict={}):
+ try:
+ return cexpand[" "+mystring]
+ except KeyError:
+ pass
+ """
+ new variable expansion code. Removes quotes, handles \n, etc.
+ This code is used by the configfile code, as well as others (parser)
+ This would be a good bunch of code to port to C.
+ """
+ numvars=0
+ mystring=" "+mystring
+ #in single, double quotes
+ insing=0
+ indoub=0
+ pos=1
+ newstring=" "
+ while (pos<len(mystring)):
+ if (mystring[pos]=="'") and (mystring[pos-1]!="\\"):
+ if (indoub):
+ newstring=newstring+"'"
+ else:
+ insing=not insing
+ pos=pos+1
+ continue
+ elif (mystring[pos]=='"') and (mystring[pos-1]!="\\"):
+ if (insing):
+ newstring=newstring+'"'
+ else:
+ indoub=not indoub
+ pos=pos+1
+ continue
+ if (not insing):
+ #expansion time
+ if (mystring[pos]=="\n"):
+ #convert newlines to spaces
+ newstring=newstring+" "
+ pos=pos+1
+ elif (mystring[pos]=="\\"):
+ #backslash expansion time
+ if (pos+1>=len(mystring)):
+ newstring=newstring+mystring[pos]
+ break
+ else:
+ a=mystring[pos+1]
+ pos=pos+2
+ if a=='a':
+ newstring=newstring+chr(007)
+ elif a=='b':
+ newstring=newstring+chr(010)
+ elif a=='e':
+ newstring=newstring+chr(033)
+ elif (a=='f') or (a=='n'):
+ newstring=newstring+chr(012)
+ elif a=='r':
+ newstring=newstring+chr(015)
+ elif a=='t':
+ newstring=newstring+chr(011)
+ elif a=='v':
+ newstring=newstring+chr(013)
+ elif a!='\n':
+ #remove backslash only, as bash does: this takes care of \\ and \' and \" as well
+ newstring=newstring+mystring[pos-1:pos]
+ continue
+ elif (mystring[pos]=="$") and (mystring[pos-1]!="\\"):
+ pos=pos+1
+ if mystring[pos]=="{":
+ pos=pos+1
+ braced=True
+ else:
+ braced=False
+ myvstart=pos
+ validchars=string.ascii_letters+string.digits+"_"
+ while mystring[pos] in validchars:
+ if (pos+1)>=len(mystring):
+ if braced:
+ cexpand[mystring]=""
+ return ""
+ else:
+ pos=pos+1
+ break
+ pos=pos+1
+ myvarname=mystring[myvstart:pos]
+ if braced:
+ if mystring[pos]!="}":
+ cexpand[mystring]=""
+ return ""
+ else:
+ pos=pos+1
+ if len(myvarname)==0:
+ cexpand[mystring]=""
+ return ""
+ numvars=numvars+1
+ if mydict.has_key(myvarname):
+ newstring=newstring+mydict[myvarname]
+ else:
+ newstring=newstring+mystring[pos]
+ pos=pos+1
+ else:
+ newstring=newstring+mystring[pos]
+ pos=pos+1
+ if numvars==0:
+ cexpand[mystring]=newstring[1:]
+ return newstring[1:]
+
+def pickle_write(data,filename,debug=0):
+ import cPickle,os
+ try:
+ myf=open(filename,"w")
+ cPickle.dump(data,myf,-1)
+ myf.flush()
+ myf.close()
+ writemsg("Wrote pickle: "+str(filename)+"\n",1)
+ os.chown(myefn,uid,portage_gid)
+ os.chmod(myefn,0664)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ return 0
+ return 1
+
+def pickle_read(filename,default=None,debug=0):
+ import cPickle,os
+ if not os.access(filename, os.R_OK):
+ writemsg("pickle_read(): File not readable. '"+filename+"'\n",1)
+ return default
+ data = None
+ try:
+ myf = open(filename)
+ mypickle = cPickle.Unpickler(myf)
+ mypickle.find_global = None
+ data = mypickle.load()
+ myf.close()
+ del mypickle,myf
+ writemsg("pickle_read(): Loaded pickle. '"+filename+"'\n",1)
+ except SystemExit, e:
+ raise
+ except Exception, e:
+ writemsg("!!! Failed to load pickle: "+str(e)+"\n",1)
+ data = default
+ return data
+
+class ReadOnlyConfig:
+ def __init__(self,filename,strict_keys=0):
+ self.__filename = filename[:]
+ self.__strict_keys = strict_keys
+ self.__mydict = {}
+ self.__dict_was_loaded = False
+ if os.path.isfile(self.__filename):
+ self.__mydict = getconfig(self.__filename)
+ self.__dict_was_loaded = True
+
+ def isLoaded():
+ return self.__dict_was_loaded
+
+ def __getitem__(self,key):
+ if self.__mydict.has_key(key):
+ return self.__mydict[key][:]
+ if self.__strict_keys:
+ raise KeyError("%s not found in config: '%s'" % (key,self.__filename))
+ return ""
+
+ def __setitem__(self,key,value):
+ raise KeyError("This class is not modifiable.")
+
+ def keys(self):
+ return self.__mydict.keys()
+
+ def has_key(self,key):
+ return self.__mydict.has_key(key)
+
+def unique_array(array):
+ """Takes an array and makes sure each element is unique."""
+ mya = []
+ for x in array:
+ if x not in mya:
+ mya.append(x)
+ return mya
+
+
+
+
diff --git a/pym/xpak.py b/pym/xpak.py
new file mode 100644
index 00000000..b6a64942
--- /dev/null
+++ b/pym/xpak.py
@@ -0,0 +1,384 @@
+# Copyright 2001-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/pym/xpak.py,v 1.13.2.3 2005/02/26 11:22:38 carpaski Exp $
+cvs_id_string="$Id: xpak.py,v 1.13.2.3 2005/02/26 11:22:38 carpaski Exp $"[5:-2]
+
+# The format for a tbz2/xpak:
+#
+# tbz2: tar.bz2 + xpak + (xpak_offset) + "STOP"
+# xpak: "XPAKPACK" + (index_len) + (data_len) + index + data + "XPAKSTOP"
+# index: (pathname_len) + pathname + (data_offset) + (data_len)
+# index entries are concatenated end-to-end.
+# data: concatenated data chunks, end-to-end.
+#
+# [tarball]XPAKPACKIIIIDDDD[index][data]XPAKSTOPOOOOSTOP
+#
+# (integer) == encodeint(integer) ===> 4 characters (big-endian copy)
+# '+' means concatenate the fields ===> All chunks are strings
+
+import sys,os,string
+from stat import *
+
+def addtolist(mylist,curdir):
+ """(list, dir) --- Takes an array(list) and appends all files from dir down
+ the directory tree. Returns nothing. list is modified."""
+ for x in os.listdir("."):
+ if os.path.isdir(x):
+ os.chdir(x)
+ addtolist(mylist,curdir+x+"/")
+ os.chdir("..")
+ else:
+ if curdir+x not in mylist:
+ mylist.append(curdir+x)
+
+def encodeint(myint):
+ """Takes a 4 byte integer and converts it into a string of 4 characters.
+ Returns the characters in a string."""
+ part1=chr((myint >> 24 ) & 0x000000ff)
+ part2=chr((myint >> 16 ) & 0x000000ff)
+ part3=chr((myint >> 8 ) & 0x000000ff)
+ part4=chr(myint & 0x000000ff)
+ return part1+part2+part3+part4
+
+def decodeint(mystring):
+ """Takes a 4 byte string and converts it into a 4 byte integer.
+ Returns an integer."""
+ myint=0
+ myint=myint+ord(mystring[3])
+ myint=myint+(ord(mystring[2]) << 8)
+ myint=myint+(ord(mystring[1]) << 16)
+ myint=myint+(ord(mystring[0]) << 24)
+ return myint
+
+def xpak(rootdir,outfile=None):
+ """(rootdir,outfile) -- creates an xpak segment of the directory 'rootdir'
+ and under the name 'outfile' if it is specified. Otherwise it returns the
+ xpak segment."""
+ try:
+ origdir=os.getcwd()
+ except SystemExit, e:
+ raise
+ except:
+ os.chdir("/")
+ origdir="/"
+ os.chdir(rootdir)
+ mylist=[]
+
+ addtolist(mylist,"")
+ mylist.sort()
+
+ #Our list index has been created
+
+ indexglob=""
+ indexpos=0
+ dataglob=""
+ datapos=0
+ for x in mylist:
+ a=open(x,"r")
+ newglob=a.read()
+ a.close()
+ mydatasize=len(newglob)
+ indexglob=indexglob+encodeint(len(x))+x+encodeint(datapos)+encodeint(mydatasize)
+ indexpos=indexpos+4+len(x)+4+4
+ dataglob=dataglob+newglob
+ datapos=datapos+mydatasize
+ os.chdir(origdir)
+ if outfile:
+ outf=open(outfile,"w")
+ outf.write("XPAKPACK"+encodeint(len(indexglob))+encodeint(len(dataglob)))
+ outf.write(indexglob)
+ outf.write(dataglob)
+ outf.write("XPAKSTOP")
+ outf.close()
+ else:
+ myret="XPAKPACK"+encodeint(len(indexglob))+encodeint(len(dataglob))
+ myret=myret+indexglob+dataglob+"XPAKSTOP"
+ return myret
+
+def xsplit(infile):
+ """(infile) -- Splits the infile into two files.
+ 'infile.index' contains the index segment.
+ 'infile.dat' contails the data segment."""
+ myfile=open(infile,"r")
+ mydat=myfile.read()
+ myfile.close()
+
+ splits = xsplit_mem(mydat)
+ if not splits:
+ return
+
+ myfile=open(infile+".index","w")
+ myfile.write(splits[0])
+ myfile.close()
+ myfile=open(infile+".dat","w")
+ myfile.write(splits[1])
+ myfile.close()
+ return
+
+def xsplit_mem(mydat):
+ if mydat[0:8]!="XPAKPACK":
+ return None
+ if mydat[-8:]!="XPAKSTOP":
+ return None
+ indexsize=decodeint(mydat[8:12])
+ datasize=decodeint(mydat[12:16])
+ return (mydat[16:indexsize+16], mydat[indexsize+16:-8])
+
+def getindex(infile):
+ """(infile) -- grabs the index segment from the infile and returns it."""
+ myfile=open(infile,"r")
+ myheader=myfile.read(16)
+ if myheader[0:8]!="XPAKPACK":
+ myfile.close()
+ return
+ indexsize=decodeint(myheader[8:12])
+ myindex=myfile.read(indexsize)
+ myfile.close()
+ return myindex
+
+def getboth(infile):
+ """(infile) -- grabs the index and data segments from the infile.
+ Returns an array [indexSegment,dataSegment]"""
+ myfile=open(infile,"r")
+ myheader=myfile.read(16)
+ if myheader[0:8]!="XPAKPACK":
+ myfile.close()
+ return
+ indexsize=decodeint(myheader[8:12])
+ datasize=decodeint(myheader[12:16])
+ myindex=myfile.read(indexsize)
+ mydata=myfile.read(datasize)
+ myfile.close()
+ return [myindex,mydata]
+
+def listindex(myindex):
+ """Print to the terminal the filenames listed in the indexglob passed in."""
+ for x in getindex_mem(myindex):
+ print x
+
+def getindex_mem(myindex):
+ """Returns the filenames listed in the indexglob passed in."""
+ myindexlen=len(myindex)
+ startpos=0
+ myret=[]
+ while ((startpos+8)<myindexlen):
+ mytestlen=decodeint(myindex[startpos:startpos+4])
+ myret=myret+[myindex[startpos+4:startpos+4+mytestlen]]
+ startpos=startpos+mytestlen+12
+ return myret
+
+def searchindex(myindex,myitem):
+ """(index,item) -- Finds the offset and length of the file 'item' in the
+ datasegment via the index 'index' provided."""
+ mylen=len(myitem)
+ myindexlen=len(myindex)
+ startpos=0
+ while ((startpos+8)<myindexlen):
+ mytestlen=decodeint(myindex[startpos:startpos+4])
+ if mytestlen==mylen:
+ if myitem==myindex[startpos+4:startpos+4+mytestlen]:
+ #found
+ datapos=decodeint(myindex[startpos+4+mytestlen:startpos+8+mytestlen]);
+ datalen=decodeint(myindex[startpos+8+mytestlen:startpos+12+mytestlen]);
+ return [datapos,datalen]
+ startpos=startpos+mytestlen+12
+
+def getitem(myid,myitem):
+ myindex=myid[0]
+ mydata=myid[1]
+ myloc=searchindex(myindex,myitem)
+ if not myloc:
+ return None
+ return mydata[myloc[0]:myloc[0]+myloc[1]]
+
+def xpand(myid,mydest):
+ myindex=myid[0]
+ mydata=myid[1]
+ try:
+ origdir=os.getcwd()
+ except SystemExit, e:
+ raise
+ except:
+ os.chdir("/")
+ origdir="/"
+ os.chdir(mydest)
+ myindexlen=len(myindex)
+ startpos=0
+ while ((startpos+8)<myindexlen):
+ namelen=decodeint(myindex[startpos:startpos+4])
+ datapos=decodeint(myindex[startpos+4+namelen:startpos+8+namelen]);
+ datalen=decodeint(myindex[startpos+8+namelen:startpos+12+namelen]);
+ myname=myindex[startpos+4:startpos+4+namelen]
+ dirname=os.path.dirname(myname)
+ if dirname:
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ mydat=open(myname,"w")
+ mydat.write(mydata[datapos:datapos+datalen])
+ mydat.close()
+ startpos=startpos+namelen+12
+ os.chdir(origdir)
+
+class tbz2:
+ def __init__(self,myfile):
+ self.file=myfile
+ self.filestat=None
+ self.index=""
+ self.infosize=0
+ self.xpaksize=0
+ self.indexsize=None
+ self.datasize=None
+ self.indexpos=None
+ self.datapos=None
+ self.scan()
+
+ def decompose(self,datadir,cleanup=1):
+ """Alias for unpackinfo() --- Complement to recompose() but optionally
+ deletes the destination directory. Extracts the xpak from the tbz2 into
+ the directory provided. Raises IOError if scan() fails.
+ Returns result of upackinfo()."""
+ if not self.scan():
+ raise IOError
+ if cleanup and os.path.exists(datadir):
+ # XXX: Potentially bad
+ os.system("rm -Rf "+datadir+"/*")
+ if not os.path.exists(datadir):
+ os.makedirs(datadir)
+ return self.unpackinfo(datadir)
+ def compose(self,datadir,cleanup=0):
+ """Alias for recompose()."""
+ return recompose(datadir,cleanup)
+ def recompose(self,datadir,cleanup=0):
+ """Creates an xpak segment from the datadir provided, truncates the tbz2
+ to the end of regular data if an xpak segment already exists, and adds
+ the new segment to the file with terminating info."""
+ self.scan() # Don't care about condition... We'll rewrite the data anyway.
+ myfile=open(self.file,"a+")
+ if not myfile:
+ raise IOError
+ myfile.seek(-self.xpaksize,2) # 0,2 or -0,2 just mean EOF.
+ myfile.truncate()
+ xpdata=xpak(datadir)
+ myfile.write(xpdata+encodeint(len(xpdata))+"STOP")
+ myfile.flush()
+ myfile.close()
+ if cleanup:
+ # XXX: Potentially bad
+ os.system("rm -Rf "+datadir)
+ return 1
+
+ def scan(self):
+ """Scans the tbz2 to locate the xpak segment and setup internal values.
+ This function is called by relevant functions already."""
+ try:
+ mystat=os.stat(self.file)
+ if self.filestat:
+ changed=0
+ for x in [ST_SIZE, ST_MTIME, ST_CTIME]:
+ if mystat[x] != self.filestat[x]:
+ changed=1
+ if not changed:
+ return 1
+ self.filestat=mystat
+ a=open(self.file,"r")
+ a.seek(-16,2)
+ trailer=a.read()
+ self.infosize=0
+ self.xpaksize=0
+ if trailer[-4:]!="STOP":
+ a.close()
+ return 0
+ if trailer[0:8]!="XPAKSTOP":
+ a.close()
+ return 0
+ self.infosize=decodeint(trailer[8:12])
+ self.xpaksize=self.infosize+8
+ a.seek(-(self.xpaksize),2)
+ header=a.read(16)
+ if header[0:8]!="XPAKPACK":
+ a.close()
+ return 0
+ self.indexsize=decodeint(header[8:12])
+ self.datasize=decodeint(header[12:16])
+ self.indexpos=a.tell()
+ self.index=a.read(self.indexsize)
+ self.datapos=a.tell()
+ a.close()
+ return 2
+ except SystemExit, e:
+ raise
+ except:
+ return 0
+
+ def filelist(self):
+ """Return an array of each file listed in the index."""
+ if not self.scan():
+ return None
+ return getindex_mem(self.index)
+
+ def getfile(self,myfile,mydefault=None):
+ """Finds 'myfile' in the data segment and returns it."""
+ if not self.scan():
+ return None
+ myresult=searchindex(self.index,myfile)
+ if not myresult:
+ return mydefault
+ a=open(self.file,"r")
+ a.seek(self.datapos+myresult[0],0)
+ myreturn=a.read(myresult[1])
+ a.close()
+ return myreturn
+
+ def getelements(self,myfile):
+ """A split/array representation of tbz2.getfile()"""
+ mydat=self.getfile(myfile)
+ if not mydat:
+ return []
+ return string.split(mydat)
+
+ def unpackinfo(self,mydest):
+ """Unpacks all the files from the dataSegment into 'mydest'."""
+ if not self.scan():
+ return 0
+ try:
+ origdir=os.getcwd()
+ except SystemExit, e:
+ raise
+ except:
+ os.chdir("/")
+ origdir="/"
+ a=open(self.file,"r")
+ if not os.path.exists(mydest):
+ os.makedirs(mydest)
+ os.chdir(mydest)
+ startpos=0
+ while ((startpos+8)<self.indexsize):
+ namelen=decodeint(self.index[startpos:startpos+4])
+ datapos=decodeint(self.index[startpos+4+namelen:startpos+8+namelen]);
+ datalen=decodeint(self.index[startpos+8+namelen:startpos+12+namelen]);
+ myname=self.index[startpos+4:startpos+4+namelen]
+ dirname=os.path.dirname(myname)
+ if dirname:
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ mydat=open(myname,"w")
+ a.seek(self.datapos+datapos)
+ mydat.write(a.read(datalen))
+ mydat.close()
+ startpos=startpos+namelen+12
+ a.close()
+ os.chdir(origdir)
+ return 1
+
+ def getboth(self):
+ """Returns an array [indexSegment,dataSegment]"""
+ if not self.scan():
+ return None
+
+ a = open(self.file,"r")
+ a.seek(self.datapos)
+ mydata =a.read(self.datasize)
+ a.close()
+
+ return [self.index[:],mydata]
+
diff --git a/qa/iuse/iuse.sh b/qa/iuse/iuse.sh
new file mode 100644
index 00000000..3b30d25e
--- /dev/null
+++ b/qa/iuse/iuse.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+cd /usr/portage/
+for x in `find -name '*.ebuild'`
+do
+ echo $x
+ bn=${x##*/}
+ dn=${x%/*}
+ fn=.use-${bn/.ebuild/}
+ myout=${dn}/${fn}
+
+ #massive pipeline follows
+ sed -e 's/^\([^#]*\)#.*$/\1/' -e '/^pkg_/q' $x | \
+ grep -e 'use [[:alnum:]]*' | \
+ grep -v DESCRIPTION | \
+ sed -e 's/^.*use \([[:alnum:]]*\).*$/\1/' | \
+ sed -e '/^$/d' | \
+ sort | \
+ uniq > $myout
+
+done
diff --git a/qa/iuse/iuse2.py b/qa/iuse/iuse2.py
new file mode 100755
index 00000000..7944b932
--- /dev/null
+++ b/qa/iuse/iuse2.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python2.2
+import portage,sys
+portdir=portage.settings["PORTDIR"]
+for cp in portage.portdb.cp_all():
+ for cpv in portage.portdb.cp_list(cp):
+ try:
+ myaux=portage.portdb.aux_get(cpv,["DEPEND","RDEPEND","SRC_URI"])
+ except KeyError:
+ pass
+ myuse={}
+ for str in myaux:
+ mysplit=str.split()
+ for part in mysplit:
+ if part[-1]=="?":
+ if part[0]=="!":
+ if not myuse.has_key(part[1:-1]):
+ myuse[part[1:-1]]=None
+ else:
+ if not myuse.has_key(part[:-1]):
+ myuse[part[:-1]]=None
+ if not myuse:
+ continue
+ cpsplit=cpv.split("/")
+ mypath=portdir+"/"+cp+"/.use-"+cpsplit[1]
+ print mypath
+ myfile=open(mypath,"r")
+ for x in myfile.readlines():
+ if x[:-1]:
+ if not myuse.has_key(x[:-1]):
+ myuse[x[:-1]]=None
+ print myuse.keys()
+ myfile.close()
+ if not myuse.keys():
+ #no IUSE to add
+ continue
+ myepath=portdir+"/"+cp+"/"+cpsplit[1]+".ebuild"
+ myefile=open(myepath,"r")
+ mylines=myefile.readlines()
+ myefile.close()
+ mynewlines=[]
+ pos=0
+ while (pos<len(mylines)) and (mylines[pos][0]=="#"):
+ mynewlines.append(mylines[pos])
+ pos += 1
+ myuses=myuse.keys()
+ iuseline="\nIUSE=\""+myuses[0]
+ for x in myuses[1:]:
+ iuseline=iuseline+" "+x
+ iuseline=iuseline+"\"\n"
+ mynewlines.append(iuseline)
+ while (pos<len(mylines)):
+ mynewlines.append(mylines[pos])
+ pos += 1
+
+ myefile=open(myepath,"w")
+ for x in mynewlines:
+ myefile.write(x)
+ myefile.close()
diff --git a/spec/emerge.syntax b/spec/emerge.syntax
new file mode 100755
index 00000000..17b8131a
--- /dev/null
+++ b/spec/emerge.syntax
@@ -0,0 +1,1149 @@
+#!/usr/bin/env python
+import os
+from os.path import walk, splitext, exists, basename, dirname
+import sys
+
+import output
+from output import *
+import portage
+import xpak
+import string
+from string import strip, find, replace, split
+import commands
+import shutil
+import re
+import time
+
+#number of ebuilds merged
+merged=0
+# there can only be one action specified; the default action is to merge
+# specified packages, not update.
+actions=["help",
+ "rebuild",
+ "search",
+ "update",
+ "clean",
+ "zap",
+ "rsync"]
+# emerge (prints help)
+# emerge help (prints help)
+# emerge help config (prints config file management help)
+
+# emerge rsync
+
+# the default behavior of emerge is to satisfy dependencies specified by merging packages.
+# emerge system (satisfy deps for "system" package class)
+# emerge world (equivalent to emerge system since "world" doesn't offer any new deps)
+# emerge <depstring> (satisfy dep by merging most recent version of app available that satisfies dep)
+# NOTE: this will cause something to be merged again if the dep happens to be already satisfied
+# "unslotted" is invalid for a package class here because it only applies to already-installed ebuilds.
+# pkgclass support: "system", "world", <depstring>, <pkgname>, <ebuild>, <tbz2>
+
+# no changes here except we use "update" rather than "--update"
+# emerge update <pkgclass/depstring/pkgname>
+# emerge update (defaults to "world")
+# "emerge update <ebuild/tbz2> doesn't make too much sense.
+# But it should do the same thing are "emerge <ebuild/tbz2>".
+
+# rebuild is like "update" except that all packages will be rebuilt even if they currently are installed.
+# emerge rebuild (defaults to "world")
+# emerge rebuild <pkgclass/depstring/pkgname/ebuild>
+# "emerge rebuild <ebuild/tbz2> doesn't make too much sense.
+# But it should do the same thing are "emerge <ebuild/tbz2>".
+
+# emerge search (invalid)
+# emerge search <regex>
+
+# clean does "cleaning" only; it does not do anything that would generally be considered dangerous
+# emerge clean (defaults to "world"; apply default AUTOCLEAN behavior defined in make.conf)
+# emerge --rev clean (defaults to "world", cleans out old revisions)
+# emerge --slot clean (defaults to "world", cleans out old stuff from slots)
+# emerge [--rev/--slot] clean <pkgclass>
+# AUTOCLEAN var can be set to "slot", "rev", or "none/off/etc".
+
+# zap flat out removes stuff. No holds barred. Can be dangerous.
+# emerge zap <pkgclass> (only "unslotted" is valid, which is still dangerous. Or a dep "=foo/bar")
+# NOTE: of course, "emerge zap" alone is invalid and will *not* default to a "world" package class
+
+pkgclass=["world","system","unslotted"]
+helpclass=["config"]
+
+# These next options are the only long options for Portage 1.8.9 except for "--help" (equiv. to "help")
+
+options=["--autoclean",
+ "--buildpkg",
+ "--debug",
+ "--fetchonly",
+ "--noreplace",
+ "--onlydeps",
+ "--pretend",
+ "--usepkg",
+ "--verbose",
+ "--emptytree",
+ "--rev",
+ "--slot",
+ "--help"]
+
+# Here are the currently supported short mappings.
+
+shortmapping={"a":"--autoclean",
+ "b":"--buildpkg",
+ "d":"--debug",
+ "f":"--fetchonly",
+ "h":"--help",
+ "k":"--usepkg",
+ "n":"--noreplace",
+ "o":"--onlydeps",
+ "p":"--pretend",
+ "v":"--verbose" }
+
+# end of spec
+
+myaction=None
+myopts=[]
+mymode=[]
+myfiles=[]
+edebug=0
+
+# process short actions and options
+for x in sys.argv[1:]:
+ if x[0:1]=="-"and not x[1:2]=="-":
+ for y in x[1:]:
+ if shortmapping.has_key(y):
+ sys.argv.append(shortmapping[y])
+ else:
+ print y
+ print "!!! Error: -"+y+" is an invalid short action or option."
+ sys.argv.remove(x)
+
+# process the command arguments
+for x in sys.argv[1:]:
+ if x=="update" or x=="--unmerge" or x=="--world":
+ print
+ if x=="update":
+ print " "+red("* WARNING:"),green("emerge update"),"has been deprecated, use",green("emerge --update"),"instead."
+ elif x=="--unmerge":
+ print " "+red("* WARNING:"),green("emerge --unmerge"),"has been deprecated, use",green("emerge --zap"),"instead."
+ elif x=="--world":
+ print " "+red("* WARNING:"),green("emerge --world"),"has been deprecated, use",green("emerge world"),"instead."
+ print " "+red("*"),"Read",green("emerge --help"),"to get a complete overview of the interface changes."
+ print
+ sys.exit(1)
+
+ if len(x)>=2:
+ if x[0:1]=="-":
+ if x[1:2]=="-":
+ if x in actions:
+ if myaction:
+ print "!!! Error: more than one action specified on command-line."
+ print "!!! Available actions:",actions
+ sys.exit(1)
+ else:
+ myaction=x
+ elif x in options:
+ myopts.append(x)
+ else:
+ print "!!! Error:",x,"is an invalid action or option."
+ sys.exit(1)
+ else:
+ for y in x[1:]:
+ if shortmapping.has_key(y):
+ myopts.append(shortmapping[y])
+ else:
+ print y
+ print "!!! Error: -"+y+" is an invalid short action or option."
+ elif x in modes:
+ if len(mymode)>=1:
+ print "!!! Error: more than one mode specified on command-line."
+ print "!!! Available modes:",modes
+ sys.exit(1)
+ else:
+ mymode.append(x)
+ else:
+ # this little conditional helps tab completion
+ if x[-1]=="/":
+ myfiles.append(x[:-1])
+ else:
+ myfiles.append(x)
+
+# check if root user is the current user for the actions where emerge needs this
+if os.getuid()!=0 and "--help"!=myaction and "--search"!=myaction:
+ print "!!! to be able to perform the requested action, emerge must be run by root."
+ sys.exit(1)
+
+# search functionality
+class search:
+
+ #
+ # class constants
+ #
+ VERSION_SHORT=1
+ VERSION_RELEASE=2
+
+ #
+ # public interface
+ #
+ def __init__(self,searchkey=""):
+ """Searches the available and installed packages for the supplied search key.
+ The list of available and installed packages is created at object instantiation.
+ This makes successive searches faster."""
+ self.searchkey = searchkey
+ self.treecache = portage.portagetree()
+ self.treecache.populate()
+ self.installcache = portage.vartree()
+ self.installcache.populate()
+ self.re_portagedir = re.compile('/usr/portage/')
+ self.re_description = re.compile('DESCRIPTION="')
+ self.initResults()
+
+ def setKey(self,searchkey):
+ """changes the search key"""
+ self.searchkey = searchkey
+ self.initResults()
+
+ def execute(self):
+ """Performs the saerch for the supplied search key"""
+ if self.searchkey:
+ self.initResults()
+ for package in self.treecache.getallnodes():
+ package_parts=package.split("/")
+ if package_parts:
+ if self.searchkey != "*":
+ if re.search(self.searchkey.lower(), package_parts[1].lower()):
+ self.packagematches.append(package)
+ else:
+ self.packagematches.append(package)
+
+ def output(self):
+ """Outputs the results of the search."""
+ print "[ Results for search key : "+white(self.searchkey)+" ]"
+ print "[ Applications found : "+white(str(len(self.packagematches)))+" ]"
+ print " "
+ for match in self.packagematches:
+ full_package = strip(self.treecache.dep_bestmatch(match))
+ if len(full_package) > 1:
+ print green("*")+" "+white(match)
+ print " ", "Latest version Available:",self.getVersion(full_package, search.VERSION_RELEASE)
+ print " ", self.getInstallationStatus(match)
+ print " ", "Description:",self.getDescription(self.getFullPath(match, full_package),self.getVersion(full_package, search.VERSION_SHORT))
+ print " "
+ else:
+ print green("*")+" "+white(match)+" "+red("[ Masked ]")
+ print " "
+
+ #
+ # private interface
+ #
+ def initResults(self):
+ self.packagematches = []
+
+ def getInstallationStatus(self,package):
+ installed_package = self.installcache.dep_bestmatch(package)
+ result = ""
+ version = self.getVersion(installed_package,search.VERSION_RELEASE)
+ if len(version) > 1:
+ result = "Latest version Installed: "+version
+ else:
+ result = "Latest version Installed: [ Not Installed ]"
+ return result
+
+ def getDescription(self,ebuildPath,packageVersion): ## Gets description from latest ebuild ##
+ file = open(ebuildPath)
+ result = "";
+ indescription=0
+ while 1:
+ data = file.readline()
+ if data:
+ if self.re_description.match(data.upper()):
+ indescription=1
+ p = self.re_description.split(data)
+ p = p[1].split('"')
+ result = p[0].strip()
+ if len(p)>1:
+ break
+ elif indescription==1:
+ if '"' in data:
+ p = data.split('"')
+ result = result+" "+p[0].strip()
+ indescription = 0
+ else:
+ result = result+" "+data.strip()
+ else:
+ break;
+ result = replace(result, "${PV}", packageVersion)
+ result = replace(result, "${pv}", packageVersion)
+ result = replace(result, "${description}", "KDE " + packageVersion + " ")
+ result = replace(result, "\n", "")
+ file.close()
+ # format and wrap the description text nicely
+ wraplength=60
+ formatted_result=""
+ while len(result)>wraplength:
+ lineposition=0
+ position=wraplength
+ while result[lineposition+position]!=' ' and position != 0:
+ position = position-1
+ if position==0:
+ position=wraplength
+ if len(formatted_result)==0:
+ formatted_result=result[:position]
+ else:
+ formatted_result=formatted_result+"\n "+result[:position]
+ result=result[position+1:]
+ if wraplength==60:
+ wraplength=73
+ formatted_result=formatted_result+"\n "+result
+ return formatted_result
+
+ def getFullPath(self,packageShortName,packageFullName): ## Returns the full path of the ebuild ##
+ absolute_path = '/usr/portage/' + strip(packageShortName)
+ package_parts = packageFullName.split("/")
+ result = absolute_path + "/" + package_parts[1] + ".ebuild"
+ return result
+
+ def getVersion(self,full_package,detail):
+ if len(full_package) > 1:
+ package_parts = portage.catpkgsplit(full_package)
+ if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
+ result = package_parts[2]+ "-" + package_parts[3]
+ else:
+ result = package_parts[2]
+ else:
+ result = ""
+ return result
+
+#build our package digraph
+def getsyslist():
+ if os.path.exists(portage.profiledir+"/packages"):
+ pfile=portage.profiledir+"/packages"
+ else:
+ print "!!! Couldn't find",portage.profiledir+"/packages;"
+ print "\"system\" mode unavailable."
+ sys.exit(1)
+ myfile=open(pfile,"r")
+ mylines=myfile.readlines()
+ myfile.close()
+
+ mynewlines=[]
+ for x in mylines:
+ myline=string.join(string.split(x))
+ if not len(myline):
+ continue
+ elif myline[0]=="#":
+ continue
+ elif myline[0]!="*":
+ continue
+ myline=myline[1:]
+ mynewlines.append(myline.strip())
+
+ return mynewlines
+
+class depgraph:
+
+ def __init__(self,mymode,myaction,myopts):
+ self.mymode=mymode
+ self.myaction=myaction
+ self.myopts=myopts
+ virts=portage.getvirtuals("/")
+ self.db={}
+ self.db["/"]={"virtuals":virts,"vartree":portage.vartree("/",virts),"porttree":portage.portagetree("/",virts),"bintree":portage.binarytree("/",virts)}
+ if portage.root!="/":
+ pr=portage.root
+ virts=portage.getvirtuals(pr)
+ self.db[pr]={"virtuals":virts,"vartree":portage.vartree(pr,virts),"porttree":portage.portagetree(pr,virts),"bintree":portage.binarytree(pr,virts)}
+ self.digraph=portage.digraph()
+ self.orderedkeys=[]
+ #the following is so we have an empty vartree (used in emerge update calculations)
+ self.emptytree=portage.vartree("/",virts,self.db["/"]["vartree"])
+ self.emptytree.tree={}
+ if "--emptytree" in myopts:
+ print "Running in empty tree mode"
+ self.db["/"]["vartree"].tree=self.emptytree.tree
+ self.db["/"]["vartree"].populated=1
+ self.db["/"]["vartree"].inject("virtual/glibc-1.0")
+ self.outdatedpackages=[]
+ def create(self,mybigkey,myparent=None,addme=1):
+ """creates the actual digraph of packages to merge. return 1 on success, 0 on failure
+ mybigkey = specification of package to merge; myparent = parent package (one depending on me);
+ addme = should I be added to the tree? (for the --onlydeps mode)"""
+ if mybigkey==None:
+ return
+ sys.stdout.write(".")
+ sys.stdout.flush()
+ if self.digraph.hasnode(mybigkey):
+ #if we've already hit this node before, we're already recursing on the dependencies.
+ #no need to recurse again.
+ if addme:
+ if myparent:
+ self.digraph.addnode(mybigkey,myparent)
+ return 1
+ mytype,myroot,mykey=string.split(mybigkey)
+ if "--noreplace" in self.myopts:
+ if self.db[myroot]["vartree"].exists_specific(mykey):
+ print "\n>>>",mykey,"already merged in",myroot+", skipping...\n"
+ return 1
+ if mytype=="binary":
+ if not self.db[portage.root]["bintree"].exists_specific(mykey):
+ print "\n\n!!!",mytype,mykey,"not found (possibly blocked by package.mask)\n"
+ sys.exit(1)
+ mypkgparts=portage.catpkgsplit(mykey)
+ mytbz2=xpak.tbz2(self.db[portage.root]["bintree"].getname(mykey))
+ edepend=["",string.join(mytbz2.getelements("RDEPEND")," "),mytbz2.getfile("SLOT",mypkgparts[2])]
+ elif mytype=="ebuild":
+ if not self.db[myroot]["porttree"].exists_specific(mykey):
+ print "\n\n!!!",mytype,mykey,"not found (possibly blocked by package.mask)\n"
+ sys.exit(1)
+ mydep={}
+ myebuild=self.db[myroot]["porttree"].getname(mykey)
+ edepend=portage.doebuild(myebuild,"depend",myroot,1,edebug)
+ if edepend==1:
+ print "!!! emerge aborting."
+ sys.exit(1)
+ elif mytype=="blocks":
+ edepend=None
+ parenttype,parentroot,parentkey=string.split(myparent)
+ mykeyparts=portage.catpkgsplit(mykey)
+ parentkeyparts=portage.catpkgsplit(parentkey)
+ # only add blocking deps that aren't from the same package that is installing
+ if mykeyparts[0]!=parentkeyparts[0] or mykeyparts[1]!=parentkeyparts[1]:
+ self.digraph.addnode(mybigkey,myparent)
+
+ if edepend:
+ mydep={}
+ if myroot=="/":
+ mydep["/"]=edepend[0]+" "+edepend[1]
+ else:
+ mydep["/"],mydep[myroot]=edepend
+ if addme:
+ self.digraph.addnode(mybigkey,myparent)
+ for dep in mydep.keys():
+ if "--update"==self.myaction:
+ mycheck=self.emptytree.depcheck(mydep[dep])
+ else:
+ mycheck=self.db[dep]["vartree"].depcheck(mydep[dep])
+ if mycheck[0]==0:
+ print "!!! depgraph.create() error: string format:",mydep
+ return 0
+ for x in mycheck[1]:
+ mynew=self.match(x,dep,mykey)
+ if not self.digraph.hasnode(mynew):
+ if addme:
+ if not self.create(mynew,mybigkey):
+ return 0
+ else:
+ if not self.create(mynew,None):
+ return 0
+ else:
+ self.digraph.addnode(mynew,mybigkey)
+
+ return 1
+
+ def altlist(self):
+ mygraph=self.digraph.copy()
+ dolist=["/"]
+ retlist=[]
+ for x in self.db.keys():
+ self.db[x]["merge"]=[]
+ if x not in dolist:
+ dolist.append(x)
+ while (not mygraph.empty()):
+ mycurkey=mygraph.firstzero()
+ if not mycurkey:
+ print "!!! Error: circular dependencies"
+ sys.exit(1)
+ splitski=string.split(mycurkey)
+ if "--update"==self.myaction:
+ if not self.db["/"]["vartree"].exists_specific(splitski[2]):
+ self.db["/"]["merge"].append(splitski)
+ else:
+ self.db[splitski[1]]["merge"].append(splitski)
+ mygraph.delnode(mycurkey)
+ for x in dolist:
+ for y in self.db[x]["merge"]:
+ retlist.append(y)
+ return retlist
+
+ def syscreate(self,mylines=[]):
+ for myline in mylines:
+ if "--update"==self.myaction or "--rebuild"==self.myaction:
+ self.create(self.match(myline,mykey="update (likely old /var/db/pkg entry)"))
+ else:
+ mycheck=self.db[portage.root]["vartree"].depcheck(myline)
+ if mycheck[0]==0:
+ print "\n!!! Warning:",myline,"has an invalid depstring\n"
+ continue
+ if mycheck[1]==None:
+ continue
+ for x in mycheck[1]:
+ self.create(self.match(myline,mykey="syscreate1"))
+
+ def match(self,mydep,myroot=portage.root,mykey=None):
+ # support mutual exclusive deps
+ mydep2=mydep
+ if mydep2[0]=="!":
+ mydep2=mydep[1:]
+
+ if self.myaction=="--rebuild":
+ myeb=self.db[portage.root]["vartree"].dep_bestmatch(mydep2)
+ if not self.db[portage.root]["porttree"].exists_specific(myeb):
+ self.outdatedpackages.append(myeb)
+ return None
+ else:
+ myeb=self.db[portage.root]["porttree"].dep_bestmatch(mydep2)
+ if not myeb:
+ if not mykey:
+ print "\n!!! Warning: couldn't find match for",mydep
+ else:
+ print "\n!!! Warning: couldn't find match for",mydep,"in",mykey
+ return None
+
+ # handle filtering of virtual deps for the rebuild action
+ if self.myaction=="--rebuild" and myeb[0:len("virtual")]=="virtual":
+ return None
+
+ # handle filtering of non slot packages
+ if "noslot" in mymode and self.db[portage.root]["vartree"].slotted(myeb)==1:
+ return None
+
+ if mydep[0]=="!":
+ myk="blocks "+myroot+" "+myeb
+ else:
+ if "--usepkg" in self.myopts:
+ mypk=self.db[portage.root]["bintree"].dep_bestmatch(mydep)
+ if myeb==mypk:
+ myk="binary "+portage.root+" "+mypk
+ else:
+ myk="ebuild "+myroot+" "+myeb
+ else:
+ myk="ebuild "+myroot+" "+myeb
+
+ return myk
+
+ def display(self,mylist):
+ for x in mylist:
+ if x[0]=="blocks":
+ addl=""+red("B")+" "
+ print "["+x[0]+" "+addl+"]",red(x[2])
+ else:
+ if self.db[x[1]]["vartree"].exists_specific(x[2]):
+ addl=" "+yellow("R")+" "
+ elif self.db[x[1]]["vartree"].exists_specific_cat(x[2]):
+ addl=" "+turquoise("U")+" "
+ else:
+ addl=" "+green("N")+" "
+ print "["+x[0]+" "+addl+"]",x[2],"to",x[1]
+
+ def outdated(self):
+ return self.outdatedpackages
+
+ def merge(self,mylist):
+ returnme=0
+ #check for blocking dependencies
+ for x in mylist:
+ if x[0]=="blocks":
+ print "\n!!! Error: the "+x[2]+" package conflicts with this package and both can't be installed on the same system together."
+ sys.exit(1)
+
+ #above line used by --fetchonly
+ for x in mylist:
+ myroot=x[1]
+ print ">>> emerge",x[2],"to",x[1]
+ #the last argument in the portage.doebuild() tells doebuild to *not* do dep checking
+ #(emerge is already handling that)
+ y=self.db[myroot]["porttree"].getname(x[2])
+ if x[0]=="ebuild":
+ if "--fetchonly" in self.myopts:
+ retval=portage.doebuild(y,"fetch",myroot,0,edebug)
+ if retval:
+ print
+ print "!!! Fetch for",y,"failed, continuing..."
+ print
+ returnme=1
+ elif "--buildpkg" in self.myopts:
+ #create pkg, then merge pkg
+ retval=portage.doebuild(y,"clean",myroot,0,edebug)
+ if retval:
+ print "!!! emerge aborting on ",y,"."
+ sys.exit(1)
+ retval=portage.doebuild(y,"package",myroot,0,edebug)
+ if retval:
+ print "!!! emerge aborting on ",y,"."
+ sys.exit(1)
+ #dynamically update our database
+ self.db[portage.root]["bintree"].inject(x[2])
+ mytbz2=self.db[portage.root]["bintree"].getname(x[2])
+ retval=portage.pkgmerge(mytbz2,myroot)
+ if retval==None:
+ print "!!! emerge aborting on ",y,"."
+ sys.exit(1)
+ else:
+ retval=portage.doebuild(y,"clean",myroot,0,edebug)
+ if retval:
+ print "!!! emerge aborting on ",y,"."
+ sys.exit(1)
+ retval=portage.doebuild(y,"merge",myroot,0,edebug)
+ if retval:
+ print "!!! emerge aborting on ",y,"."
+ sys.exit(1)
+ #dynamically update our database
+ elif x[0]=="binary":
+ #merge the tbz2
+ mytbz2=self.db[portage.root]["bintree"].getname(x[2])
+ retval=portage.pkgmerge(mytbz2,x[1])
+ if retval==None:
+ print "!!! emerge aborting on ",y,"."
+ sys.exit(1)
+ #need to check for errors
+ self.db[x[1]]["vartree"].inject(x[2])
+ if "--autoclean" in self.myopts:
+ retval=portage.doebuild(y,"clean",myroot,0,edebug)
+ if retval:
+ print "!!! emerge aborting on ",y,"."
+ sys.exit(1)
+ #my doing an exit this way, --fetchonly can continue to try to
+ #fetch everything even if a particular download fails.
+ if "--fetchonly" in self.myopts:
+ if returnme:
+ print "\n\n!!! Some fetch errors were encountered. Please see above for details.\n\n"
+ sys.exit(returnme)
+ else:
+ sys.exit(0)
+
+def post_emerge(retval=0):
+ auxpat=re.compile('^([^-]*)(-\d+)?\.info(-\d+)?(\.gz)?')
+ global myopts
+ print
+ if "--pretend" in myopts:
+ sys.exit(retval)
+ root=portage.root
+ if not os.path.isdir(root+"usr/share/info"):
+ print " "+root+"usr/share/info doesn't exist, skipping info regeneration."
+ elif not os.path.exists("/usr/bin/install-info"):
+ print " /usr/bin/install-info doesn't exist; skipping info regeneration."
+ else:
+ print " "+green("*")+" Regenerating GNU info directory index..."
+ if os.path.exists(root+"usr/share/info/dir"):
+ os.rename(root+"usr/share/info/dir",root+"usr/share/info/dir.old")
+ icount=0
+ badcount=0
+ for x in os.listdir(root+"usr/share/info"):
+ aux=auxpat.search(x)
+ if not aux:
+ continue
+ auxgroups=aux.groups()
+ if not (auxgroups[1] or auxgroups[2]):
+ myso=commands.getstatusoutput("/usr/bin/install-info --dir-file="+root+"usr/share/info/dir "+root+"usr/share/info/"+x)[1]
+ if myso!="":
+ print auxgroups
+ badcount=badcount+1
+ if "--verbose" in myopts:
+ print myso
+ icount=icount+1
+ if badcount:
+ if "--verbose" not in myopts:
+ print " "+yellow("*")+" Processed",icount,"info files:",badcount,"errors; type "+green("emerge --verbose")+" to view errors."
+ else:
+ print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
+
+ else:
+ print " "+green("*")+" Processed",icount,"info files."
+ if portage.settings["CONFIG_PROTECT"]:
+ #number of directories with some protect files in them
+ procount=0
+ for x in string.split(portage.settings["CONFIG_PROTECT"]):
+ if os.path.isdir(x):
+ a=commands.getstatusoutput("cd "+x+"; find -iname '._cfg????_*'")
+ if a[0]!=0:
+ print " "+red("*")+" error scanning",x
+ else:
+ files=string.split(a[1])
+ if files:
+ procount=procount+1
+ print " "+yellow("* IMPORTANT:")+"",len(files),"config files in",x,"need updating."
+ if procount:
+ print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+ print
+ sys.exit(retval)
+
+# general options that should be taken into account before any action
+if not portage.settings.has_key("MAINTAINER_noclean"):
+ if not "--autoclean" in myopts:
+ myopts.append("--autoclean")
+if "--debug" in myopts:
+ edebug=1
+
+# process modes that aren't in the universal emerge interface format first
+# this format is 'emerge --action --option --option [packageset]'
+if "rsync" in mymode and not myaction:
+ if not os.path.exists("/usr/bin/rsync"):
+ print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
+ sys.exit(1)
+ rclean=0
+ myportdir=portage.settings["PORTDIR"]
+ if myportdir[-1]=="/":
+ myportdir=myportdir[:-1]
+ if not os.path.exists(myportdir):
+ print ">>>",myportdir,"not found, creating it."
+ os.makedirs(myportdir,0755)
+ if "--clean" in myopts:
+ #we'll --delete files when we rsync
+ rclean=1
+ mycommand="/usr/bin/rsync -rlptDv --stats --progress "
+ if rclean:
+ mycommand=mycommand+"--delete --exclude='distfiles/*' --exclude='packages/*' "
+ mycommand=mycommand+"rsync://cvs.gentoo.org/gentoo-x86-portage/* "+myportdir
+ print ">>> starting rsync with cvs.gentoo.org..."
+ #protect users that did not set a default umask
+ os.umask(022)
+ sys.exit(os.system(mycommand))
+
+# HELP action
+elif "--help"==myaction:
+ if len(mymode)==0:
+ print
+ print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] [ "+green("options")+" ] [ "+turquoise("ebuildfile")+" | "+turquoise("tbz2file")+" | "+turquoise("dependency")+" ] ..."
+ print " "+turquoise("emerge")+" [ "+green("action")+" ] [ "+green("options")+" ] [ "+turquoise("system")+" | "+turquoise("world")+" | "+turquoise("noslot")+" ]"
+ print " "+turquoise("emerge")+" [ "+green("--clean")+" "+green("-c")+" ] "+turquoise("rsync")
+ print " "+turquoise("emerge")+" "+green("--help")+" "" "+green("-h")+" [ "+turquoise("rsync")+" | "+turquoise("system")+" | "+turquoise("world")+" | "+turquoise("noslot")+" | "+turquoise("config")+" ] "
+ print
+ print turquoise("Actions:")
+ print " "+green("--help")+" "+green("-h")
+ print " displays this help, an additional mode specifier provides"
+ print " detailed help about that mode instead"
+ print
+ print " "+green("--update")+" "+green("-u")
+ print " updates installed packages, this is typically used with",bold("world")
+ print " and",bold("system")
+ print
+ print " "+green("--zap")+" "+green("-z")
+ print " removes an installed package. the arguments can be in two"
+ print " different formats : /var/db/pkg/category/package-version"
+ print " or category/package."
+ print
+ print " "+green("--rebuild")+" "+green("-r")
+ print " forcably rebuild installed packages, this is typically used with"
+ print " "+bold("world"),"and",bold("system")
+ print
+ print " "+green("--search")+" "+green("-s")
+ print " searches for matches of the supplied string in the current local"
+ print " portage tree. The search string is a regular expression."
+ print " A few examples: "
+ print " "+bold("emerge --search \"^kde\"")
+ print " list all packages starting with kde"
+ print " "+bold("emerge --search \"gcc$\"")
+ print " list all packages ending with gcc"
+ print " "+bold("emerge --search \"\"")+" or"
+ print " "+bold("emerge --search \"*\"")
+ print " list all available packages "
+ print
+ print turquoise("Options:")
+ print " "+green("--autoclean")+" "+green("-a")
+ print " emerge normally cleans out the package-specific temporary"
+ print " build directory before it starts the building a package. With"
+ print " --autoclean, it will also clean the directory *after* the"
+ print " build completes. This option is automatically enabled for"
+ print " normal users, but maintainers can use this option to enable"
+ print " autocleaning."
+ print
+ print " "+green("--buildpkg")+" "+green("-b")
+ print " tell emerge to build binary packages for all ebuilds processed"
+ print " (in addition to actually merging the packages. Useful for"
+ print " maintainers or if you administrate multiple Gentoo Linux"
+ print " systems (build once, emerge tbz2s everywhere)."
+ print
+ print " "+green("--debug")+" "+green("-d")
+ print " Tell emerge to run the ebuild command in --debug mode. In this"
+ print " mode, the bash build environment will run with the -x option,"
+ print " causing it to output verbose debug information print to stdout."
+ print " --debug is great for finding bash syntax errors."
+ print
+ print " "+green("--fetchonly")+" "+green("-f")
+ print " Instead of doing any package building, just perform fetches for"
+ print " all packages (main package as well as all dependencies.)"
+ print
+ print " "+green("--onlydeps")+" "+green("-o")
+ print " Only merge (or pretend to merge) the dependencies of the"
+ print " specified packages, not the packages themselves."
+ print
+ print " "+green("--pretend")+" "+green("-p")
+ print " instead of actually performing the merge, simply display what"
+ print " ebuilds and tbz2s *would* have been installed if --pretend"
+ print " weren't used. Using --pretend is strongly recommended before"
+ print " installing an unfamiliar package. In the printout, N = new,"
+ print " U = upgrading, R = replacing"
+ print
+ print " "+green("--noreplace")+" "+green("-n")
+ print " Skip the packages specified on the command-line that have"
+ print " already been installed. Without this option, any packages,"
+ print " ebuilds, or deps you specify on on the command-line *will* cause"
+ print " Portage to remerge the package, even if it is already installed."
+ print " Note that Portage will never remerge dependencies automatically."
+ print
+ print " "+green("--usepkg")+" "+green("-k")
+ print " tell emerge to use binary packages (from $PKGDIR) if they are"
+ print " available, thus possibly avoiding some time-consuming compiles."
+ print " This option is useful for CD installs; you can export"
+ print " PKGDIR=/mnt/cdrom/packages and then use this option to have"
+ print " emerge \"pull\" binary packages from the CD in order to satisfy"
+ print " dependencies."
+ print
+ print " "+green("--verbose")+" "+green("-v")
+ print " Tell emerge to run in verbose mode. Currently, this causes"
+ print " emerge to print out GNU info errors, if any."
+ print
+ elif "rsync" in mymode:
+ print
+ print bold("Usage: ")+turquoise("emerge")+" [ "+green("--clean")+" "+green("-c")+" ] "+turquoise("rsync")
+ print
+ print " \"emerge rsync\" initiates an rsync update with cvs.gentoo.org,"
+ print " updating your Portage tree (typically in /usr/portage). This option"
+ print " will erase any changes that you have made to existing Portage files"
+ print " so be careful. \"emerge --clean rsync\" does the same thing as \"emerge"
+ print " rsync\", but files that no longer exist on our server are removed."
+ print
+ elif "system" in mymode:
+ print
+ print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] "+" [ "+green("options")+" ] "+turquoise("system")
+ print
+ print " \"emerge system\" is the Portage system update command. When run, it"
+ print " will scan the etc/make.profile/packages file and determine what"
+ print " packages need to be installed so that your system meets the minimum"
+ print " requirements of your current system profile. Note that this doesn't"
+ print " necessarily bring your system up-to-date at all; instead, it just"
+ print " ensures that you have no missing parts. For example, if your system"
+ print " profile specifies that you should have sys-apps/iptables installed"
+ print " and you don't, then \"emerge system\" will install it (the most"
+ print " recent version that matches the profile spec) for you. It's always a"
+ print " good idea to do an \"emerge --pretend system\" before an \"emerge"
+ print " system\", just so you know what emerge is planning to do."
+ print
+ elif "world" in mymode:
+ print
+ print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] "+" [ "+green("options")+" ] "+turquoise("world")
+ print
+ elif "noslot" in mymode:
+ print
+ print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] "+" [ "+green("options")+" ] "+turquoise("noslot")
+ print
+ elif "config" in mymode:
+ outstuff=green("Config file management support (preliminary)")+"""
+
+Portage has a special feature called "config file protection". The purpose of
+this feature is to prevent new package installs from clobbering existig
+configuration files. By default, config file protection is turned on for /etc
+and the KDE configuration dirs; more may be added in the future.
+
+When Portage installs a file into a protected directory tree like /etc, any
+existing files will not be overwritten. If a file of the same name already
+exists, Portage will change the name of the to-be- installed file from 'foo' to
+'._cfg0000_foo'. If '._cfg0000_foo' already exists, this name becomes
+'._cfg0001_foo', etc. In this way, existing files are not overwritten,
+allowing the administrator to manually merge the new config files and avoid any
+unexpected changes.
+
+In addition to protecting overwritten files, Portage will not delete any files
+from a protected directory when a package is unmerged. While this may be a
+little bit untidy, it does prevent potentially valuable config files from being
+deleted, which is of paramount importance.
+
+Protected directories are set using the CONFIG_PROTECT variable, normally
+defined in /etc/make.globals. Directory exceptions to the CONFIG_PROTECTed
+directories can be specified using the CONFIG_PROTECT_MASK variable. To find
+files that need to be updated in /etc, type:
+
+# find /etc -iname '._cfg????_*'
+
+You can disable this feature by setting CONFIG_PROTECT="" in /etc/make.conf.
+Then, Portage will mercilessly auto-update your config files. Alternatively,
+you can leave Config File Protection on but tell Portage that it can overwrite
+files in certain specific /etc subdirectories. For example, if you wanted
+Portage to automatically update your rc scripts and your wget configuration,
+but didn't want any other changes made without your explicit approval, you'd
+add this to /etc/make.conf:
+
+CONFIG_PROTECT_MASK="/etc/wget /etc/rc.d"
+
+"""
+ print outstuff
+
+# SEARCH action
+elif "--search"==myaction:
+ if not myfiles:
+ print
+ print "No search terms provided."
+ print
+ else:
+ searchinstance = search()
+ for mysearch in myfiles:
+ searchinstance.setKey(mysearch)
+ searchinstance.execute()
+ searchinstance.output()
+
+# ZAP action
+elif "--zap"==myaction:
+ if not myfiles and not "noslot" in mymode:
+ print
+ print "No packages to unmerge have been provided."
+ print
+ else:
+ full_paths={}
+ full_ebuild_paths={}
+ full_package_paths={}
+ non_slot_packages=[]
+
+ var_path=portage.root+"var/db/pkg"
+ if "noslot" in mymode:
+ localtree=portage.vartree(portage.root)
+ for x in localtree.getallnodes():
+ if localtree.slotted(x)==0:
+ mymatches=localtree.dep_match(x)
+ for package in mymatches:
+ myfullpaths=localtree.getebuildpaths(package)
+ for full_path in myfullpaths :
+ if not os.path.exists(full_path):
+ print "The ebuild '"+full_path+"' couldn't be found."
+ print "Your portage installation tree seems to be corrupted."
+ else:
+ full_package_paths[full_path]=package
+ else:
+ # process all arguments, verify if they can be resolved to an installed
+ # ebuild file and add the absolute paths of these ebuild to a list
+ for x in myfiles:
+
+ # an absolute path has been given
+ if (x[0]=='/'):
+ path_parts=split(x, '/')
+ if len(path_parts) != 6:
+ print "When providing an absolute path it should be"
+ print "in the following format : "+var_path+"/category/package"
+ print "The path '"+x+"' doesn't respect this."
+ sys.exit(1)
+ elif not os.path.exists(x):
+ print "The path '"+x+"' doesn't exist."
+ sys.exit(1)
+ elif -1 == find(x, var_path):
+ print "The path '"+x+"' didn't commence with '"+var_path+"'."
+ sys.exit(1)
+ else:
+ # check if the SLOT file is present, and get the package version
+ # from the PF file in that case
+ package_slot_path=strip(x)+"/SLOT"
+ package_pf_path=strip(x)+"/PF"
+ if os.path.exists(package_pf_path):
+ package_pf_file=open(package_pf_path)
+ package_pf=package_pf_file.readline().strip()
+ package_pf_file.close()
+ else:
+ package_pf=path_parts[5]
+ full_path=strip(x)+"/"+package_pf+".ebuild"
+ if not os.path.exists(full_path):
+ print "The ebuild '"+full_path+"' couldn't be found."
+ print "Your portage installation tree seems to be corrupted."
+ else:
+ path_parts=split(full_path, "/")
+ full_ebuild_paths[full_path]=path_parts[4]+"/"+package_pf
+
+ # a category and package name have been given
+ else:
+ localtree=portage.vartree(portage.root)
+ mymatches=localtree.dep_match(x)
+ # if no matches were found, try again by adding a '=' dep symbol if no
+ # dep symbols are already present
+ if not mymatches and x[0] not in ('<','>','=','~'):
+ mymatches=localtree.dep_match("="+x)
+
+ # only loops over the matches if they were found
+ if mymatches:
+ for package in mymatches:
+ myfullpaths=localtree.getebuildpaths(package)
+ for full_path in myfullpaths :
+ if not os.path.exists(full_path):
+ print "The ebuild '"+full_path+"' couldn't be found."
+ print "Your portage installation tree seems to be corrupted."
+ else:
+ full_package_paths[full_path]=package
+
+ # determine what the non slot packages are
+ if len(full_package_paths) > 0:
+ # determine the latest installed packages of each cat/pkg key
+ full_paths_keys=full_package_paths.keys()
+ # sort the ebuild paths
+ full_paths_keys.sort()
+ previous_package_set=None
+ for full_path in full_paths_keys:
+ # construct the key that will be used to determine when a new package set
+ # is being processed, the package slot is taken into account for this
+ package_parts=portage.pkgsplit(full_package_paths[full_path])
+ slot_path=dirname(full_path)+"/SLOT"
+ if not os.path.exists(slot_path):
+ package_slot=package_parts[1]
+ non_slot_packages.append(package_parts[0]+"-"+package_parts[1])
+
+ full_paths=full_ebuild_paths.keys()
+ full_paths.extend(full_package_paths.keys())
+
+ if len(full_paths)==0:
+ print "Couldn't find any matching installed packages."
+ sys.exit(1)
+ else:
+ if "--pretend" in myopts:
+ print
+ print "The are the packages that I would unmerge :"
+ print
+ else:
+ print
+ print "The following packages are going to be unmerged :"
+ print
+ # this makes revisions come before slot versions
+ # and therefor unmerges the older packages first
+ full_paths.sort()
+ for full_path in full_paths:
+ path_parts=split(full_path, "/")
+ print " "+path_parts[4]+"/"+path_parts[5]
+
+ if len(non_slot_packages)>0:
+ print
+ if "--verbose" not in myopts:
+ print " "+yellow("* IMPORTANT:"),len(non_slot_packages),"non slot packages; use "+green("--verbose")+" to view details."
+ else:
+ print " "+yellow("* IMPORTANT:"),len(non_slot_packages),"non slot packages"
+ print " "+yellow("*")+" These packages have been merged with an old version of portage that didn't"
+ print " "+yellow("*")+" support binary compatibility slots. This means that each package with a"
+ print " "+yellow("*")+" different version number will be considered different and only older versions"
+ print " "+yellow("*")+" of different releases will be unmerged automatically."
+ print " "+yellow("*")+" To get rid of all non slot packages, you can rebuild your system with"
+ print " "+yellow("*")+" "+green("emerge --noslot rebuild")+"."
+ print
+ for non_slot_package in non_slot_packages:
+ print " "+non_slot_package
+
+ if "--pretend" in myopts:
+ print
+ else:
+ secs=string.atoi(portage.settings["UNMERGE_DELAY"])
+ if secs > 0:
+ print
+ print "Waiting",secs,"seconds to make sure that you want these"
+ print "packages to be removed ..."
+ while secs > 0:
+ sys.stdout.write(str(secs)+" ")
+ sys.stdout.flush()
+ time.sleep(1)
+ secs = secs-1
+ print secs
+ for full_path in full_paths:
+ print "Unmerging "+os.path.basename(full_path)+" ..."
+ retval=portage.doebuild(full_path,"unmerge",portage.root,0,edebug)
+ post_emerge()
+
+# REBUILD action
+elif "--rebuild"==myaction:
+ if not "system" in mymode and not "world" in mymode and not "noslot" in mymode:
+ print
+ print " "+red("* WARNING:"),green("emerge --rebuild"),"shouldn't be used for regular packages"
+ print " "+red("*"),"it's only intended to be used with",green("system")+", "+green("world")+", and",green("noroot")
+ print
+ else:
+ if "--pretend" in myopts:
+ print
+ print "These are the packages that I would rebuild, in order."
+ print
+
+ if "system" in mymode:
+ mydepgraph=depgraph(mymode,myaction,myopts)
+ print "Calculating system dependencies",
+ mydepgraph.syscreate(getsyslist())
+ print " done!"
+ elif "world" in mymode or "noslot" in mymode:
+ mydepgraph=depgraph(mymode,myaction,myopts)
+ print "Calculating world dependencies",
+ mydepgraph.syscreate(mydepgraph.db["/"]["vartree"].getallnodes())
+ print " done!"
+
+ if "--pretend" in myopts:
+ mydepgraph.display(mydepgraph.altlist())
+
+ myoutdated=mydepgraph.outdated()
+ if len(myoutdated):
+ if "--verbose" not in myopts:
+ print
+ print " "+yellow("* IMPORTANT:"),len(myoutdated),"packages aren't available anymore; use "+green("--verbose")+" for details."
+ else:
+ print
+ print " "+yellow("* IMPORTANT:"),len(myoutdated),"packages aren't available anymore"
+ print " "+yellow("*")+" Your portage tree doesn't contain the ebuilds anymore that correspond to the"
+ print " "+yellow("*")+" following packages. This means that portage is unable to rebuild them."
+ print " "+yellow("*")+" Instead you should upgrade to the latest versions or install possible"
+ print " "+yellow("*")+" alternative packages that provide the same functionalities."
+ myoutdated.sort()
+ for mypackage in myoutdated:
+ print " "+mypackage
+ else:
+ mydepgraph.merge(mydepgraph.altlist())
+ post_emerge()
+
+# INSTALL and UPDATE action
+elif "--update"==myaction or not myaction:
+ if not myaction and "world" in mymode:
+ print
+ print " "+red("* WARNING:"),green("emerge world"),"can't be used without an action"
+ print " "+red("*"),green("world"),"is only intended to be used with",green("emerge --update")
+ print
+ else:
+ if "--pretend" in myopts:
+ print
+ print "These are the packages that I would merge, in order."
+ print
+
+ if "system" in mymode:
+ mydepgraph=depgraph(mymode,myaction,myopts)
+ print "Calculating system dependencies",
+ mydepgraph.syscreate(getsyslist())
+ print " done!"
+ elif "world" in mymode:
+ mydepgraph=depgraph(mymode,myaction,myopts)
+ print "Calculating world dependencies",
+ mydepgraph.syscreate(mydepgraph.db["/"]["vartree"].getallnodes())
+ print " done!"
+ elif "noslot" in mymode:
+ mydepgraph=depgraph(mymode,myaction,myopts)
+ print "Calculating noslot dependencies",
+ mydepgraph.syscreate(mydepgraph.db["/"]["vartree"].getallnodes())
+ print " done!"
+ else:
+ mydepgraph=depgraph(mymode,myaction,myopts)
+ if not myfiles:
+ post_emerge()
+ #we don't have any files to process; skip this step and exit
+ print "Calculating dependencies",
+ for mypkg in myfiles:
+ if mypkg[-5:]==".tbz2":
+ mytype="binary"
+ mytbz2=xpak.tbz2(mypkg)
+ mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(mypkg)[:-5]
+ elif mypkg[-7:]==".ebuild":
+ mytype="ebuild"
+ mykey=os.path.basename(os.path.abspath(mypkg+"/../.."))+"/"+os.path.basename(mypkg)[:-7]
+ else:
+ mykey=""
+ if "--usepkg" in myopts:
+ mykey=mydepgraph.db[portage.root]["bintree"].dep_bestmatch(mypkg)
+ mytype="binary"
+ if not mykey:
+ mykey=mydepgraph.db[portage.root]["porttree"].dep_bestmatch(mypkg)
+ mytype="ebuild"
+ if not mykey:
+ print "!!! Couldn't find match for",mypkg+"; aborting."
+ sys.exit(1)
+ # else:
+ # print "!!! Error:",x,"is neither an ebuild nor a .tbz2 package."
+ # sys.exit(1)
+ mydepgraph.create(mytype+" "+portage.root+" "+mykey,None,"--onlydeps" not in myopts)
+ print " done!"
+
+ if "--pretend" in myopts:
+ mydepgraph.display(mydepgraph.altlist())
+ else:
+ mydepgraph.merge(mydepgraph.altlist())
+ post_emerge()
+
diff --git a/src/bsd-flags/PKG-INFO b/src/bsd-flags/PKG-INFO
new file mode 100644
index 00000000..f2cb5c58
--- /dev/null
+++ b/src/bsd-flags/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: bsd-chflags
+Version: 0.1
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: Stephen Bennett
+Author-email: spb@gentoo.org
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/src/bsd-flags/chflags.c b/src/bsd-flags/chflags.c
new file mode 100644
index 00000000..77b89a28
--- /dev/null
+++ b/src/bsd-flags/chflags.c
@@ -0,0 +1,161 @@
+/* $Header: /var/cvsroot/gentoo-src/portage/src/bsd-flags/chflags.c,v 1.1.2.2 2005/02/13 10:48:31 jstubbs Exp $ */
+
+#include "Python.h"
+
+#include <sys/stat.h>
+
+static char chflags_lchflags__doc__[];
+static PyObject * chflags_lchflags(PyObject *self, PyObject *args);
+static char chflags_lgetflags__doc__[];
+static PyObject * chflags_lgetflags(PyObject *self, PyObject *args);
+static char chflags_lhasproblems__doc__[];
+static PyObject * chflags_lhasproblems(PyObject *self, PyObject *args);
+
+static char chflags__doc__[] = "Provide some operations for manipulating" \
+ "FreeBSD's filesystem flags";
+
+static PyMethodDef chflags_methods[] = {
+ {"lchflags", chflags_lchflags, METH_VARARGS, chflags_lchflags__doc__},
+ {"lgetflags", chflags_lgetflags, METH_VARARGS, chflags_lgetflags__doc__},
+ {"lhasproblems", chflags_lhasproblems, METH_VARARGS, chflags_lhasproblems__doc__},
+ {NULL, NULL}
+};
+
+static char chflags_lchflags__doc__[] =
+"lchflags(path, flags) -> None\n\
+Change the flags on path to equal flags.";
+
+static char chflags_lgetflags__doc__[] =
+"lgetflags(path) -> Integer\n\
+Returns the file flags on path.";
+
+static char chflags_lhasproblems__doc__[] =
+"lhasproblems(path) -> Integer\n\
+Returns 1 if path has any flags set that prevent write operations;\n\
+0 otherwise.";
+
+static const unsigned long problemflags=0x00160016;
+
+#if defined __FreeBSD__
+static PyObject *chflags_lchflags(PyObject *self, PyObject *args)
+{
+ char *path = NULL;
+ int flags;
+ int res;
+
+ if (!PyArg_ParseTuple(args, "eti:lchflags",
+ Py_FileSystemDefaultEncoding, &path,
+ &flags))
+ {
+ return NULL;
+ }
+
+ res = lchflags(path, flags);
+
+ PyMem_Free(path);
+ return PyInt_FromLong((long)res);
+}
+
+static PyObject *chflags_lhasproblems(PyObject *self, PyObject *args)
+{
+ char *path = NULL;
+ struct stat sb;
+ int res;
+
+ if (!PyArg_ParseTuple(args, "et:lhasproblems",
+ Py_FileSystemDefaultEncoding, &path))
+ {
+ return NULL;
+ }
+
+ res = lstat(path, &sb);
+
+ PyMem_Free(path);
+
+ if (res < 0)
+ {
+ return PyInt_FromLong((long)res);
+ }
+
+ if (sb.st_flags & problemflags)
+ return PyInt_FromLong(1);
+ else
+ return PyInt_FromLong(0);
+}
+
+static PyObject *chflags_lgetflags(PyObject *self, PyObject *args)
+{
+ char *path = NULL;
+ struct stat sb;
+ int res;
+
+ if (!PyArg_ParseTuple(args, "et:lgetflags",
+ Py_FileSystemDefaultEncoding, &path))
+ {
+ return NULL;
+ }
+
+ res = lstat(path, &sb);
+
+ if (res < 0)
+ {
+ PyMem_Free(path);
+ return PyInt_FromLong((long)res);
+ }
+
+ PyMem_Free(path);
+
+ return PyInt_FromLong((long)sb.st_flags);
+}
+
+#else
+#warning Not on FreeBSD; building dummy lchflags
+
+static PyObject *chflags_lgetflags(PyObject *self, PyObject *args)
+{
+ /* Obviously we can't set flags if the OS/filesystem doesn't support them. */
+ return PyInt_FromLong(0);
+}
+
+static PyObject *chflags_lchflags(PyObject *self, PyObject *args)
+{
+ /* If file system flags aren't supported, just return 0,
+ as the effect is basically the same. */
+ return PyInt_FromLong(0);
+}
+
+static PyObject *chflags_lhasproblems(PyObject *self, PyObject *args)
+{
+ return PyInt_FromLong(0);
+}
+
+#endif
+
+static int ins(PyObject *m, char *symbolname, int value)
+{
+ return PyModule_AddIntConstant(m, symbolname, value);
+}
+
+DL_EXPORT(void) initchflags(void)
+{
+ PyObject *m;
+ m = Py_InitModule4("chflags", chflags_methods, chflags__doc__,
+ (PyObject*)NULL, PYTHON_API_VERSION);
+
+ ins(m, "UF_SETTABLE", 0x0000ffff);
+ ins(m, "UF_NODUMP", 0x00000001);
+ ins(m, "UF_IMMUTABLE", 0x00000002);
+ ins(m, "UF_APPEND", 0x00000004);
+ ins(m, "UF_OPAQUE", 0x00000008);
+ ins(m, "UF_NOUNLINK", 0x00000010);
+
+ ins(m, "SF_SETTABLE", 0xffff0000);
+ ins(m, "SF_NODUMP", 0x00010000);
+ ins(m, "SF_IMMUTABLE", 0x00020000);
+ ins(m, "SF_APPEND", 0x00040000);
+ ins(m, "SF_OPAQUE", 0x00080000);
+ ins(m, "SF_NOUNLINK", 0x00100000);
+ ins(m, "SF_SNAPSHOT", 0x00200000);
+
+ ins(m, "PROBLEM_FLAGS", 0x00160016);
+}
diff --git a/src/bsd-flags/setup.cfg b/src/bsd-flags/setup.cfg
new file mode 100644
index 00000000..7bb13404
--- /dev/null
+++ b/src/bsd-flags/setup.cfg
@@ -0,0 +1,6 @@
+# bsd-flags
+# $Header: /var/cvsroot/gentoo-src/portage/src/bsd-flags/setup.cfg,v 1.1.2.1 2005/02/06 12:56:40 carpaski Exp $
+
+[bdist_rpm]
+release = 1
+python=python2
diff --git a/src/bsd-flags/setup.py b/src/bsd-flags/setup.py
new file mode 100755
index 00000000..6f4a12ba
--- /dev/null
+++ b/src/bsd-flags/setup.py
@@ -0,0 +1,24 @@
+#! /usr/bin/env python
+# $Header: /var/cvsroot/gentoo-src/portage/src/bsd-flags/setup.py,v 1.1.2.1 2005/02/06 12:56:40 carpaski Exp $
+
+from os import chdir, stat
+from distutils.core import setup, Extension
+
+setup (# Distribution meta-data
+ name = "bsd-chflags",
+ version = "0.1",
+ description = "",
+ author = "Stephen Bennett",
+ author_email = "spb@gentoo.org",
+ license = "",
+ long_description = \
+ '''''',
+ ext_modules = [ Extension(
+ "chflags",
+ ["chflags.c"],
+ libraries=[],
+ )
+ ],
+ url = "",
+ )
+
diff --git a/src/python-missingos/ChangeLog b/src/python-missingos/ChangeLog
new file mode 100644
index 00000000..1c80b2e6
--- /dev/null
+++ b/src/python-missingos/ChangeLog
@@ -0,0 +1,16 @@
+# $Header: /var/cvsroot/gentoo-src/portage/src/python-missingos/ChangeLog,v 1.4 2003/03/22 14:24:38 carpaski Exp $
+
+python-missingos ChangeLog
+Jonathon D Nelson <jnelson@gentoo.org>
+2 April 2002
+
+ 2 April 2002 14:15 jnelson
+ * Add optional 'mode' parameter to mknod
+ * Change from missingosmodule to missingos.
+ * Add some __doc__ entries
+ * Remove stupid hack for Python 1.5.2 support,
+ 1.5.2 doesn't have Py_FileSystemDefaultEncoding anyway.
+ * Return description of error when mode not p,b,c,u in mknod
+
+ 2 April 2002 12:10 jnelson
+ * Populate files
diff --git a/src/python-missingos/PKG-INFO b/src/python-missingos/PKG-INFO
new file mode 100644
index 00000000..cb8087f4
--- /dev/null
+++ b/src/python-missingos/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: python-missingos
+Version: 0.2
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: Jonathon D Nelson
+Author-email: jnelson@gentoo.org
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/src/python-missingos/README b/src/python-missingos/README
new file mode 100644
index 00000000..de3467d5
--- /dev/null
+++ b/src/python-missingos/README
@@ -0,0 +1,15 @@
+# $Header: /var/cvsroot/gentoo-src/portage/src/python-missingos/README,v 1.5.2.1 2004/10/22 16:53:30 carpaski Exp $
+
+python-missingos
+Jonathon D Nelson <jnelson@gentoo.org>
+2 April 2002
+
+INTRO
+=====
+This module provides some missing file operations that don't
+seem to be provided by the standard os and posix modules.
+This list currently includes lchown and mknod.
+
+COPYRIGHT
+=========
+GPL
diff --git a/src/python-missingos/missingos.c b/src/python-missingos/missingos.c
new file mode 100644
index 00000000..cbcde5bf
--- /dev/null
+++ b/src/python-missingos/missingos.c
@@ -0,0 +1,120 @@
+/* $Header: /var/cvsroot/gentoo-src/portage/src/python-missingos/missingos.c,v 1.5.2.1 2004/10/22 16:53:30 carpaski Exp $ */
+
+#include "Python.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+static char missingos_lchown__doc__[];
+static PyObject * missingos_lchown(PyObject *self, PyObject *args);
+static char missingos_mknod__doc__[];
+static PyObject * missingos_mknod(PyObject *self, PyObject *args);
+
+static char missingos__doc__[] = "Provide some operations that\
+ are missing from the standard os / posix modules.";
+
+static PyMethodDef missingos_methods[] = {
+ {"lchown", missingos_lchown, METH_VARARGS, missingos_lchown__doc__},
+ {"mknod", missingos_mknod, METH_VARARGS, missingos_mknod__doc__},
+ {NULL, NULL} /* sentinel */
+};
+
+static PyObject *
+posix_error_with_allocated_filename(char* name)
+{
+ PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
+ PyMem_Free(name);
+ return rc;
+}
+
+static char missingos_lchown__doc__[] =
+"lchown(path, uid, gid) -> None\n\
+Change the owner and group id of path to the numeric uid and gid.";
+
+static PyObject *
+missingos_lchown(PyObject *self, PyObject *args) {
+ char *path = NULL;
+ int uid, gid;
+ int res;
+ if (!PyArg_ParseTuple(args, "etii:lchown",
+ Py_FileSystemDefaultEncoding, &path,
+ &uid, &gid))
+ return NULL;
+ res = lchown(path, (uid_t) uid, (gid_t) gid);
+ if (res < 0)
+ return posix_error_with_allocated_filename(path);
+ PyMem_Free(path);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char missingos_mknod__doc__[] =
+"mknod(path, type, major, minor [, mode=0600 ]) -> None\n\
+Create a special file. Mode fixed at 0600.\
+Note that for type 'p' major and minor are ignored.\
+";
+
+static PyObject *
+missingos_mknod(PyObject *self, PyObject *args) {
+ char *path = NULL;
+ char *type = NULL;
+ int major = 0;
+ int minor = 0;
+ mode_t real_mode;
+ dev_t real_dev;
+ int mode = 0600;
+
+ int res;
+ if (!PyArg_ParseTuple(args, "etsii|i:mknod",
+ Py_FileSystemDefaultEncoding, &path,
+ &type, &major, &minor, &mode))
+ return NULL;
+ /* type can be *one* of b, c, u, p */
+ /* major/minor are forbidden for p, reqd otherwise */
+ if (!strcmp(type, "p")) {
+ /* pipe */
+ if (major != 0 || minor != 0) {
+ return NULL;
+ }
+ real_mode = S_IFIFO;
+ major = 0;
+ minor = 0;
+ } else if (!strcmp(type, "b")) {
+ /* block */
+ real_mode = S_IFBLK;
+ } else if (!strcmp(type, "c")) {
+ real_mode = S_IFCHR;
+ /* char */
+ } else if (!strcmp(type, "u")) {
+ real_mode = S_IFCHR;
+ /* unbuffered char */
+ } else {
+ /* error */
+ PyErr_SetString(PyExc_ValueError, "type must be one of p,b,c,u");
+ return NULL;
+ }
+
+ real_mode |= mode;
+ real_dev = (major << 8) | minor;
+
+ /* use mode to modify real_mode */
+
+ res = mknod(path, real_mode, real_dev);
+ if (res < 0)
+ return posix_error_with_allocated_filename(path);
+ PyMem_Free(path);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+DL_EXPORT(void)
+initmissingos(void) {
+ PyObject *m;
+
+ m = Py_InitModule4("missingos", missingos_methods,
+ missingos__doc__, (PyObject *)NULL,
+ PYTHON_API_VERSION);
+}
diff --git a/src/python-missingos/setup.cfg b/src/python-missingos/setup.cfg
new file mode 100644
index 00000000..8677f66f
--- /dev/null
+++ b/src/python-missingos/setup.cfg
@@ -0,0 +1,8 @@
+# python-missingos
+# $Header: /var/cvsroot/gentoo-src/portage/src/python-missingos/setup.cfg,v 1.4.2.1 2004/10/22 16:53:30 carpaski Exp $
+
+[bdist_rpm]
+release = 1
+doc_files = ChangeLog
+ README
+python=python2
diff --git a/src/python-missingos/setup.py b/src/python-missingos/setup.py
new file mode 100755
index 00000000..b82e3e51
--- /dev/null
+++ b/src/python-missingos/setup.py
@@ -0,0 +1,24 @@
+#! /usr/bin/env python2.2
+# $Header: /var/cvsroot/gentoo-src/portage/src/python-missingos/setup.py,v 1.5.2.1 2004/10/22 16:53:30 carpaski Exp $
+
+from os import chdir, stat
+from distutils.core import setup, Extension
+
+setup (# Distribution meta-data
+ name = "python-missingos",
+ version = "0.2",
+ description = "",
+ author = "Jonathon D Nelson",
+ author_email = "jnelson@gentoo.org",
+ license = "",
+ long_description = \
+ '''''',
+ ext_modules = [ Extension(
+ "missingos",
+ ["missingos.c"],
+ libraries=[],
+ )
+ ],
+ url = "",
+ )
+
diff --git a/src/sandbox-1.1/ChangeLog b/src/sandbox-1.1/ChangeLog
new file mode 100644
index 00000000..8da8ec9f
--- /dev/null
+++ b/src/sandbox-1.1/ChangeLog
@@ -0,0 +1,265 @@
+# ChangeLog for Path Sandbox
+# Copyright 1999-2004 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/ChangeLog,v 1.37.2.3 2004/12/01 22:14:09 carpaski Exp $
+
+ 01 Dec 2004; Nicholas Jones <carpaski@gentoo.org> libsandbox.c, sandbox.c:
+ Added ferringb's code to handle the sandbox pid overflow problem.
+
+ 07 Nov 2004; Brian Harring <ferringb@gentoo.org> libsandbox.c: c99 standard
+ allowing data and code mixing in code isn't available for gcc 2.95- should fix
+ bug #70351.
+
+ 03 Nov 2004; Brian Harring <ferringb@gentoo.org> libsandbox.c, sandbox_futils.c:
+ Fixups, and a hole closed regarding verifying SANDBOX_(|DEBUG_)LOG is sane.
+
+ 02 Aug 2004; Nicholas Jones <carpaski@gentoo.org> libsandbox.c: Code from
+ Seth Robertson that tracked down all adjuct flags for read operations that
+ do not invoke a write operation.
+
+ 04 Apr 2004; Nicholas Jones <carpaski@gentoo.org> libsandbox.c, sandbox.c:
+ Another fix from jstubbs regarding a free() on a stack variable for the
+ environment -- tracking now prevents extraneous free()'s segfault.
+
+ 04 Apr 2004; Nicholas Jones <carpaski@gentoo.org> libsandbox.c, sandbox.c:
+ J. Stubbs tracked down a new bug where mkdir was failing to the patch on
+ the lstat in mkdir... it now only returns 0 or -1 as documented for mkdir.
+ Also remove the errno = ESUCCESS settings as documentation points out that
+ a library isn't allowed to do that.
+
+ 04 Apr 2004; Nicholas Jones <carpaski@gentoo.org> libsandbox.c: Added a
+ file_security_check() function to check random potential exploits on files
+ that sandbox is to load and read -- Normally sandboxpids.tmp. This fixes
+ the 'system-crippling' exploits (bug 21923) and catches a few other
+ potential problems.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> Makefile: Updates for
+ 32/64 bit sandbox. Made CC and LD '?=' values to allow passed in CC to work.
+
+ 20 Mar 2004; Nicholas Jones <carpaski@gentoo.org> libsandbox.c:
+ bug 42048 -- Fixed the lstat/errno conditions for mkdir <caleb@g.o>.
+ Added the 64/32 bit sandbox patch for AMD64 bug 32963 <brad/azarah>.
+
+ 29 Feb 2004; Martin Schlemmer <azarah@gentoo.org> sandbox.c, sandbox_futils.c :
+ Fix permissions and group of pids file and logs. Permissions should be 0664
+ and group should be 'portage'. Bug #34260.
+
+ 28 Feb 2004; Martin Schlemmer <azarah@gentoo.org> libsandbox.c :
+ Besides a small cleanup, redo how we replace LD_PRELOAD in the environ passed
+ to the real execve (in our execve wrapper). Seems that on some arches (sparc
+ among others) do not allow us to tamper with the readonly copy passed to
+ execve, so pass our own copy of the environment. Bug #42290.
+
+ 11 Jan 2004; Nicholas Jones <carpaski@gentoo.org> create-decls:
+ Changed tail to head and added a notice about duration of glibc check.
+
+ 21 Dec 2003; Nicholas Jones <carpaski@gentoo.org> create-decls:
+ Changed the glibc subversion check to use /usr/bin/* instead of /bin/sh
+ as there isn't a guarentee that it is dynamic.
+
+ 02 Nov 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c :
+ If 'file' passed to before_syscall(const char *func, const char *file) is
+ invalid, we should set errno to ENOENT, and not EINVAL. This should
+ close bug #32238.
+
+ 14 Oct 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c :
+ Fix a bug that occurs mainly on 64bit arch, where the file passed to
+ the functions we wrap, is invalid, and then cause canonicalize to pass
+ garbage to before_syscall(), thanks to great detective work from
+ Andrea Luzzardi <al@sig11.org> (bug #29846).
+
+ 13 Oct 2003; Martin Schlemmer <azarah@gentoo.org> create-localdecls :
+ Add a uClibc detection patch from Peter S. Mazinger <ps.m@gmx.net>.
+
+ 13 Oct 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c :
+ Fix a bug in libsandbox.c 's checking in the rename wrapper - it basically
+ only checked the destination patch, and not the source, so we could move
+ a protected file to a unprotected directory, and then delete/modify it.
+ Thanks to Andrea Luzzardi (scox) <al@sig11.org>, bug #30992, for this fix.
+
+ 12 Oct 2003; Nicholas Jones <carpaski@gentoo.org> sandbox.c :
+ Added python2.3 to the predict section/variable.
+
+ 28 Sep 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c, sandbox.c,
+ sandbox.h, sandbox_futils.c :
+ Add support to set the pids file via SANDBOX_PIDS_FILE at startup. If
+ it is not set, it will revert to its old value.
+
+ 27 Sep 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c :
+ Fix our mkdir wrapper to check if the dir exist, and return EEXIST if so,
+ rather than failing with a violation, bug #29748.
+
+ 27 Jul 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c :
+ Fix canonicalize() to ignore calls with path = "".
+
+ 27 Jul 2003; Martin Schlemmer <azarah@gentoo.org> getcwd.c, libsandbox.c,
+ sandbox_futils.c, canonicalize.c :
+ Once again coreutils fails, as my systems had 2.5 kernel, the getcwd system
+ call handled strings larger than PATH_MAX (bug #21766). It however does not
+ work the same on 2.4 kernels.
+
+ To fix, I added the posix implementation of getcwd() (from glibc cvs) that
+ do not need the system call. We use the default getcwd() function via a
+ wrapper (egetcwd), and then lstat the returned path. If lstat fails, it
+ means the current directory was removed, OR that the the system call for
+ getcwd failed (curious is that it do not fail and return NULL or set
+ errno, but rather just truncate the retured directory - usually from the
+ start), and if so, we use the generic getcwd() function (__egetcwd). Note
+ that we do not use the generic version all the time, as it calls lstat()
+ a great number of times, and performance degrade much.
+
+ 29 Jun 2003; Martin Schlemmer <azarah@gentoo.org> create-localdecls,
+ libsandbox.c :
+ Make sure SB_PATH_MAX will not wrap. Fix two possible memory leaks.
+
+ 22 Jun 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c, canonicalize.c
+ create-localdecls :
+ When checking path names of files accessed, we need to canonicalize it, else
+ it may be a symlink in a 'write allowed' directory pointing to a file in a
+ directory we should not have write access to.
+
+ With something like coreutils-5.0, we have two problems:
+ 1) One of the tests checks if getcwd() can return a path longer than
+ PATH_MAX. This test then tries to create a dir which even while
+ created local (mkdir("conftest2")), it ends up being resolved with
+ a name that is much larger than PATH_MAX. The problem now is that
+ canonicalize() have undefined behaviour when the path was too long
+ (returned wrongly truncated paths, etc), and pass the wrong path to
+ before_syscall() (causing the bogus sandbox violations).
+ 2) The ecanonicalize() function we used, along with the canonicalize()
+ function did not support longer than PATH_MAX. This is partly a
+ cause for 1), but the error checking (rather lack of it) of calls
+ to erealpath() in canonicalize() was the prime reason for 1).
+
+ As we do not use this canonicalized name to call the function, we resolve this
+ by fixing canonicalize() to do better error checking, and ecanonicalize() as
+ well as all functions in libsandbox.c to use a PATH_MAX of 'PATH_MAX * 2'.
+ While they will resolve paths properly now, and can check if a write/read is
+ allowed, the functions called from the sandboxed environment will still work
+ as expected.
+
+ This should resolve bug #21766.
+
+ 06 Apr 2003; Martin Schlemmer <azarah@gentoo.org> libsandbox.c :
+ For some reason sandbox fails with a 'open_wr' if you run 'locale -a' under
+ it (bug #16298).
+
+ Problem is that for some reason locale fopen's locale.alias with mode "rm".
+
+ -------------------------------------------------------
+ nosferatu root # grep fopen locale.log
+ fopen("/usr/share/locale/locale.alias", "rm"ACCESS DENIED open_wr: /usr/share/locale/locale.alias
+ nosferatu root #
+ --------------------------------------------------------
+
+ I checked the source of locale, but it have fopen with mode 'r', so
+ not sure where the "rm" mode comes from. Anyhow, changed the check in
+ before_syscall_open_char() to also see mode "rm" as readonly.
+
+ 23 Feb 2003; Martin Schlemmer <azarah@gentoo.org> create-localdecls :
+
+ Add glibc-2.3 support.
+
+ 22 Feb 2003; Martin Schlemmer <azarah@gentoo.org> sandbox.c :
+
+ Some /etc/ld.so.preload fixes. Just changed the #if defines to cover all
+ operations releated to preload, as well as only try to modify ld.so.preload
+ if we can. Also modify to write the pid to /tmp/sandboxpids.tmp even when
+ not using ld.so.preload. Fix to not write this instance of sandbox's pid
+ to /tmp/sandboxpids.tmp on exit if this is not the last sandbox running.
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> Makefile :
+
+ Changed the LD to CC for hppa.
+
+ 22 Feb 2003; Nicholas Jones <carpaski@gentoo.org> create-localdecls :
+
+ Killed the previous changes I made.
+
+ 17 Feb 2003; Nicholas Jones <carpaski@gentoo.org> create-localdecls :
+
+ Added parisc to BROKEN_RTLD_ARCHLIST to see if it we can fix the relocation probs.
+
+ 09 Jan 2003; J Robert Ray <jrray@gentoo.org> sandbox.c :
+
+ Don't segfault if $HOME isn't set, set $HOME to "/" instead. Fixes bug 10868.
+
+ 16 Dec 2002; Martin Schlemmer <azarah@gentoo.org> create-localdecls :
+
+ Fix memory leak for mips, bug #12236. Thanks to Torgeir Hansen <torgeir@trenger.ro>
+ for this fix.
+
+ 4 Dec 2002; J Robert Ray <jrray@gentoo.org> sandbox.h sandbox_futils.c :
+
+ sandbox_futils defined a dirname() function that was masking the same
+ function in glibc and was broken (e.g.: SANDBOX_DIR was being set to
+ '/usr/lib/portage/bi/'). Fixed function to return expected results and
+ renamed it to sb_dirname() to no longer mask the glibc function. Closes bug
+ 11231.
+
+ 4 Dec 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Fix a segfault in libsandbox.c if canonicalize() was called with
+ first parameter = NULL.
+
+ 1 Sep 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Fix my braindead 'return 1;' in a void function. Updated sandbox.c,
+ cleanup() for this.
+
+ Change cleanup() in sandbox.c not to exit with fail status if
+ the pidsfile is missing. We really should still display sandbox
+ violations if they occured.
+
+ 31 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Update cleanup() in sandbox.c to remove the PIDSFILE if this is
+ the last sandbox running.
+
+ 25 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Major cleanups to mainly libsandbox.c again.
+
+ 22 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Add copyrights to sandbox.h and sandbox_futils.h. If wrong, the
+ parties involved should please contact me so that we can fix it.
+
+ Add opendir wrapper to libsandbox.c.
+
+ 21 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Do some more cleanups to ecanonicalize(), as it dropped filenames in
+ rare cases (after my symlink cleanups), and caused glibc to bork.
+ These fixes went into canonicalize.c.
+
+ 20 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Fix spawn_shell() and main() in sandbox.c to properly return fail
+ status.
+
+ 19 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ The new canonicalize() function in libsandbox.c also resolved symlinks,
+ which caused on cleaning sandbox errors if the symlink pointed to a
+ file in the live root. Ripped out canonicalize() and realpath() from
+ glibc; removed the symlink stuff, and changed them to ecanonicalize()
+ and erealpath().
+
+ 18 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Ripped out all the wrappers, and implemented those of InstallWatch.
+ Losts of cleanups and bugfixes. Implement a execve that forces
+ $LIBSANDBOX in $LD_PRELOAD. We can now thus do away with the feared
+ /etc/ld.so.preload (*g*) ... Made the needed changes to sandbox.c,
+ sandbox.h and sandbox_futils.c. Rewrote the Makefile for most
+ parts; it now have an install target.
+
+ Reformat the whole thing to look somewhat like the reworked sandbox.c
+ and new sandbox.h and sandbox_futils.c from:
+
+ Brad House <brad@mainstreetsoftworks.com>.
+
+ Additional Copyrights now due to the InstallWatch code:
+
+ Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>
+
diff --git a/src/sandbox-1.1/Makefile b/src/sandbox-1.1/Makefile
new file mode 100644
index 00000000..b451676a
--- /dev/null
+++ b/src/sandbox-1.1/Makefile
@@ -0,0 +1,81 @@
+# Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+# Distributed under the terms of the GNU General Public License, v2 or later
+# Author : Geert Bevin <gbevin@uwyn.com>
+#
+# Modified 15 Apr 2002 Jon Nelson <jnelson@gentoo.org>
+# Clean up Makefile somewhat, and use make's implicit rules
+#
+# Modified 19 Aug 2002; Martin Schlemmer <azarah@gentoo.org>
+# Major rewrite to support new stuff
+#
+# Indent: indent -kr -i2 -ts2 -sob -l80 -ss -bs -psl
+#
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/Makefile,v 1.7.2.2 2004/11/29 08:41:28 carpaski Exp $
+
+CC ?= gcc
+LD ?= ld
+CFLAGS =
+ARCH_CFLAGS =
+OBJ_CFLAGS = -D_GNU_SOURCE -DPIC -fPIC -D_REENTRANT
+LIBS =
+LDFLAGS =
+DESTDIR =
+
+HAVE_64BIT_ARCH =
+
+ifneq ($(HAVE_64BIT_ARCH),)
+ TARGETS = libsandbox.so libsandbox32.so sandbox
+ ARCH_CFLAGS += -m64
+ OBJ_CFLAGS += -DSB_HAVE_64BIT_ARCH
+else
+ TARGETS = libsandbox.so sandbox
+endif
+
+all: $(TARGETS)
+
+sandbox: sandbox.o sandbox_futils.o getcwd.c
+ $(CC) $(CFLAGS) $(ARCH_CFLAGS) $(OBJ_CFLAGS) -Wall $^ -ldl -lc -o $@
+
+sandbox.o: sandbox.c sandbox.h
+ $(CC) $(CFLAGS) $(ARCH_CFLAGS) $(OBJ_CFLAGS) -Wall -c sandbox.c -o $@
+
+sandbox_futils.o: localdecls.h sandbox_futils.c sandbox.h
+ $(CC) $(CFLAGS) $(ARCH_CFLAGS) $(OBJ_CFLAGS) -Wall -c sandbox_futils.c -o $@
+
+libsandbox.so: libsandbox.o sandbox_futils.o
+ $(CC) $^ -shared $(ARCH_CFLAGS) -fPIC -ldl -lc -nostdlib -lgcc -o $@
+
+libsandbox.o: localdecls.h libsandbox.c canonicalize.c getcwd.c
+ $(CC) $(CFLAGS) $(ARCH_CFLAGS) $(OBJ_CFLAGS) -Wall -c libsandbox.c
+
+sandbox_futils32.o: sandbox_futils.c sandbox.h
+ $(CC) $(CFLAGS) -m32 $(OBJ_CFLAGS) -Wall -c sandbox_futils.c -o $@
+
+libsandbox32.so: libsandbox32.o sandbox_futils32.o
+ $(CC) $^ -shared -m32 -fPIC -ldl -lc -nostdlib -lgcc -o $@
+
+libsandbox32.o: libsandbox.c localdecls.h canonicalize.c getcwd.c
+ $(CC) $(CFLAGS) -m32 $(OBJ_CFLAGS) -Wall -c libsandbox.c -o $@
+
+localdecls.h: create-localdecls libctest.c
+ ./create-localdecls
+
+
+install: all
+ install -d -m 0755 $(DESTDIR)/lib
+ $(if $(HAVE_64BIT_ARCH),install -d -m 0755 $(DESTDIR)/lib32)
+ install -d -m 0755 $(DESTDIR)/usr/lib/portage/bin
+ install -d -m 0755 $(DESTDIR)/usr/lib/portage/lib
+ install -m 0755 libsandbox.so $(DESTDIR)/lib
+ $(if $(HAVE_64BIT_ARCH),install -m 0755 libsandbox32.so $(DESTDIR)/lib32/libsandbox.so)
+ install -m 0755 sandbox $(DESTDIR)/usr/lib/portage/bin
+ install -m 0644 sandbox.bashrc $(DESTDIR)/usr/lib/portage/lib
+
+
+clean:
+ rm -f $(TARGETS)
+ rm -f *.o *~ core
+ rm -f localdecls.h
+
+
+# vim:expandtab noai:cindent ai
diff --git a/src/sandbox-1.1/canonicalize.c b/src/sandbox-1.1/canonicalize.c
new file mode 100644
index 00000000..85ca77f7
--- /dev/null
+++ b/src/sandbox-1.1/canonicalize.c
@@ -0,0 +1,173 @@
+/* Return the canonical absolute name of a given file.
+ Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/*
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/canonicalize.c,v 1.5.2.1 2004/10/22 16:53:30 carpaski Exp $
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+/* Return the canonical absolute name of file NAME. A canonical name
+ does not contain any `.', `..' components nor any repeated path
+ separators ('/') or symlinks. All path components must exist. If
+ RESOLVED is null, the result is malloc'd; otherwise, if the
+ canonical name is SB_PATH_MAX chars or more, returns null with `errno'
+ set to ENAMETOOLONG; if the name fits in fewer than SB_PATH_MAX chars,
+ returns the name in RESOLVED. If the name cannot be resolved and
+ RESOLVED is non-NULL, it contains the path of the first component
+ that cannot be resolved. If the path can be resolved, RESOLVED
+ holds the same value as the value returned. */
+
+/* Modified: 19 Aug 2002; Martin Schlemmer <azarah@gentoo.org>
+ *
+ * Cleaned up unneeded stuff, and change so that it will not
+ * resolve symlinks. Also prepended a 'e' to functions that
+ * I did not rip out.
+ *
+ */
+
+char *
+erealpath(const char *name, char *resolved)
+{
+ char *rpath, *dest;
+ const char *start, *end, *rpath_limit;
+ long int path_max;
+
+ if (name == NULL) {
+ /* As per Single Unix Specification V2 we must return an error if
+ either parameter is a null pointer. We extend this to allow
+ the RESOLVED parameter to be NULL in case the we are expected to
+ allocate the room for the return value. */
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ if (name[0] == '\0') {
+ /* As per Single Unix Specification V2 we must return an error if
+ the name argument points to an empty string. */
+ __set_errno(ENOENT);
+ return NULL;
+ }
+#ifdef SB_PATH_MAX
+ path_max = SB_PATH_MAX;
+#else
+ path_max = pathconf(name, _PC_PATH_MAX);
+ if (path_max <= 0)
+ path_max = 1024;
+#endif
+
+ if (resolved == NULL) {
+ rpath = malloc(path_max);
+ if (rpath == NULL)
+ return NULL;
+ } else
+ rpath = resolved;
+ rpath_limit = rpath + path_max;
+
+ if (name[0] != '/') {
+ if (!egetcwd(rpath, path_max)) {
+ rpath[0] = '\0';
+ goto error;
+ }
+ dest = strchr(rpath, '\0');
+ } else {
+ rpath[0] = '/';
+ dest = rpath + 1;
+ }
+
+ for (start = end = name; *start; start = end) {
+ /* Skip sequence of multiple path-separators. */
+ while (*start == '/')
+ ++start;
+
+ /* Find end of path component. */
+ for (end = start; *end && *end != '/'; ++end)
+ /* Nothing. */ ;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.')
+ /* nothing */ ;
+ else if (end - start == 2 && start[0] == '.' && start[1] == '.') {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rpath + 1)
+ while ((--dest)[-1] != '/') ;
+ } else {
+ size_t new_size;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) >= rpath_limit) {
+ ptrdiff_t dest_offset = dest - rpath;
+ char *new_rpath;
+
+ if (resolved) {
+ __set_errno(ENAMETOOLONG);
+ if (dest > rpath + 1)
+ dest--;
+ *dest = '\0';
+ goto error;
+ }
+ new_size = rpath_limit - rpath;
+ if (end - start + 1 > path_max)
+ new_size += end - start + 1;
+ else
+ new_size += path_max;
+ new_rpath = (char *) realloc(rpath, new_size);
+ if (new_rpath == NULL)
+ goto error;
+ rpath = new_rpath;
+ rpath_limit = rpath + new_size;
+
+ dest = rpath + dest_offset;
+ }
+
+ dest = __mempcpy(dest, start, end - start);
+ *dest = '\0';
+ }
+ }
+#if 1
+ if (dest > rpath + 1 && dest[-1] == '/')
+ --dest;
+#endif
+ *dest = '\0';
+
+ return resolved ? memcpy(resolved, rpath, dest - rpath + 1) : rpath;
+
+error:
+ if (resolved)
+ strcpy(resolved, rpath);
+ else
+ free(rpath);
+ return NULL;
+}
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-1.1/create-localdecls b/src/sandbox-1.1/create-localdecls
new file mode 100755
index 00000000..816723d5
--- /dev/null
+++ b/src/sandbox-1.1/create-localdecls
@@ -0,0 +1,115 @@
+#!/bin/sh
+
+# This is a quick'n'dirty hack to make the program behave correctly
+# under different systems.
+# Example:
+# when using libc5, (f)trucate's offset argument type is size_t with
+# libc5, but it's off_t with libc6 (glibc2).
+#
+# Uhm... time to learn GNU autoconf :-)
+#
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/create-localdecls,v 1.11.2.1 2004/10/22 16:53:30 carpaski Exp $
+
+OUTFILE='localdecls.h'
+
+# if your arch needs to dlopen() glibc, add it here separated by space :]
+BROKEN_RTLD_ARCHLIST="mips"
+
+echo '/* This file is automatically generated *' > $OUTFILE
+echo ' * Modify create-localdecls instead of this */' >> $OUTFILE
+echo >> $OUTFILE
+echo '#ifndef __LOCALDECLS_H_' >> $OUTFILE
+echo '#define __LOCALDECLS_H_' >> $OUTFILE
+echo >> $OUTFILE
+
+###
+###
+###
+
+echo -n 'Checking truncate argument type... '
+if grep -q 'truncate.*size_t' /usr/include/unistd.h ; then
+ echo 'size_t'
+ echo '#define TRUNCATE_T size_t' >> $OUTFILE
+else
+ echo 'off_t' # At least, I HOPE it's off_t :-)
+ echo '#define TRUNCATE_T off_t' >> $OUTFILE
+fi
+
+###
+###
+###
+
+echo -n 'Checking libc version... '
+gcc -Wall -o libctest libctest.c
+VERSION=`ldd libctest | grep libc\\.so | grep -v 'ld-uClibc' | awk '{print $1}'`
+
+echo $VERSION
+echo "#define LIBC_VERSION \"$VERSION\"" >> $OUTFILE
+if test "$VERSION" = 'libc.so.5' ; then
+ echo '#define BROKEN_RTLD_NEXT' >> $OUTFILE
+ echo '#define LIBC 5' >> $OUTFILE
+else
+ # for the arch's that need to dlopen() libc to fetch real funcs!
+ # 16.12.02 -Torgeir Hansen <torgeir@trenger.ro>
+ MYARCH=`/bin/uname -m`
+ for x in $BROKEN_RTLD_ARCHLIST; do
+ if [ $x = $MYARCH ]; then
+ echo '#define BROKEN_RTLD_NEXT' >> $OUTFILE
+ fi
+ done
+
+fi
+
+if test "$VERSION" = 'libc.so.6' ; then
+ echo -n 'Checking glibc subversion...'
+ tmp="$(ldd libctest 2>/dev/null | grep libc.so 2>/dev/null | head -n 1)"
+ LibcPath=`expr "$tmp" : '[^/]*\(/[^ ]*\)'`
+ tmp="`strings $LibcPath | grep -i 'c library'`"
+ OsLibcMajor=`expr "$tmp" : '.* \([0-9][0-9]*\)'`
+ OsLibcMinor=`expr "$tmp" : '.* [0-9][0-9]*\.\([0-9][0-9]*\)'`
+ echo " ${OsLibcMajor}.${OsLibcMinor}"
+ case "$OsLibcMajor" in
+ 2)
+ # 2 is the glibc version
+ case "$OsLibcMinor" in
+ 0)
+ echo '#define GLIBC_MINOR 0' >> $OUTFILE
+ SUBVERSION='glibc-2.0' ;;
+ 1)
+ echo '#define GLIBC_MINOR 1' >> $OUTFILE
+ SUBVERSION='glibc-2.1' ;;
+ 2)
+ echo '#define GLIBC_MINOR 2' >> $OUTFILE
+ SUBVERSION='glibc-2.2' ;;
+ 3)
+ echo '#define GLIBC_MINOR 3' >> $OUTFILE
+ SUBVERSION='glibc-2.3' ;;
+ *)
+ echo 'Treated as glibc >= 2.1 (finger crossed)'
+ echo '#define GLIBC_MINOR 1' >> $OUTFILE
+ SUBVERSION='glibc-2.1' ;;
+ esac
+ ;;
+ esac
+fi
+
+rm libctest
+
+echo '
+#ifdef PATH_MAX
+# define SB_PATH_MAX PATH_MAX * 2
+# if (SB_PATH_MAX >= INT_MAX) || (SB_PATH_MAX < PATH_MAX)
+# undef SB_PATH_MAX
+# define SB_PATH_MAX PATH_MAX + 25
+# if (SB_PATH_MAX >= INT_MAX) || (SB_PATH_MAX < PATH_MAX)
+# error SB_PATH_MAX too big!
+# endif
+# endif
+#else
+# error PATH_MAX not defined!
+#endif' >> $OUTFILE
+
+echo >> $OUTFILE
+echo '#endif' >> $OUTFILE
+echo
+
diff --git a/src/sandbox-1.1/getcwd.c b/src/sandbox-1.1/getcwd.c
new file mode 100644
index 00000000..552e41a0
--- /dev/null
+++ b/src/sandbox-1.1/getcwd.c
@@ -0,0 +1,511 @@
+/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Wants:
+ AC_STDC_HEADERS
+ AC_DIR_HEADER
+ AC_UNISTD_H
+ AC_MEMORY_H
+ AC_CONST
+ AC_ALLOCA
+ */
+
+/*
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/getcwd.c,v 1.1.2.1 2004/10/22 16:53:30 carpaski Exp $
+ */
+
+/* Modified: 26 July 2003; Martin Schlemmer <azarah@gentoo.org>
+ *
+ * Cleaned up unneeded stuff. Add a wrapper to try and detect when
+ * we have a kernel whose getcwd system call do not handle directory
+ * names longer than PATH_MAX, and if so, use our generic version.
+ * To work truly with > PATH_MAX lengh CWDs, I had to increase the
+ * size of the dots[] array. Also prepended a 'e' to functions that
+ * I did not rip out.
+ *
+ */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined _AIX && !defined __GNUC__
+#pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#if !defined __GNU_LIBRARY__ && !defined STDC_HEADERS
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+#if defined USGr3 && !defined DIRENT
+# define DIRENT
+#endif /* USGr3 */
+#if defined Xenix && !defined SYSNDIR
+# define SYSNDIR
+#endif /* Xenix */
+
+#if defined POSIX || defined DIRENT || defined __GNU_LIBRARY__
+# include <dirent.h>
+# ifndef __GNU_LIBRARY__
+# define D_NAMLEN(d) strlen((d)->d_name)
+# else
+# define HAVE_D_NAMLEN
+# define D_NAMLEN(d) ((d)->d_namlen)
+# endif
+#else /* not POSIX or DIRENT */
+# define dirent direct
+# define D_NAMLEN(d) ((d)->d_namlen)
+# define HAVE_D_NAMLEN
+# if defined USG && !defined sgi
+# if defined SYSNDIR
+# include <sys/ndir.h>
+# else /* Not SYSNDIR */
+# include "ndir.h"
+# endif /* SYSNDIR */
+# else /* not USG */
+# include <sys/dir.h>
+# endif /* USG */
+#endif /* POSIX or DIRENT or __GNU_LIBRARY__ */
+
+#if defined HAVE_UNISTD_H || defined __GNU_LIBRARY__
+# include <unistd.h>
+#endif
+
+#if defined STDC_HEADERS || defined __GNU_LIBRARY__ || defined POSIX
+# include <stdlib.h>
+# include <string.h>
+# define ANSI_STRING
+#else /* No standard headers. */
+
+# ifdef USG
+
+# include <string.h>
+# ifdef NEED_MEMORY_H
+# include <memory.h>
+# endif
+# define ANSI_STRING
+
+# else /* Not USG. */
+
+# ifdef NeXT
+
+# include <string.h>
+
+# else /* Not NeXT. */
+
+# include <strings.h>
+
+# ifndef bcmp
+extern int bcmp();
+# endif
+# ifndef bzero
+extern void bzero();
+# endif
+# ifndef bcopy
+extern void bcopy();
+# endif
+
+# endif /* NeXT. */
+
+# endif /* USG. */
+
+extern char *malloc(), *realloc();
+extern void free();
+
+#endif /* Standard headers. */
+
+#ifndef ANSI_STRING
+# define memcpy(d, s, n) bcopy((s), (d), (n))
+# define memmove memcpy
+#endif /* Not ANSI_STRING. */
+
+#ifndef MAX
+# define MAX(a, b) ((a) < (b) ? (b) : (a))
+#endif
+
+#ifdef _LIBC
+# ifndef mempcpy
+# define mempcpy __mempcpy
+# endif
+# define HAVE_MEMPCPY 1
+#endif
+
+#if !defined __alloca && !defined __GNU_LIBRARY__
+
+# ifdef __GNUC__
+# undef alloca
+# define alloca(n) __builtin_alloca (n)
+# else /* Not GCC. */
+# if defined sparc || defined HAVE_ALLOCA_H
+# include <alloca.h>
+# else /* Not sparc or HAVE_ALLOCA_H. */
+# ifndef _AIX
+extern char *alloca();
+# endif /* Not _AIX. */
+# endif /* sparc or HAVE_ALLOCA_H. */
+# endif /* GCC. */
+
+# define __alloca alloca
+
+#endif
+
+#if defined HAVE_LIMITS_H || defined STDC_HEADERS || defined __GNU_LIBRARY__
+# include <limits.h>
+#else
+# include <sys/param.h>
+#endif
+
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# else
+# define PATH_MAX 1024
+# endif
+#endif
+
+#if !defined STDC_HEADERS && !defined __GNU_LIBRARY__
+# undef size_t
+# define size_t unsigned int
+#endif
+
+#if !__STDC__ && !defined const
+# define const
+#endif
+
+#ifndef __GNU_LIBRARY__
+# define __lstat stat
+#endif
+
+#ifndef _LIBC
+# define __getcwd getcwd
+#endif
+
+#ifndef GETCWD_RETURN_TYPE
+# define GETCWD_RETURN_TYPE char *
+#endif
+
+#ifndef SB_PATH_MAX
+# include "localdecls.h"
+# define OUTSIDE_LIBSANDBOX
+#endif
+
+#ifndef __LIBC
+# define __lstat lstat
+# define __readdir readdir
+# define __closedir closedir
+#endif
+
+/* Get the pathname of the current working directory, and put it in SIZE
+ bytes of BUF. Returns NULL if the directory couldn't be determined or
+ SIZE was too small. If successful, returns BUF. In GNU, if BUF is
+ NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
+ unless SIZE == 0, in which case it is as big as necessary. */
+
+GETCWD_RETURN_TYPE
+__egetcwd(buf, size)
+char *buf;
+size_t size;
+{
+ static const char dots[]
+ = "../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../../\
+../../../../../../../../../../../../../../../../../../../../../../../../../..";
+ const char *dotp = &dots[sizeof (dots)];
+ const char *dotlist = dots;
+ size_t dotsize = sizeof (dots) - 1;
+ dev_t rootdev, thisdev;
+ ino_t rootino, thisino;
+ char *path;
+ register char *pathp;
+ struct stat st;
+ int prev_errno = errno;
+ size_t allocated = size;
+
+ if (size == 0) {
+ if (buf != NULL) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ allocated = SB_PATH_MAX + 1;
+ }
+
+ if (buf != NULL)
+ path = buf;
+ else {
+ path = malloc(allocated);
+ if (path == NULL)
+ return NULL;
+ }
+
+ pathp = path + allocated;
+ *--pathp = '\0';
+
+ if (__lstat(".", &st) < 0)
+ goto lose2;
+ thisdev = st.st_dev;
+ thisino = st.st_ino;
+
+ if (__lstat("/", &st) < 0)
+ goto lose2;
+ rootdev = st.st_dev;
+ rootino = st.st_ino;
+
+ while (!(thisdev == rootdev && thisino == rootino)) {
+ register DIR *dirstream;
+ struct dirent *d;
+ dev_t dotdev;
+ ino_t dotino;
+ char mount_point;
+
+ /* Look at the parent directory. */
+ if (dotp == dotlist) {
+ /* My, what a deep directory tree you have, Grandma. */
+ char *new;
+ if (dotlist == dots) {
+ new = malloc(dotsize * 2 + 1);
+ if (new == NULL)
+ goto lose;
+#ifdef HAVE_MEMPCPY
+ dotp = mempcpy(new, dots, dotsize);
+#else
+ memcpy(new, dots, dotsize);
+ dotp = &new[dotsize];
+#endif
+ } else {
+ new = realloc((__ptr_t) dotlist, dotsize * 2 + 1);
+ if (new == NULL)
+ goto lose;
+ dotp = &new[dotsize];
+ }
+#ifdef HAVE_MEMPCPY
+ *((char *) mempcpy((char *) dotp, new, dotsize)) = '\0';
+ dotsize *= 2;
+#else
+ memcpy((char *) dotp, new, dotsize);
+ dotsize *= 2;
+ new[dotsize] = '\0';
+#endif
+ dotlist = new;
+ }
+
+ dotp -= 3;
+
+ /* Figure out if this directory is a mount point. */
+ if (__lstat(dotp, &st) < 0)
+ goto lose;
+ dotdev = st.st_dev;
+ dotino = st.st_ino;
+ mount_point = dotdev != thisdev;
+
+ /* Search for the last directory. */
+#ifdef OUTSIDE_LIBSANDBOX
+ dirstream = opendir(dotp);
+#else
+ dirstream = true_opendir(dotp);
+#endif
+ if (dirstream == NULL)
+ goto lose;
+ /* Clear errno to distinguish EOF from error if readdir returns
+ NULL. */
+ __set_errno(0);
+ while ((d = __readdir(dirstream)) != NULL) {
+ if (d->d_name[0] == '.' &&
+ (d->d_name[1] == '\0'
+ || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+ continue;
+ if (mount_point || (ino_t) d->d_ino == thisino) {
+ char name[dotlist + dotsize - dotp + 1 + _D_ALLOC_NAMLEN(d)];
+#ifdef HAVE_MEMPCPY
+ char *tmp = mempcpy(name, dotp,
+ dotlist + dotsize - dotp);
+ *tmp++ = '/';
+ strcpy(tmp, d->d_name);
+#else
+ memcpy(name, dotp, dotlist + dotsize - dotp);
+ name[dotlist + dotsize - dotp] = '/';
+ strcpy(&name[dotlist + dotsize - dotp + 1], d->d_name);
+#endif
+ /* We don't fail here if we cannot stat() a directory entry.
+ This can happen when (network) filesystems fail. If this
+ entry is in fact the one we are looking for we will find
+ out soon as we reach the end of the directory without
+ having found anything. */
+ if (__lstat(name, &st) >= 0 && st.st_dev == thisdev
+ && st.st_ino == thisino)
+ break;
+ }
+ }
+ if (d == NULL) {
+ int save = errno;
+ (void) __closedir(dirstream);
+ if (save == 0)
+ /* EOF on dirstream, which means that the current directory
+ has been removed. */
+ save = ENOENT;
+ __set_errno(save);
+ goto lose;
+ } else {
+ size_t namlen = _D_EXACT_NAMLEN(d);
+
+ if ((size_t) (pathp - path) <= namlen) {
+ if (size != 0) {
+ (void) __closedir(dirstream);
+ __set_errno(ERANGE);
+ goto lose;
+ } else {
+ char *tmp;
+ size_t oldsize = allocated;
+
+ allocated = 2 * MAX(allocated, namlen);
+ tmp = realloc(path, allocated);
+ if (tmp == NULL) {
+ (void) __closedir(dirstream);
+ __set_errno(ENOMEM); /* closedir might have changed it. */
+ goto lose;
+ }
+
+ /* Move current contents up to the end of the buffer.
+ This is guaranteed to be non-overlapping. */
+ pathp =
+ memcpy(tmp + allocated -
+ (path + oldsize - pathp),
+ tmp + (pathp - path), path + oldsize - pathp);
+ path = tmp;
+ }
+ }
+ pathp -= namlen;
+ (void) memcpy(pathp, d->d_name, namlen);
+ *--pathp = '/';
+ (void) __closedir(dirstream);
+ }
+
+ thisdev = dotdev;
+ thisino = dotino;
+ }
+
+ if (pathp == &path[allocated - 1])
+ *--pathp = '/';
+
+ if (dotlist != dots)
+ free((__ptr_t) dotlist);
+
+ memmove(path, pathp, path + allocated - pathp);
+
+ /* Restore errno on successful return. */
+ __set_errno(prev_errno);
+
+ return path;
+
+lose:
+ if (dotlist != dots)
+ free((__ptr_t) dotlist);
+lose2:
+ if (buf == NULL)
+ free(path);
+ return NULL;
+}
+
+GETCWD_RETURN_TYPE
+egetcwd(buf, size)
+char *buf;
+size_t size;
+{
+ struct stat st;
+ char *tmpbuf;
+
+ __set_errno(0);
+ tmpbuf = getcwd(buf, size);
+
+ if (tmpbuf) {
+ __lstat(buf, &st);
+ } else {
+ return tmpbuf;
+ }
+
+ if (errno) {
+ /* If lstat() failed with eerror = ENOENT, then its
+ * possible that we are running on an older kernel,
+ * so use our generic version which *should* not fail.
+ */
+ if (errno == ENOENT) {
+ return __egetcwd(buf, size);
+ } else {
+ return tmpbuf;
+ }
+ }
+
+ return tmpbuf;
+}
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-1.1/libctest.c b/src/sandbox-1.1/libctest.c
new file mode 100644
index 00000000..5365a20c
--- /dev/null
+++ b/src/sandbox-1.1/libctest.c
@@ -0,0 +1,7 @@
+/* Dummy program to check your libc version */
+
+int
+main(void)
+{
+ return 0;
+}
diff --git a/src/sandbox-1.1/libsandbox.c b/src/sandbox-1.1/libsandbox.c
new file mode 100644
index 00000000..be4efc4f
--- /dev/null
+++ b/src/sandbox-1.1/libsandbox.c
@@ -0,0 +1,1383 @@
+/*
+ * Path sandbox for the gentoo linux portage package system, initially
+ * based on the ROCK Linux Wrapper for getting a list of created files
+ *
+ * to integrate with bash, bash should have been built like this
+ *
+ * ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
+ *
+ * it's very important that the --enable-static-link option is NOT specified
+ *
+ * Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+ * Distributed under the terms of the GNU General Public License, v2 or later
+ * Author : Geert Bevin <gbevin@uwyn.com>
+ *
+ * Post Bevin leaving Gentoo ranks:
+ * --------------------------------
+ * Ripped out all the wrappers, and implemented those of InstallWatch.
+ * Losts of cleanups and bugfixes. Implement a execve that forces $LIBSANDBOX
+ * in $LD_PRELOAD. Reformat the whole thing to look somewhat like the reworked
+ * sandbox.c from Brad House <brad@mainstreetsoftworks.com>.
+ *
+ * Martin Schlemmer <azarah@gentoo.org> (18 Aug 2002)
+ *
+ * Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>,
+ * as some of the InstallWatch code was used.
+ *
+ *
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/libsandbox.c,v 1.22.2.3 2004/12/01 22:14:09 carpaski Exp $
+ *
+ */
+
+/* Uncomment below to enable wrapping of mknod().
+ * This is broken currently. */
+/* #define WRAP_MKNOD 1 */
+
+/* Uncomment below to enable the use of strtok_r(). */
+#define REENTRANT_STRTOK 1
+
+/* Uncomment below to enable memory debugging. */
+/* #define SB_MEM_DEBUG 1 */
+
+#define open xxx_open
+#define open64 xxx_open64
+
+/* Wrapping mknod, do not have any effect, and
+ * wrapping __xmknod causes calls to it to segfault
+ */
+#ifdef WRAP_MKNOD
+# define __xmknod xxx___xmknod
+#endif
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <utime.h>
+
+#ifdef SB_MEM_DEBUG
+# include <mcheck.h>
+#endif
+
+#ifdef WRAP_MKNOD
+# undef __xmknod
+#endif
+
+#undef open
+#undef open64
+
+#include "localdecls.h"
+#include "sandbox.h"
+
+/* Macros to check if a function should be executed */
+#define FUNCTION_SANDBOX_SAFE(func, path) \
+ ((0 == is_sandbox_on()) || (1 == before_syscall(func, path)))
+
+#define FUNCTION_SANDBOX_SAFE_INT(func, path, flags) \
+ ((0 == is_sandbox_on()) || (1 == before_syscall_open_int(func, path, flags)))
+
+#define FUNCTION_SANDBOX_SAFE_CHAR(func, path, mode) \
+ ((0 == is_sandbox_on()) || (1 == before_syscall_open_char(func, path, mode)))
+
+/* Macro to check if a wrapper is defined, if not
+ * then try to resolve it again. */
+#define check_dlsym(name) \
+{ \
+ int old_errno=errno; \
+ if (!true_ ## name) true_ ## name=get_dlsym(#name); \
+ errno=old_errno; \
+}
+
+/* Macro to check if we could canonicalize a path. It returns an integer on
+ * failure. */
+#define canonicalize_int(path, resolved_path) \
+{ \
+ if (0 != canonicalize(path, resolved_path)) \
+ return -1; \
+}
+
+/* Macro to check if we could canonicalize a path. It returns a NULL pointer on
+ * failure. */
+#define canonicalize_ptr(path, resolved_path) \
+{ \
+ if (0 != canonicalize(path, resolved_path)) \
+ return NULL; \
+}
+
+static char sandbox_lib[255];
+//static char sandbox_pids_file[255];
+static char *sandbox_pids_file;
+
+typedef struct {
+ int show_access_violation;
+ char **deny_prefixes;
+ int num_deny_prefixes;
+ char **read_prefixes;
+ int num_read_prefixes;
+ char **write_prefixes;
+ int num_write_prefixes;
+ char **predict_prefixes;
+ int num_predict_prefixes;
+ char **write_denied_prefixes;
+ int num_write_denied_prefixes;
+} sbcontext_t;
+
+/* glibc modified realpath() functions */
+char *erealpath(const char *name, char *resolved);
+/* glibc modified getcwd() functions */
+char *egetcwd(char *, size_t);
+
+static void init_wrappers(void);
+static void *get_dlsym(const char *);
+static int canonicalize(const char *, char *);
+static int check_access(sbcontext_t *, const char *, const char *);
+static int check_syscall(sbcontext_t *, const char *, const char *);
+static int before_syscall(const char *, const char *);
+static int before_syscall_open_int(const char *, const char *, int);
+static int before_syscall_open_char(const char *, const char *, const char *);
+static void clean_env_entries(char ***, int *);
+static void init_context(sbcontext_t *);
+static void init_env_entries(char ***, int *, char *, int);
+static char *filter_path(const char *);
+static int is_sandbox_on();
+static int is_sandbox_pid();
+
+/* Wrapped functions */
+
+extern int chmod(const char *, mode_t);
+static int (*true_chmod) (const char *, mode_t);
+extern int chown(const char *, uid_t, gid_t);
+static int (*true_chown) (const char *, uid_t, gid_t);
+extern int creat(const char *, mode_t);
+static int (*true_creat) (const char *, mode_t);
+extern FILE *fopen(const char *, const char *);
+static FILE *(*true_fopen) (const char *, const char *);
+extern int lchown(const char *, uid_t, gid_t);
+static int (*true_lchown) (const char *, uid_t, gid_t);
+extern int link(const char *, const char *);
+static int (*true_link) (const char *, const char *);
+extern int mkdir(const char *, mode_t);
+static int (*true_mkdir) (const char *, mode_t);
+extern DIR *opendir(const char *);
+static DIR *(*true_opendir) (const char *);
+#ifdef WRAP_MKNOD
+extern int __xmknod(const char *, mode_t, dev_t);
+static int (*true___xmknod) (const char *, mode_t, dev_t);
+#endif
+extern int open(const char *, int, ...);
+static int (*true_open) (const char *, int, ...);
+extern int rename(const char *, const char *);
+static int (*true_rename) (const char *, const char *);
+extern int rmdir(const char *);
+static int (*true_rmdir) (const char *);
+extern int symlink(const char *, const char *);
+static int (*true_symlink) (const char *, const char *);
+extern int truncate(const char *, TRUNCATE_T);
+static int (*true_truncate) (const char *, TRUNCATE_T);
+extern int unlink(const char *);
+static int (*true_unlink) (const char *);
+
+#if (GLIBC_MINOR >= 1)
+
+extern int creat64(const char *, __mode_t);
+static int (*true_creat64) (const char *, __mode_t);
+extern FILE *fopen64(const char *, const char *);
+static FILE *(*true_fopen64) (const char *, const char *);
+extern int open64(const char *, int, ...);
+static int (*true_open64) (const char *, int, ...);
+extern int truncate64(const char *, __off64_t);
+static int (*true_truncate64) (const char *, __off64_t);
+
+#endif
+
+extern int execve(const char *filename, char *const argv[], char *const envp[]);
+static int (*true_execve) (const char *, char *const[], char *const[]);
+
+/*
+ * Initialize the shabang
+ */
+
+static void
+init_wrappers(void)
+{
+ void *libc_handle = NULL;
+
+#ifdef BROKEN_RTLD_NEXT
+// printf ("RTLD_LAZY");
+ libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY);
+#else
+// printf ("RTLD_NEXT");
+ libc_handle = RTLD_NEXT;
+#endif
+
+ true_chmod = dlsym(libc_handle, "chmod");
+ true_chown = dlsym(libc_handle, "chown");
+ true_creat = dlsym(libc_handle, "creat");
+ true_fopen = dlsym(libc_handle, "fopen");
+ true_lchown = dlsym(libc_handle, "lchown");
+ true_link = dlsym(libc_handle, "link");
+ true_mkdir = dlsym(libc_handle, "mkdir");
+ true_opendir = dlsym(libc_handle, "opendir");
+#ifdef WRAP_MKNOD
+ true___xmknod = dlsym(libc_handle, "__xmknod");
+#endif
+ true_open = dlsym(libc_handle, "open");
+ true_rename = dlsym(libc_handle, "rename");
+ true_rmdir = dlsym(libc_handle, "rmdir");
+ true_symlink = dlsym(libc_handle, "symlink");
+ true_truncate = dlsym(libc_handle, "truncate");
+ true_unlink = dlsym(libc_handle, "unlink");
+
+#if (GLIBC_MINOR >= 1)
+ true_creat64 = dlsym(libc_handle, "creat64");
+ true_fopen64 = dlsym(libc_handle, "fopen64");
+ true_open64 = dlsym(libc_handle, "open64");
+ true_truncate64 = dlsym(libc_handle, "truncate64");
+#endif
+
+ true_execve = dlsym(libc_handle, "execve");
+}
+
+void
+_fini(void)
+{
+ free(sandbox_pids_file);
+}
+
+void
+_init(void)
+{
+ int old_errno = errno;
+ char *tmp_string = NULL;
+
+#ifdef SB_MEM_DEBUG
+ mtrace();
+#endif
+
+ init_wrappers();
+
+ /* Get the path and name to this library */
+ tmp_string = get_sandbox_lib("/");
+ strncpy(sandbox_lib, tmp_string, sizeof(sandbox_lib)-1);
+ if (tmp_string)
+ free(tmp_string);
+ tmp_string = NULL;
+
+ /* Generate sandbox pids-file path */
+ sandbox_pids_file = get_sandbox_pids_file();
+
+ errno = old_errno;
+}
+
+static int
+canonicalize(const char *path, char *resolved_path)
+{
+ int old_errno = errno;
+ char *retval;
+
+ *resolved_path = '\0';
+
+ /* If path == NULL, return or we get a segfault */
+ if (NULL == path) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Do not try to resolve an empty path */
+ if ('\0' == path[0]) {
+ errno = old_errno;
+ return 0;
+ }
+
+ retval = erealpath(path, resolved_path);
+
+ if ((!retval) && (path[0] != '/')) {
+ /* The path could not be canonicalized, append it
+ * to the current working directory if it was not
+ * an absolute path
+ */
+ if (errno == ENAMETOOLONG)
+ return -1;
+
+ egetcwd(resolved_path, SB_PATH_MAX - 2);
+ strcat(resolved_path, "/");
+ strncat(resolved_path, path, SB_PATH_MAX - 1);
+
+ if (!erealpath(resolved_path, resolved_path)) {
+ if (errno == ENAMETOOLONG) {
+ /* The resolved path is too long for the buffer to hold */
+ return -1;
+ } else {
+ /* Whatever it resolved, is not a valid path */
+ errno = ENOENT;
+ return -1;
+ }
+ }
+
+ } else if ((!retval) && (path[0] == '/')) {
+ /* Whatever it resolved, is not a valid path */
+ errno = ENOENT;
+ return -1;
+ }
+
+ errno = old_errno;
+ return 0;
+}
+
+static void *
+get_dlsym(const char *symname)
+{
+ void *libc_handle = NULL;
+ void *symaddr = NULL;
+
+#ifdef BROKEN_RTLD_NEXT
+ libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY);
+ if (!libc_handle) {
+ printf("libsandbox.so: Can't dlopen libc: %s\n", dlerror());
+ abort();
+ }
+#else
+ libc_handle = RTLD_NEXT;
+#endif
+
+ symaddr = dlsym(libc_handle, symname);
+ if (!symaddr) {
+ printf("libsandbox.so: Can't resolve %s: %s\n", symname, dlerror());
+ abort();
+ }
+
+ return symaddr;
+}
+
+/*
+ * Wrapper Functions
+ */
+
+int
+chmod(const char *path, mode_t mode)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("chmod", canonic) {
+ check_dlsym(chmod);
+ result = true_chmod(path, mode);
+ }
+
+ return result;
+}
+
+int
+chown(const char *path, uid_t owner, gid_t group)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("chown", canonic) {
+ check_dlsym(chown);
+ result = true_chown(path, owner, group);
+ }
+
+ return result;
+}
+
+int
+creat(const char *pathname, mode_t mode)
+{
+/* Is it a system call? */
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("creat", canonic) {
+ check_dlsym(open);
+ result = true_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
+ }
+
+ return result;
+}
+
+FILE *
+fopen(const char *pathname, const char *mode)
+{
+ FILE *result = NULL;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_ptr(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_CHAR
+ ("fopen", canonic, mode) {
+ check_dlsym(fopen);
+ result = true_fopen(pathname, mode);
+ }
+
+ return result;
+}
+
+int
+lchown(const char *path, uid_t owner, gid_t group)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("lchown", canonic) {
+ check_dlsym(lchown);
+ result = true_lchown(path, owner, group);
+ }
+
+ return result;
+}
+
+int
+link(const char *oldpath, const char *newpath)
+{
+ int result = -1;
+ char old_canonic[SB_PATH_MAX], new_canonic[SB_PATH_MAX];
+
+ canonicalize_int(oldpath, old_canonic);
+ canonicalize_int(newpath, new_canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("link", new_canonic) {
+ check_dlsym(link);
+ result = true_link(oldpath, newpath);
+ }
+
+ return result;
+}
+
+int
+mkdir(const char *pathname, mode_t mode)
+// returns 0 success, or -1 if an error occurred
+{
+ int result = -1, my_errno = errno;
+ char canonic[SB_PATH_MAX];
+ struct stat st;
+
+ canonicalize_int(pathname, canonic);
+
+ /* Check if the directory exist, return EEXIST rather than failing */
+ if (0 == lstat(canonic, &st)) {
+ errno = EEXIST;
+ return -1;
+ }
+ errno = my_errno;
+
+ if FUNCTION_SANDBOX_SAFE
+ ("mkdir", canonic) {
+ check_dlsym(mkdir);
+ result = true_mkdir(pathname, mode);
+ }
+
+ return result;
+}
+
+DIR *
+opendir(const char *name)
+{
+ DIR *result = NULL;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_ptr(name, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("opendir", canonic) {
+ check_dlsym(opendir);
+ result = true_opendir(name);
+ }
+
+ return result;
+}
+
+#ifdef WRAP_MKNOD
+
+int
+__xmknod(const char *pathname, mode_t mode, dev_t dev)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("__xmknod", canonic) {
+ check_dlsym(__xmknod);
+ result = true___xmknod(pathname, mode, dev);
+ }
+
+ return result;
+}
+
+#endif
+
+int
+open(const char *pathname, int flags, ...)
+{
+/* Eventually, there is a third parameter: it's mode_t mode */
+ va_list ap;
+ mode_t mode = 0;
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ if (flags & O_CREAT) {
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+ }
+
+ canonicalize_int(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_INT
+ ("open", canonic, flags) {
+ /* We need to resolve open() realtime in some cases,
+ * else we get a segfault when running /bin/ps, etc
+ * in a sandbox */
+ check_dlsym(open);
+ result = true_open(pathname, flags, mode);
+ }
+
+ return result;
+}
+
+int
+rename(const char *oldpath, const char *newpath)
+{
+ int result = -1;
+ char old_canonic[SB_PATH_MAX], new_canonic[SB_PATH_MAX];
+
+ canonicalize_int(oldpath, old_canonic);
+ canonicalize_int(newpath, new_canonic);
+
+ if (FUNCTION_SANDBOX_SAFE("rename", old_canonic) &&
+ FUNCTION_SANDBOX_SAFE("rename", new_canonic)) {
+ check_dlsym(rename);
+ result = true_rename(oldpath, newpath);
+ }
+
+ return result;
+}
+
+int
+rmdir(const char *pathname)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("rmdir", canonic) {
+ check_dlsym(rmdir);
+ result = true_rmdir(pathname);
+ }
+
+ return result;
+}
+
+int
+symlink(const char *oldpath, const char *newpath)
+{
+ int result = -1;
+ char old_canonic[SB_PATH_MAX], new_canonic[SB_PATH_MAX];
+
+ canonicalize_int(oldpath, old_canonic);
+ canonicalize_int(newpath, new_canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("symlink", new_canonic) {
+ check_dlsym(symlink);
+ result = true_symlink(oldpath, newpath);
+ }
+
+ return result;
+}
+
+int
+truncate(const char *path, TRUNCATE_T length)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("truncate", canonic) {
+ check_dlsym(truncate);
+ result = true_truncate(path, length);
+ }
+
+ return result;
+}
+
+int
+unlink(const char *pathname)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("unlink", canonic) {
+ check_dlsym(unlink);
+ result = true_unlink(pathname);
+ }
+
+ return result;
+}
+
+#if (GLIBC_MINOR >= 1)
+
+int
+creat64(const char *pathname, __mode_t mode)
+{
+/* Is it a system call? */
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("creat64", canonic) {
+ check_dlsym(open64);
+ result = true_open64(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
+ }
+
+ return result;
+}
+
+FILE *
+fopen64(const char *pathname, const char *mode)
+{
+ FILE *result = NULL;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_ptr(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_CHAR
+ ("fopen64", canonic, mode) {
+ check_dlsym(fopen64);
+ result = true_fopen(pathname, mode);
+ }
+
+ return result;
+}
+
+int
+open64(const char *pathname, int flags, ...)
+{
+/* Eventually, there is a third parameter: it's mode_t mode */
+ va_list ap;
+ mode_t mode = 0;
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ if (flags & O_CREAT) {
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+ }
+
+ canonicalize_int(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_INT
+ ("open64", canonic, flags) {
+ check_dlsym(open64);
+ result = true_open64(pathname, flags, mode);
+ }
+
+ return result;
+}
+
+int
+truncate64(const char *path, __off64_t length)
+{
+ int result = -1;
+ char canonic[SB_PATH_MAX];
+
+ canonicalize_int(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("truncate64", canonic) {
+ check_dlsym(truncate64);
+ result = true_truncate64(path, length);
+ }
+
+ return result;
+}
+
+#endif /* GLIBC_MINOR >= 1 */
+
+/*
+ * Exec Wrappers
+ */
+
+int
+execve(const char *filename, char *const argv[], char *const envp[])
+{
+ int old_errno = errno;
+ int result = -1;
+ int count = 0;
+ int env_len = 0;
+ char canonic[SB_PATH_MAX];
+ char **my_env = NULL;
+ int kill_env = 1;
+ /* We limit the size LD_PRELOAD can be here, but it should be enough */
+ char tmp_str[4096];
+
+ canonicalize_int(filename, canonic);
+
+ if FUNCTION_SANDBOX_SAFE
+ ("execve", canonic) {
+ while (envp[count] != NULL) {
+ if (strstr(envp[count], "LD_PRELOAD=") == envp[count]) {
+ if (NULL != strstr(envp[count], sandbox_lib)) {
+ my_env = (char **) envp;
+ kill_env = 0;
+ break;
+ } else {
+ int i = 0;
+ const int max_envp_len =
+ strlen(envp[count]) + strlen(sandbox_lib) + 1;
+
+ /* Fail safe ... */
+ if (max_envp_len > 4096) {
+ fprintf(stderr, "sandbox: max_envp_len too big!\n");
+ errno = ENOMEM;
+ return result;
+ }
+
+ /* Calculate envp size */
+ my_env = (char **) envp;
+ do
+ env_len += 1;
+ while (*my_env++);
+
+ my_env = (char **) malloc((env_len + 2) * sizeof (char *));
+ if (NULL == my_env) {
+ errno = ENOMEM;
+ return result;
+ }
+ /* Copy envp to my_env */
+ do
+ my_env[i] = envp[i];
+ while (envp[i++]);
+
+ /* Set tmp_str to envp[count] */
+ strncpy(tmp_str, envp[count], max_envp_len - 1);
+
+ /* LD_PRELOAD already have variables other than sandbox_lib,
+ * thus we have to add sandbox_lib seperated via a whitespace. */
+ if (0 != strncmp(envp[count], "LD_PRELOAD=", max_envp_len - 1)) {
+ strncat(tmp_str, " ", max_envp_len - strlen(tmp_str));
+ strncat(tmp_str, sandbox_lib, max_envp_len - strlen(tmp_str));
+ } else {
+ strncat(tmp_str, sandbox_lib, max_envp_len - strlen(tmp_str));
+ }
+
+ /* Valid string? */
+ tmp_str[max_envp_len] = '\0';
+
+ /* Ok, replace my_env[count] with our version that contains
+ * sandbox_lib ... */
+ my_env[count] = tmp_str;
+
+ break;
+ }
+ }
+ count++;
+ }
+
+ errno = old_errno;
+ check_dlsym(execve);
+ result = true_execve(filename, argv, my_env);
+ old_errno = errno;
+
+ if (my_env && kill_env) {
+ free(my_env);
+ my_env = NULL;
+ }
+ }
+
+ errno = old_errno;
+
+ return result;
+}
+
+/*
+ * Internal Functions
+ */
+
+#if (GLIBC_MINOR == 1)
+
+/* This hack is needed for glibc 2.1.1 (and others?)
+ * (not really needed, but good example) */
+extern int fclose(FILE *);
+static int (*true_fclose) (FILE *) = NULL;
+int
+fclose(FILE * file)
+{
+ int result = -1;
+
+ check_dlsym(fclose);
+ result = true_fclose(file);
+
+ return result;
+}
+
+#endif /* GLIBC_MINOR == 1 */
+
+static void
+init_context(sbcontext_t * context)
+{
+ context->show_access_violation = 1;
+ context->deny_prefixes = NULL;
+ context->num_deny_prefixes = 0;
+ context->read_prefixes = NULL;
+ context->num_read_prefixes = 0;
+ context->write_prefixes = NULL;
+ context->num_write_prefixes = 0;
+ context->predict_prefixes = NULL;
+ context->num_predict_prefixes = 0;
+ context->write_denied_prefixes = NULL;
+ context->num_write_denied_prefixes = 0;
+}
+
+static int
+is_sandbox_pid()
+{
+ int old_errno = errno;
+ int result = 0;
+ FILE *pids_stream = NULL;
+ int pids_file = -1;
+ int current_pid = 0;
+ int tmp_pid = 0;
+
+ init_wrappers();
+
+ pids_stream = true_fopen(sandbox_pids_file, "r");
+
+ if (NULL == pids_stream) {
+ perror(">>> pids file fopen");
+ } else {
+ pids_file = fileno(pids_stream);
+
+ if (pids_file < 0) {
+ perror(">>> pids file fileno");
+ } else {
+ current_pid = getpid();
+
+ while (EOF != fscanf(pids_stream, "%d\n", &tmp_pid)) {
+ if (tmp_pid == current_pid) {
+ result = 1;
+ break;
+ }
+ }
+ }
+ if (EOF == fclose(pids_stream)) {
+ perror(">>> pids file fclose");
+ }
+ pids_stream = NULL;
+ pids_file = -1;
+ }
+
+ errno = old_errno;
+
+ return result;
+}
+
+static void
+clean_env_entries(char ***prefixes_array, int *prefixes_num)
+{
+ int old_errno = errno;
+ int i = 0;
+
+ if (NULL != *prefixes_array) {
+ for (i = 0; i < *prefixes_num; i++) {
+ if (NULL != (*prefixes_array)[i]) {
+ free((*prefixes_array)[i]);
+ (*prefixes_array)[i] = NULL;
+ }
+ }
+ if (*prefixes_array)
+ free(*prefixes_array);
+ *prefixes_array = NULL;
+ *prefixes_num = 0;
+ }
+
+ errno = old_errno;
+}
+
+static void
+init_env_entries(char ***prefixes_array, int *prefixes_num, char *env, int warn)
+{
+ int old_errno = errno;
+ char *prefixes_env = getenv(env);
+
+ if (NULL == prefixes_env) {
+ fprintf(stderr,
+ "Sandbox error : the %s environmental variable should be defined.\n",
+ env);
+ } else {
+ char *buffer = NULL;
+ int prefixes_env_length = strlen(prefixes_env);
+ int i = 0;
+ int num_delimiters = 0;
+ char *token = NULL;
+ char *prefix = NULL;
+
+ for (i = 0; i < prefixes_env_length; i++) {
+ if (':' == prefixes_env[i]) {
+ num_delimiters++;
+ }
+ }
+
+ if (num_delimiters > 0) {
+ *prefixes_array =
+ (char **) malloc((num_delimiters + 1) * sizeof (char *));
+ buffer = strndupa(prefixes_env, prefixes_env_length);
+
+#ifdef REENTRANT_STRTOK
+ token = strtok_r(buffer, ":", &buffer);
+#else
+ token = strtok(buffer, ":");
+#endif
+
+ while ((NULL != token) && (strlen(token) > 0)) {
+ prefix = strndup(token, strlen(token));
+ (*prefixes_array)[(*prefixes_num)++] = filter_path(prefix);
+
+#ifdef REENTRANT_STRTOK
+ token = strtok_r(NULL, ":", &buffer);
+#else
+ token = strtok(NULL, ":");
+#endif
+
+ if (prefix)
+ free(prefix);
+ prefix = NULL;
+ }
+ } else if (prefixes_env_length > 0) {
+ (*prefixes_array) = (char **) malloc(sizeof (char *));
+
+ (*prefixes_array)[(*prefixes_num)++] = filter_path(prefixes_env);
+ }
+ }
+
+ errno = old_errno;
+}
+
+static char *
+filter_path(const char *path)
+{
+ int old_errno = errno;
+ char *filtered_path = (char *) malloc(SB_PATH_MAX * sizeof (char));
+
+ canonicalize_ptr(path, filtered_path);
+
+ errno = old_errno;
+
+ return filtered_path;
+}
+
+static int
+check_access(sbcontext_t * sbcontext, const char *func, const char *path)
+{
+ int old_errno = errno;
+ int result = -1;
+ int i = 0;
+ char *filtered_path = filter_path(path);
+
+ if ('/' != filtered_path[0]) {
+ errno = old_errno;
+
+ if (filtered_path)
+ free(filtered_path);
+ filtered_path = NULL;
+
+ return 0;
+ }
+
+ if ((0 == strncmp(filtered_path, "/etc/ld.so.preload", 18))
+ && (is_sandbox_pid())) {
+ result = 1;
+ }
+
+ if (-1 == result) {
+ if (NULL != sbcontext->deny_prefixes) {
+ for (i = 0; i < sbcontext->num_deny_prefixes; i++) {
+ if (NULL != sbcontext->deny_prefixes[i]) {
+ if (0 == strncmp(filtered_path,
+ sbcontext->
+ deny_prefixes[i],
+ strlen(sbcontext->deny_prefixes[i]))) {
+ result = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ if (-1 == result) {
+ if ((NULL != sbcontext->read_prefixes) &&
+ ((0 == strncmp(func, "open_rd", 7)) ||
+ (0 == strncmp(func, "popen", 5)) ||
+ (0 == strncmp(func, "opendir", 7)) ||
+ (0 == strncmp(func, "system", 6)) ||
+ (0 == strncmp(func, "execl", 5)) ||
+ (0 == strncmp(func, "execlp", 6)) ||
+ (0 == strncmp(func, "execle", 6)) ||
+ (0 == strncmp(func, "execv", 5)) ||
+ (0 == strncmp(func, "execvp", 6)) ||
+ (0 == strncmp(func, "execve", 6))
+ )
+ ) {
+ for (i = 0; i < sbcontext->num_read_prefixes; i++) {
+ if (NULL != sbcontext->read_prefixes[i]) {
+ if (0 == strncmp(filtered_path,
+ sbcontext->
+ read_prefixes[i],
+ strlen(sbcontext->read_prefixes[i]))) {
+ result = 1;
+ break;
+ }
+ }
+ }
+ } else if ((NULL != sbcontext->write_prefixes) &&
+ ((0 == strncmp(func, "open_wr", 7)) ||
+ (0 == strncmp(func, "creat", 5)) ||
+ (0 == strncmp(func, "creat64", 7)) ||
+ (0 == strncmp(func, "mkdir", 5)) ||
+ (0 == strncmp(func, "mknod", 5)) ||
+ (0 == strncmp(func, "mkfifo", 6)) ||
+ (0 == strncmp(func, "link", 4)) ||
+ (0 == strncmp(func, "symlink", 7)) ||
+ (0 == strncmp(func, "rename", 6)) ||
+ (0 == strncmp(func, "utime", 5)) ||
+ (0 == strncmp(func, "utimes", 6)) ||
+ (0 == strncmp(func, "unlink", 6)) ||
+ (0 == strncmp(func, "rmdir", 5)) ||
+ (0 == strncmp(func, "chown", 5)) ||
+ (0 == strncmp(func, "lchown", 6)) ||
+ (0 == strncmp(func, "chmod", 5)) ||
+ (0 == strncmp(func, "truncate", 8)) ||
+ (0 == strncmp(func, "ftruncate", 9)) ||
+ (0 == strncmp(func, "truncate64", 10)) ||
+ (0 == strncmp(func, "ftruncate64", 11))
+ )
+ ) {
+ struct stat tmp_stat;
+
+ for (i = 0; i < sbcontext->num_write_denied_prefixes; i++) {
+ if (NULL != sbcontext->write_denied_prefixes[i]) {
+ if (0 ==
+ strncmp(filtered_path,
+ sbcontext->
+ write_denied_prefixes
+ [i], strlen(sbcontext->write_denied_prefixes[i]))) {
+ result = 0;
+ break;
+ }
+ }
+ }
+
+ if (-1 == result) {
+ for (i = 0; i < sbcontext->num_write_prefixes; i++) {
+ if (NULL != sbcontext->write_prefixes[i]) {
+ if (0 ==
+ strncmp
+ (filtered_path,
+ sbcontext->write_prefixes[i],
+ strlen(sbcontext->write_prefixes[i]))) {
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ if (-1 == result) {
+ /* hack to prevent mkdir of existing dirs to show errors */
+ if (0 == strncmp(func, "mkdir", 5)) {
+ if (0 == stat(filtered_path, &tmp_stat)) {
+ sbcontext->show_access_violation = 0;
+ result = 0;
+ }
+ }
+
+ if (-1 == result) {
+ for (i = 0; i < sbcontext->num_predict_prefixes; i++) {
+ if (NULL != sbcontext->predict_prefixes[i]) {
+ if (0 ==
+ strncmp
+ (filtered_path,
+ sbcontext->
+ predict_prefixes[i],
+ strlen(sbcontext->predict_prefixes[i]))) {
+ sbcontext->show_access_violation = 0;
+ result = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (-1 == result) {
+ result = 0;
+ }
+
+ if (filtered_path)
+ free(filtered_path);
+ filtered_path = NULL;
+
+ errno = old_errno;
+
+ return result;
+}
+
+static int
+check_syscall(sbcontext_t * sbcontext, const char *func, const char *file)
+{
+ int old_errno = errno;
+ int result = 1;
+ struct stat log_stat;
+ char *log_path = NULL;
+ char *absolute_path = NULL;
+ char *tmp_buffer = NULL;
+ int log_file = 0;
+ struct stat debug_log_stat;
+ char *debug_log_env = NULL;
+ char *debug_log_path = NULL;
+ int debug_log_file = 0;
+ char buffer[512];
+ char *dpath = NULL;
+
+ init_wrappers();
+
+ if ('/' == file[0]) {
+ absolute_path = (char *) malloc((strlen(file) + 1) * sizeof (char));
+ sprintf(absolute_path, "%s", file);
+ } else {
+ tmp_buffer = (char *) malloc(SB_PATH_MAX * sizeof (char));
+ egetcwd(tmp_buffer, SB_PATH_MAX - 1);
+ absolute_path = (char *) malloc((strlen(tmp_buffer) + 1 + strlen(file) + 1) * sizeof (char));
+ sprintf(absolute_path, "%s/%s", tmp_buffer, file);
+ if (tmp_buffer)
+ free(tmp_buffer);
+ tmp_buffer = NULL;
+ }
+
+ log_path = getenv("SANDBOX_LOG");
+ debug_log_env = getenv("SANDBOX_DEBUG");
+ debug_log_path = getenv("SANDBOX_DEBUG_LOG");
+
+ if (((NULL == log_path) ||
+ (0 != strncmp(absolute_path, log_path, strlen(log_path)))) &&
+ ((NULL == debug_log_env) ||
+ (NULL == debug_log_path) ||
+ (0 != strncmp(absolute_path, debug_log_path, strlen(debug_log_path))))
+ && (0 == check_access(sbcontext, func, absolute_path))
+ ) {
+ if (1 == sbcontext->show_access_violation) {
+ fprintf(stderr,
+ "\e[31;01mACCESS DENIED\033[0m %s:%*s%s\n",
+ func, (int) (10 - strlen(func)), "", absolute_path);
+
+ if (NULL != log_path) {
+ sprintf(buffer, "%s:%*s%s\n", func, (int) (10 - strlen(func)), "",
+ absolute_path);
+ // log_path somehow gets corrupted. figuring out why would be good.
+ dpath = strdup(log_path);
+ if ((0 == lstat(log_path, &log_stat))
+ && (0 == S_ISREG(log_stat.st_mode))
+ ) {
+ fprintf(stderr,
+ "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n",
+ dpath);
+ } else if (0 == check_access(sbcontext, "open_wr", dpath)) {
+ unsetenv("SANDBOX_LOG");
+ fprintf(stderr,
+ "\e[31;01mSECURITY BREACH\033[0m SANDBOX_LOG %s isn't allowed via SANDBOX_WRITE\n",
+ dpath);
+ } else {
+ log_file = true_open(dpath,
+ O_APPEND | O_WRONLY
+ | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (log_file >= 0) {
+ write(log_file, buffer, strlen(buffer));
+ close(log_file);
+ }
+ }
+ free(dpath);
+ }
+ }
+
+ result = 0;
+ } else if (NULL != debug_log_env) {
+ if (NULL != debug_log_path) {
+ if (0 != strncmp(absolute_path, debug_log_path, strlen(debug_log_path))) {
+ sprintf(buffer, "%s:%*s%s\n", func, (int) (10 - strlen(func)), "",
+ absolute_path);
+ //debug_log_path somehow gets corupted, same thing as log_path above.
+ dpath = strdup(debug_log_path);
+ if ((0 == lstat(debug_log_path, &debug_log_stat))
+ && (0 == S_ISREG(debug_log_stat.st_mode))
+ ) {
+ fprintf(stderr,
+ "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n",
+ debug_log_path);
+ } else if (0 == check_access(sbcontext, "open_wr", dpath)) {
+ unsetenv("SANDBOX_DEBUG");
+ unsetenv("SANDBOX_DEBUG_LOG");
+ fprintf(stderr,
+ "\e[31;01mSECURITY BREACH\033[0m SANDBOX_DEBUG_LOG %s isn't allowed by SANDBOX_WRITE.\n",
+ dpath);
+ } else {
+ debug_log_file =
+ true_open(dpath,
+ O_APPEND | O_WRONLY |
+ O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (debug_log_file >= 0) {
+ write(debug_log_file, buffer, strlen(buffer));
+ close(debug_log_file);
+ }
+ }
+ free(dpath);
+ }
+ } else {
+ fprintf(stderr,
+ "\e[32;01mACCESS ALLOWED\033[0m %s:%*s%s\n",
+ func, (int) (10 - strlen(func)), "", absolute_path);
+ }
+ }
+
+ if (absolute_path)
+ free(absolute_path);
+ absolute_path = NULL;
+
+ errno = old_errno;
+
+ return result;
+}
+
+static int
+is_sandbox_on()
+{
+ int old_errno = errno;
+
+ /* $SANDBOX_ACTIVE is an env variable that should ONLY
+ * be used internal by sandbox.c and libsanbox.c. External
+ * sources should NEVER set it, else the sandbox is enabled
+ * in some cases when run in parallel with another sandbox,
+ * but not even in the sandbox shell.
+ *
+ * Azarah (3 Aug 2002)
+ */
+ if ((NULL != getenv("SANDBOX_ON")) &&
+ (0 == strncmp(getenv("SANDBOX_ON"), "1", 1)) &&
+ (NULL != getenv("SANDBOX_ACTIVE")) &&
+ (0 == strncmp(getenv("SANDBOX_ACTIVE"), "armedandready", 13))
+ ) {
+ errno = old_errno;
+
+ return 1;
+ } else {
+ errno = old_errno;
+
+ return 0;
+ }
+}
+
+static int
+before_syscall(const char *func, const char *file)
+{
+ int old_errno = errno;
+ int result = 1;
+ sbcontext_t sbcontext;
+
+ if (!strlen(file)) {
+ /* The file/directory does not exist */
+ errno = ENOENT;
+ return 0;
+ }
+
+ init_context(&sbcontext);
+
+ init_env_entries(&(sbcontext.deny_prefixes),
+ &(sbcontext.num_deny_prefixes), "SANDBOX_DENY", 1);
+ init_env_entries(&(sbcontext.read_prefixes),
+ &(sbcontext.num_read_prefixes), "SANDBOX_READ", 1);
+ init_env_entries(&(sbcontext.write_prefixes),
+ &(sbcontext.num_write_prefixes), "SANDBOX_WRITE", 1);
+ init_env_entries(&(sbcontext.predict_prefixes),
+ &(sbcontext.num_predict_prefixes), "SANDBOX_PREDICT", 1);
+
+ result = check_syscall(&sbcontext, func, file);
+
+ clean_env_entries(&(sbcontext.deny_prefixes), &(sbcontext.num_deny_prefixes));
+ clean_env_entries(&(sbcontext.read_prefixes), &(sbcontext.num_read_prefixes));
+ clean_env_entries(&(sbcontext.write_prefixes),
+ &(sbcontext.num_write_prefixes));
+ clean_env_entries(&(sbcontext.predict_prefixes),
+ &(sbcontext.num_predict_prefixes));
+
+ errno = old_errno;
+
+ if (0 == result) {
+ errno = EACCES;
+ }
+
+ return result;
+}
+
+static int
+before_syscall_open_int(const char *func, const char *file, int flags)
+{
+ if ((flags & O_WRONLY) || (flags & O_RDWR)) {
+ return before_syscall("open_wr", file);
+ } else {
+ return before_syscall("open_rd", file);
+ }
+}
+
+static int
+before_syscall_open_char(const char *func, const char *file, const char *mode)
+{
+ if (*mode == 'r' && ((strcmp(mode, "r") == 0) ||
+ /* The strspn accept args are known non-writable modifiers */
+ (strlen(++mode) == strspn(mode, "xbtmc")))) {
+ return before_syscall("open_rd", file);
+ } else {
+ return before_syscall("open_wr", file);
+ }
+}
+
+#include "getcwd.c"
+#include "canonicalize.c"
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-1.1/sandbox.bashrc b/src/sandbox-1.1/sandbox.bashrc
new file mode 100644
index 00000000..5986f726
--- /dev/null
+++ b/src/sandbox-1.1/sandbox.bashrc
@@ -0,0 +1,8 @@
+# Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+# Distributed under the terms of the GNU General Public License, v2 or later
+# Author : Geert Bevin <gbevin@uwyn.com>
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/sandbox.bashrc,v 1.2.4.1 2004/10/22 16:53:30 carpaski Exp $
+source /etc/profile
+export LD_PRELOAD="$SANDBOX_LIB"
+alias make="make LD_PRELOAD=$SANDBOX_LIB"
+alias su="su -c '/bin/bash -rcfile $SANDBOX_DIR/sandbox.bashrc'"
diff --git a/src/sandbox-1.1/sandbox.c b/src/sandbox-1.1/sandbox.c
new file mode 100644
index 00000000..f7a2a320
--- /dev/null
+++ b/src/sandbox-1.1/sandbox.c
@@ -0,0 +1,863 @@
+/*
+** Path sandbox for the gentoo linux portage package system, initially
+** based on the ROCK Linux Wrapper for getting a list of created files
+**
+** to integrate with bash, bash should have been built like this
+**
+** ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
+**
+** it's very important that the --enable-static-link option is NOT specified
+**
+** Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+** Distributed under the terms of the GNU General Public License, v2 or later
+** Author : Geert Bevin <gbevin@uwyn.com>
+** $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/sandbox.c,v 1.20.2.1 2004/12/01 22:14:09 carpaski Exp $
+*/
+
+/* #define _GNU_SOURCE */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "sandbox.h"
+
+int preload_adaptable = 1;
+int cleaned_up = 0;
+int print_debug = 0;
+int stop_called = 0;
+
+/* Read pids file, and load active pids into an array. Return number of pids in array */
+int
+load_active_pids(int fd, int **pids)
+{
+ char *data = NULL;
+ char *ptr = NULL, *ptr2 = NULL;
+ int my_pid;
+ int num_pids = 0;
+ long len;
+
+ pids[0] = NULL;
+
+ len = file_length(fd);
+
+ /* Allocate and zero datablock to read pids file */
+ data = (char *) malloc((len + 1) * sizeof (char));
+ memset(data, 0, len + 1);
+
+ /* Start at beginning of file */
+ lseek(fd, 0L, SEEK_SET);
+
+ /* read entire file into a buffer */
+ read(fd, data, len);
+
+ ptr = data;
+
+ /* Loop and read all pids */
+ while (1) {
+ /* Find new line */
+ ptr2 = strchr(ptr, '\n');
+ if (ptr2 == NULL)
+ break; /* No more PIDs */
+
+ /* Clear the \n. And ptr should have a null-terminated decimal string */
+ ptr2[0] = 0;
+
+ my_pid = atoi(ptr);
+
+ /* If the PID is still alive, add it to our array */
+ if ((0 != my_pid) && (0 == kill(my_pid, 0))) {
+ pids[0] = (int *) realloc(pids[0], (num_pids + 1) * sizeof (int));
+ pids[0][num_pids] = my_pid;
+ num_pids++;
+ }
+
+ /* Put ptr past the NULL we just wrote */
+ ptr = ptr2 + 1;
+ }
+
+ if (data)
+ free(data);
+ data = NULL;
+
+ return num_pids;
+}
+
+/* Read ld.so.preload file, and loads dirs into an array. Return number of entries in array */
+int
+load_preload_libs(int fd, char ***preloads)
+{
+ char *data = NULL;
+ char *ptr = NULL, *ptr2 = NULL;
+ int num_entries = 0;
+ long len;
+
+ preloads[0] = NULL;
+
+ len = file_length(fd);
+
+ /* Allocate and zero datablock to read pids file */
+ data = (char *) malloc((len + 1) * sizeof (char));
+ memset(data, 0, len + 1);
+
+ /* Start at beginning of file */
+ lseek(fd, 0L, SEEK_SET);
+
+ /* read entire file into a buffer */
+ read(fd, data, len);
+
+ ptr = data;
+
+ /* Loop and read all pids */
+ while (1) {
+ /* Find new line */
+ ptr2 = strchr(ptr, '\n');
+
+ /* Clear the \n. And ptr should have a null-terminated decimal string
+ * Don't break from the loop though because the last line may not
+ * terminated with a \n
+ */
+ if (NULL != ptr2)
+ ptr2[0] = 0;
+
+ /* If listing does not match our libname, add it to the array */
+ if ((strlen(ptr)) && (NULL == strstr(ptr, LIB_NAME))) {
+ preloads[0] =
+ (char **) realloc(preloads[0], (num_entries + 1) * sizeof (char **));
+ preloads[0][num_entries] = strdup(ptr);
+ num_entries++;
+ }
+
+ if (NULL == ptr2)
+ break; /* No more PIDs */
+
+ /* Put ptr past the NULL we just wrote */
+ ptr = ptr2 + 1;
+ }
+
+ if (data)
+ free(data);
+ data = NULL;
+
+ return num_entries;
+}
+
+void
+cleanup()
+{
+ int i = 0;
+ int success = 1;
+ int pids_file = -1, num_of_pids = 0;
+ int *pids_array = NULL;
+ char pid_string[255];
+ char *sandbox_pids_file;
+#ifdef USE_LD_SO_PRELOAD
+ int preload_file = -1, num_of_preloads = 0;
+ char preload_entry[255];
+ char **preload_array = NULL;
+#endif
+
+ /* Generate sandbox pids-file path */
+ sandbox_pids_file = get_sandbox_pids_file();
+
+ /* Remove this sandbox's bash pid from the global pids
+ * file if it has rights to adapt the ld.so.preload file */
+ if ((1 == preload_adaptable) && (0 == cleaned_up)) {
+ cleaned_up = 1;
+ success = 1;
+
+ if (print_debug)
+ printf("Cleaning up pids file.\n");
+
+ /* Stat the PIDs file, make sure it exists and is a regular file */
+ if (file_exist(sandbox_pids_file, 1) <= 0) {
+ fprintf(stderr, ">>> pids file is not a regular file");
+ success = 0;
+ /* We should really not fail if the pidsfile is missing here, but
+ * rather just exit cleanly, as there is still some cleanup to do */
+ return;
+ }
+
+ pids_file = file_open(sandbox_pids_file, "r+", 1, 0664, "portage");
+ if (-1 == pids_file) {
+ success = 0;
+ /* Nothing more to do here */
+ return;
+ }
+
+ /* Load "still active" pids into an array */
+ num_of_pids = load_active_pids(pids_file, &pids_array);
+ //printf("pids: %d\r\n", num_of_pids);
+
+#ifdef USE_LD_SO_PRELOAD
+ /* clean the /etc/ld.so.preload file if no other sandbox
+ * processes are running anymore */
+ if (1 == num_of_pids) {
+ success = 1;
+
+ if (print_debug)
+ printf("Cleaning up /etc/ld.so.preload.\n");
+
+ preload_file = file_open("/etc/ld.so.preload", "r+", 1, 0644);
+ if (-1 != preload_file) {
+ /* Load all the preload libraries into an array */
+ num_of_preloads = load_preload_libs(preload_file, &preload_array);
+ //printf("num preloads: %d\r\n", num_of_preloads);
+ /* Clear file */
+ file_truncate(preload_file);
+
+ /* store the other preload libraries back into the /etc/ld.so.preload file */
+ if (num_of_preloads > 0) {
+ for (i = 0; i < num_of_preloads; i++) {
+ sprintf(preload_entry, "%s\n", preload_array[i]);
+ if (write
+ (preload_file,
+ preload_entry,
+ strlen(preload_entry)) != strlen(preload_entry)) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+ }
+
+ /* Free memory used to store preload array */
+ for (i = 0; i < num_of_preloads; i++) {
+ if (preload_array[i])
+ free(preload_array[i]);
+ preload_array[i] = NULL;
+ }
+ if (preload_array)
+ free(preload_array);
+ preload_array = NULL;
+
+ file_close(preload_file);
+ preload_file = -1;
+ }
+ }
+#endif
+
+ file_truncate(pids_file);
+
+ /* if pids are still running, write only the running pids back to the file */
+ if (num_of_pids > 1) {
+ for (i = 0; i < num_of_pids; i++) {
+ if (pids_array[i] != getpid()) {
+ sprintf(pid_string, "%d\n", pids_array[i]);
+
+ if (write(pids_file, pid_string, strlen(pid_string)) !=
+ strlen(pid_string)) {
+ perror(">>> pids file write");
+ success = 0;
+ break;
+ }
+ }
+ }
+
+ file_close(pids_file);
+ pids_file = -1;
+ } else {
+
+ file_close(pids_file);
+ pids_file = -1;
+
+ /* remove the pidsfile, as this was the last sandbox */
+ unlink(sandbox_pids_file);
+ }
+
+ if (pids_array != NULL)
+ free(pids_array);
+ pids_array = NULL;
+ }
+
+ free(sandbox_pids_file);
+ if (0 == success)
+ return;
+}
+
+void
+stop(int signum)
+{
+ if (stop_called == 0) {
+ stop_called = 1;
+ printf("Caught signal %d in pid %d\r\n", signum, getpid());
+ cleanup();
+ } else {
+ fprintf(stderr, "Pid %d alreadly caught signal and is still cleaning up\n", getpid());
+ }
+}
+
+void
+setenv_sandbox_write(char *home_dir, char *portage_tmp_dir, char *var_tmp_dir,
+ char *tmp_dir)
+{
+ char buf[1024];
+
+ /* bzero out entire buffer then append trailing 0 */
+ memset(buf, 0, sizeof(buf));
+
+ if (!getenv(ENV_SANDBOX_WRITE)) {
+ /* these could go into make.globals later on */
+ snprintf(buf, sizeof(buf),
+ "%s:%s/.gconfd/lock:%s/.bash_history:", \
+ "/dev/zero:/dev/fd/:/dev/null:/dev/pts/:" \
+ "/dev/vc/:/dev/tty:/tmp/:" \
+ "/dev/shm/ngpt:/var/log/scrollkeeper.log:" \
+ "/usr/tmp/conftest:/usr/lib/conftest:" \
+ "/usr/lib32/conftest:/usr/lib64/conftest:" \
+ "/usr/tmp/cf:/usr/lib/cf:/usr/lib32/cf:/usr/lib64/cf",
+ home_dir, home_dir);
+
+ if (NULL == portage_tmp_dir) {
+ strncat(buf, tmp_dir, sizeof(buf));
+ strncat(buf, ":", sizeof(buf));
+ strncat(buf, var_tmp_dir, sizeof(buf));
+ strncat(buf, ":/tmp/:/var/tmp/", sizeof(buf));
+ } else {
+ strncat(buf, portage_tmp_dir, sizeof(buf));
+ strncat(buf, ":", sizeof(buf));
+ strncat(buf, tmp_dir, sizeof(buf));
+ strncat(buf, ":", sizeof(buf));
+ strncat(buf, var_tmp_dir, sizeof(buf));
+ strncat(buf, ":/tmp/:/var/tmp/", sizeof(buf));
+ }
+ buf[sizeof(buf) - 1] = '\0';
+ setenv(ENV_SANDBOX_WRITE, buf, 1);
+ }
+}
+
+void
+setenv_sandbox_predict(char *home_dir)
+{
+ char buf[1024];
+
+ memset(buf, 0, sizeof(buf));
+
+ if (!getenv(ENV_SANDBOX_PREDICT)) {
+ /* these should go into make.globals later on */
+ snprintf(buf, sizeof(buf), "%s/.:" \
+ "/usr/lib/python2.0/:" \
+ "/usr/lib/python2.1/:" \
+ "/usr/lib/python2.2/:" \
+ "/usr/lib/python2.3/:" \
+ "/usr/lib/python2.4/:" \
+ "/usr/lib/python2.5/:" \
+ "/usr/lib/python3.0/:",
+ home_dir);
+
+ buf[sizeof(buf) - 1] = '\0';
+ setenv(ENV_SANDBOX_PREDICT, buf, 1);
+ }
+}
+
+int
+print_sandbox_log(char *sandbox_log)
+{
+ int sandbox_log_file = -1;
+ char *beep_count_env = NULL;
+ int i, color, beep_count = 0;
+ long len = 0;
+ char *buffer = NULL;
+
+ sandbox_log_file = file_open(sandbox_log, "r", 1, 0664, "portage");
+ if (-1 == sandbox_log_file)
+ return 0;
+
+ len = file_length(sandbox_log_file);
+ buffer = (char *) malloc((len + 1) * sizeof (char));
+ memset(buffer, 0, len + 1);
+ read(sandbox_log_file, buffer, len);
+ file_close(sandbox_log_file);
+
+ color = ( (getenv("NOCOLOR") != NULL) ? 0 : 1);
+
+ if (color) printf("\e[31;01m");
+ printf("--------------------------- ACCESS VIOLATION SUMMARY ---------------------------");
+ if (color) printf("\033[0m");
+ if (color) printf("\e[31;01m");
+ printf("\nLOG FILE = \"%s\"", sandbox_log);
+ if (color) printf("\033[0m");
+ printf("\n\n");
+ printf("%s", buffer);
+ if (buffer)
+ free(buffer);
+ buffer = NULL;
+ printf
+ ("\e[31;01m--------------------------------------------------------------------------------\033[0m\n");
+
+ beep_count_env = getenv(ENV_SANDBOX_BEEP);
+ if (beep_count_env)
+ beep_count = atoi(beep_count_env);
+ else
+ beep_count = DEFAULT_BEEP_COUNT;
+
+ for (i = 0; i < beep_count; i++) {
+ fputc('\a', stderr);
+ if (i < beep_count - 1)
+ sleep(1);
+ }
+ return 1;
+}
+
+int
+spawn_shell(char *argv_bash[])
+{
+#ifdef USE_SYSTEM_SHELL
+ int i = 0;
+ char *sh = NULL;
+ int first = 1;
+ int ret;
+ long len = 0;
+
+ while (1) {
+ if (NULL == argv_bash[i])
+ break;
+ if (NULL != sh)
+ len = strlen(sh);
+ sh = (char *) realloc(sh, len + strlen(argv_bash[i]) + 5);
+ if (first) {
+ sh[0] = 0;
+ first = 0;
+ }
+ strcat(sh, "\"");
+ strcat(sh, argv_bash[i]);
+ strcat(sh, "\" ");
+
+ //printf("%s\n", argv_bash[i]);
+ i++;
+ }
+ printf("%s\n", sh);
+ ret = system(sh);
+ if (sh)
+ free(sh);
+ sh = NULL;
+
+ if (-1 == ret)
+ return 0;
+ return 1;
+
+#else
+# ifndef NO_FORK
+ int pid;
+ int status = 0;
+ int ret = 0;
+
+ pid = fork();
+
+ /* Child's process */
+ if (0 == pid) {
+# endif
+ execv(argv_bash[0], argv_bash);
+# ifndef NO_FORK
+ return 0;
+ } else if (pid < 0) {
+ return 0;
+ }
+ ret = waitpid(pid, &status, 0);
+ if ((-1 == ret) || (status > 0))
+ return 0;
+# endif
+ return 1;
+#endif
+}
+
+int
+main(int argc, char **argv)
+{
+ int i = 0, success = 1;
+#ifdef USE_LD_SO_PRELOAD
+ int preload_file = -1;
+#endif
+ int sandbox_log_presence = 0;
+ int sandbox_log_file = -1;
+ int pids_file = -1;
+ long len;
+
+ int *pids_array = NULL;
+ int num_of_pids = 0;
+
+ // char run_arg[255];
+ char portage_tmp_dir[PATH_MAX];
+ char var_tmp_dir[PATH_MAX];
+ char tmp_dir[PATH_MAX];
+ char sandbox_log[255];
+ char sandbox_debug_log[255];
+ char sandbox_dir[255];
+ char sandbox_lib[255];
+ char *sandbox_pids_file;
+ char sandbox_rc[255];
+ char pid_string[255];
+ char **argv_bash = NULL;
+
+ char *run_str = "-c";
+ char *home_dir = NULL;
+ char *tmp_string = NULL;
+#ifdef USE_LD_SO_PRELOAD
+ char **preload_array = NULL;
+ int num_of_preloads = 0;
+#endif
+
+ /* Only print info if called with no arguments .... */
+ if (argc < 2)
+ print_debug = 1;
+
+ if (print_debug)
+ printf
+ ("========================== Gentoo linux path sandbox ===========================\n");
+
+ /* check if a sandbox is already running */
+ if (NULL != getenv(ENV_SANDBOX_ON)) {
+ fprintf(stderr,
+ "Not launching a new sandbox instance\nAnother one is already running in this process hierarchy.\n");
+ exit(1);
+ } else {
+
+ /* determine the location of all the sandbox support files */
+ if (print_debug)
+ printf("Detection of the support files.\n");
+
+ /* Generate base sandbox path */
+ tmp_string = get_sandbox_path(argv[0]);
+ strncpy(sandbox_dir, tmp_string, 254);
+ if (tmp_string)
+ free(tmp_string);
+ tmp_string = NULL;
+ strcat(sandbox_dir, "/");
+
+ /* Generate sandbox lib path */
+ tmp_string = get_sandbox_lib(sandbox_dir);
+ strncpy(sandbox_lib, tmp_string, 254);
+ if (tmp_string)
+ free(tmp_string);
+ tmp_string = NULL;
+
+ /* Generate sandbox pids-file path */
+ sandbox_pids_file = get_sandbox_pids_file();
+
+ /* Generate sandbox bashrc path */
+ tmp_string = get_sandbox_rc(sandbox_dir);
+ strncpy(sandbox_rc, tmp_string, 254);
+ if (tmp_string)
+ free(tmp_string);
+ tmp_string = NULL;
+
+ /* verify the existance of required files */
+ if (print_debug)
+ printf("Verification of the required files.\n");
+
+#ifndef SB_HAVE_64BIT_ARCH
+ if (file_exist(sandbox_lib, 0) <= 0) {
+ fprintf(stderr, "Could not open the sandbox library at '%s'.\n",
+ sandbox_lib);
+ return -1;
+ }
+#endif
+ if (file_exist(sandbox_rc, 0) <= 0) {
+ fprintf(stderr, "Could not open the sandbox rc file at '%s'.\n",
+ sandbox_rc);
+ return -1;
+ }
+#ifdef USE_LD_SO_PRELOAD
+ /* ensure that the /etc/ld.so.preload file contains an entry for the sandbox lib */
+ if (print_debug)
+ printf("Setting up the ld.so.preload file.\n");
+
+ /* check if the /etc/ld.so.preload is a regular file */
+ if (file_exist("/etc/ld.so.preload", 1) < 0) {
+ fprintf(stderr, ">>> /etc/ld.so.preload file is not a regular file\n");
+ exit(1);
+ }
+
+ if (getuid() == 0) {
+ /* Our r+ also will create the file if it doesn't exist */
+ preload_file = file_open("/etc/ld.so.preload", "r+", 1, 0644);
+ if (-1 == preload_file) {
+ preload_adaptable = 0;
+/* exit(1);*/
+ }
+ } else {
+ /* Avoid permissions warnings if we're not root */
+ preload_adaptable = 0;
+ }
+
+ /* Only update /etc/ld.so.preload if we can write to it ... */
+ if (1 == preload_adaptable) {
+ /* Load entries of preload table */
+ num_of_preloads = load_preload_libs(preload_file, &preload_array);
+
+ /* Zero out our ld.so.preload file */
+ file_truncate(preload_file);
+
+ /* Write contents of preload file */
+ for (i = 0; i < num_of_preloads + 1; i++) {
+ /* First entry should be our sandbox library */
+ if (0 == i) {
+ if (write
+ (preload_file, sandbox_lib,
+ strlen(sandbox_lib)) != strlen(sandbox_lib)) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ } else {
+ /* Output all other preload entries */
+ if (write
+ (preload_file, preload_array[i - 1],
+ strlen(preload_array[i - 1])) != strlen(preload_array[i - 1])) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+ /* Don't forget the return character after each line! */
+ if (1 != write(preload_file, "\n", 1)) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+
+ for (i = 0; i < num_of_preloads; i++) {
+ if (preload_array[i])
+ free(preload_array[i]);
+ preload_array[i] = NULL;
+ }
+ if (preload_array)
+ free(preload_array);
+ num_of_preloads = 0;
+ preload_array = NULL;
+ }
+
+ /* That's all we needed to do with the preload file */
+ if (0 < preload_file)
+ file_close(preload_file);
+ preload_file = -1;
+#endif
+
+ /* set up the required environment variables */
+ if (print_debug)
+ printf("Setting up the required environment variables.\n");
+
+ /* Generate sandbox log full path */
+ tmp_string = get_sandbox_log();
+ strncpy(sandbox_log, tmp_string, 254);
+ if (tmp_string)
+ free(tmp_string);
+ tmp_string = NULL;
+
+ setenv(ENV_SANDBOX_LOG, sandbox_log, 1);
+
+ snprintf(sandbox_debug_log, sizeof(sandbox_debug_log), "%s%s%s",
+ DEBUG_LOG_FILE_PREFIX, pid_string, LOG_FILE_EXT);
+ setenv(ENV_SANDBOX_DEBUG_LOG, sandbox_debug_log, 1);
+
+ home_dir = getenv("HOME");
+ if (!home_dir) {
+ home_dir = "/tmp";
+ setenv("HOME", home_dir, 1);
+ }
+
+ /* drobbins: we need to expand these paths using realpath() so that PORTAGE_TMPDIR
+ * can contain symlinks (example, /var is a symlink, /var/tmp is a symlink.) Without
+ * this, access is denied to /var/tmp, hurtin' ebuilds.
+ */
+
+ { char *e;
+ e = getenv("PORTAGE_TMPDIR");
+ if ( e && ( strlen(e) < sizeof(portage_tmp_dir)-1 ) && (strlen(e) > 1) )
+ realpath(e, portage_tmp_dir);
+
+ }
+ realpath("/var/tmp", var_tmp_dir);
+ realpath("/tmp", tmp_dir);
+
+ setenv(ENV_SANDBOX_DIR, sandbox_dir, 1);
+ setenv(ENV_SANDBOX_LIB, sandbox_lib, 1);
+ setenv("LD_PRELOAD", sandbox_lib, 1);
+
+ if (!getenv(ENV_SANDBOX_DENY))
+ setenv(ENV_SANDBOX_DENY, LD_PRELOAD_FILE, 1);
+
+ if (!getenv(ENV_SANDBOX_READ))
+ setenv(ENV_SANDBOX_READ, "/", 1);
+
+ /* Set up Sandbox Write path */
+ setenv_sandbox_write(home_dir, portage_tmp_dir, var_tmp_dir, tmp_dir);
+ setenv_sandbox_predict(home_dir);
+
+ setenv(ENV_SANDBOX_ON, "1", 0);
+
+ /* if the portage temp dir was present, cd into it */
+ if (NULL != portage_tmp_dir)
+ chdir(portage_tmp_dir);
+
+ argv_bash = (char **) malloc(6 * sizeof (char *));
+ argv_bash[0] = strdup("/bin/bash");
+ argv_bash[1] = strdup("-rcfile");
+ argv_bash[2] = strdup(sandbox_rc);
+
+ if (argc < 2)
+ argv_bash[3] = NULL;
+ else
+ argv_bash[3] = strdup(run_str); /* "-c" */
+
+ argv_bash[4] = NULL; /* strdup(run_arg); */
+ argv_bash[5] = NULL;
+
+ if (argc >= 2) {
+ for (i = 1; i < argc; i++) {
+ if (NULL == argv_bash[4])
+ len = 0;
+ else
+ len = strlen(argv_bash[4]);
+
+ argv_bash[4] =
+ (char *) realloc(argv_bash[4],
+ (len + strlen(argv[i]) + 2) * sizeof (char));
+
+ if (0 == len)
+ argv_bash[4][0] = 0;
+ if (1 != i)
+ strcat(argv_bash[4], " ");
+
+ strcat(argv_bash[4], argv[i]);
+ }
+ }
+
+ /* set up the required signal handlers */
+ signal(SIGHUP, &stop);
+ signal(SIGINT, &stop);
+ signal(SIGQUIT, &stop);
+ signal(SIGTERM, &stop);
+
+ /* this one should NEVER be set in ebuilds, as it is the one
+ * private thing libsandbox.so use to test if the sandbox
+ * should be active for this pid, or not.
+ *
+ * azarah (3 Aug 2002)
+ */
+
+ setenv("SANDBOX_ACTIVE", "armedandready", 1);
+
+ /* Load our PID into PIDs file */
+ success = 1;
+ if (file_exist(sandbox_pids_file, 1) < 0) {
+ success = 0;
+ fprintf(stderr, ">>> %s is not a regular file\n", sandbox_pids_file);
+ } else {
+ pids_file = file_open(sandbox_pids_file, "r+", 1, 0664, "portage");
+ if (-1 == pids_file)
+ success = 0;
+ }
+ if (1 == success) {
+ /* Grab still active pids */
+ num_of_pids = load_active_pids(pids_file, &pids_array);
+
+ /* Zero out file */
+ file_truncate(pids_file);
+
+ /* Output active pids, and append our pid */
+ for (i = 0; i < num_of_pids + 1; i++) {
+ /* Time for our entry */
+ if (i == num_of_pids)
+ sprintf(pid_string, "%d\n", getpid());
+ else
+ sprintf(pid_string, "%d\n", pids_array[i]);
+
+ if (write(pids_file, pid_string, strlen(pid_string)) !=
+ strlen(pid_string)) {
+ perror(">>> pids file write");
+ success = 0;
+ break;
+ }
+ }
+ /* Clean pids_array */
+ if (pids_array)
+ free(pids_array);
+ pids_array = NULL;
+ num_of_pids = 0;
+
+ /* We're done with the pids file */
+ file_close(pids_file);
+ }
+
+ /* Something went wrong, bail out */
+ if (0 == success) {
+ perror(">>> pids file write");
+ exit(1);
+ }
+
+ /* STARTING PROTECTED ENVIRONMENT */
+ if (print_debug) {
+ printf("The protected environment has been started.\n");
+ printf
+ ("--------------------------------------------------------------------------------\n");
+ }
+
+ if (print_debug)
+ printf("Shell being started in forked process.\n");
+
+ /* Start Bash */
+ if (!spawn_shell(argv_bash)) {
+ if (print_debug)
+ fprintf(stderr, ">>> shell process failed to spawn\n");
+ success = 0;
+ }
+
+ /* Free bash stuff */
+ for (i = 0; i < 6; i++) {
+ if (argv_bash[i])
+ free(argv_bash[i]);
+ argv_bash[i] = NULL;
+ }
+ if (argv_bash)
+ free(argv_bash);
+ argv_bash = NULL;
+
+ if (print_debug)
+ printf("Cleaning up sandbox process\n");
+
+ cleanup();
+
+ if (print_debug) {
+ printf
+ ("========================== Gentoo linux path sandbox ===========================\n");
+ printf("The protected environment has been shut down.\n");
+ }
+
+ if (file_exist(sandbox_log, 0)) {
+ sandbox_log_presence = 1;
+ success = 1;
+ if (!print_sandbox_log(sandbox_log))
+ success = 0;
+
+#if 0
+ if (!success)
+ exit(1);
+#endif
+
+ sandbox_log_file = -1;
+ } else if (print_debug) {
+ printf
+ ("--------------------------------------------------------------------------------\n");
+ }
+
+ if ((sandbox_log_presence) || (!success))
+ return 1;
+ else
+ return 0;
+ }
+}
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-1.1/sandbox.h b/src/sandbox-1.1/sandbox.h
new file mode 100644
index 00000000..67a415dd
--- /dev/null
+++ b/src/sandbox-1.1/sandbox.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2002 Brad House <brad@mainstreetsoftworks.com>,
+ * Possibly based on code from Geert Bevin, Uwyn, http://www.uwyn.com
+ * Distributed under the terms of the GNU General Public License, v2 or later
+ * Author: Brad House <brad@mainstreetsoftworks.com>
+ *
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/sandbox.h,v 1.5.2.1 2004/10/22 16:53:30 carpaski Exp $
+ */
+
+#ifndef __SANDBOX_H__
+#define __SANDBOX_H__
+
+/* Uncomment below to use flock instead of fcntl (POSIX way) to lock/unlock files */
+/* #define USE_FLOCK */
+
+/* Uncomment below to use system() to execute the shell rather than execv */
+/* #define USE_SYSTEM_SHELL */
+
+/* Uncomment below to use /etc/ld.so.preload (could be very intrusive!!) */
+/* #define USE_LD_SO_PRELOAD */
+
+/* Uncommend to not have the protected shell forked, just run in parent process */
+/* ONLY FOR DEBUGGING PURPOSES!! (strace needs it like that) */
+/* #define NO_FORK */
+
+#define LD_PRELOAD_FILE "/etc/ld.so.preload"
+#define LIB_NAME "libsandbox.so"
+#define BASHRC_NAME "sandbox.bashrc"
+#define PIDS_FILE "/tmp/sandboxpids.tmp"
+#define LOG_FILE_PREFIX "/tmp/sandbox-"
+#define DEBUG_LOG_FILE_PREFIX "/tmp/sandbox-debug-"
+#define LOG_FILE_EXT ".log"
+
+#define ENV_SANDBOX_DEBUG_LOG "SANDBOX_DEBUG_LOG"
+#define ENV_SANDBOX_LOG "SANDBOX_LOG"
+#define ENV_SANDBOX_DIR "SANDBOX_DIR"
+#define ENV_SANDBOX_LIB "SANDBOX_LIB"
+
+#define ENV_SANDBOX_DENY "SANDBOX_DENY"
+#define ENV_SANDBOX_READ "SANDBOX_READ"
+#define ENV_SANDBOX_WRITE "SANDBOX_WRITE"
+#define ENV_SANDBOX_PREDICT "SANDBOX_PREDICT"
+
+#define ENV_SANDBOX_ON "SANDBOX_ON"
+#define ENV_SANDBOX_BEEP "SANDBOX_BEEP"
+
+#define DEFAULT_BEEP_COUNT 3
+
+char *get_sandbox_path(char *argv0);
+char *get_sandbox_lib(char *sb_path);
+char *get_sandbox_pids_file(void);
+char *get_sandbox_rc(char *sb_path);
+char *get_sandbox_log();
+char *sb_dirname(const char *path);
+int file_getmode(char *mode);
+long file_tell(int fp);
+int file_lock(int fd, int lock, char *filename);
+int file_unlock(int fd);
+int file_locktype(char *mode);
+int file_open(char *filename, char *mode, int perm_specified, ...);
+void file_close(int fd);
+long file_length(int fd);
+int file_truncate(int fd);
+int file_exist(char *filename, int checkmode);
+
+#endif
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-1.1/sandbox_futils.c b/src/sandbox-1.1/sandbox_futils.c
new file mode 100644
index 00000000..f9ddb342
--- /dev/null
+++ b/src/sandbox-1.1/sandbox_futils.c
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2002 Brad House <brad@mainstreetsoftworks.com>
+ * Distributed under the terms of the GNU General Public License, v2 or later
+ * Author: Brad House <brad@mainstreetsoftworks.com>
+ *
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-1.1/Attic/sandbox_futils.c,v 1.11.2.1 2004/11/03 13:12:55 ferringb Exp $
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <grp.h>
+#include <pwd.h>
+
+#include "sandbox.h"
+
+/* BEGIN Prototypes */
+int file_security_check(char *filename);
+/* END Prototypes */
+
+
+/* glibc modified getcwd() functions */
+char *egetcwd(char *, size_t);
+
+char *
+get_sandbox_path(char *argv0)
+{
+ char path[255];
+ char *cwd = NULL;
+
+ memset(path, 0, sizeof(path));
+ /* ARGV[0] specifies full path */
+ if (argv0[0] == '/') {
+ strncpy(path, argv0, sizeof(path)-1);
+
+ /* ARGV[0] specifies relative path */
+ } else {
+ egetcwd(cwd, sizeof(path)-2);
+ snprintf(path, sizeof(path), "%s/%s", cwd, argv0);
+ if (cwd)
+ free(cwd);
+ cwd = NULL;
+ }
+
+ /* Return just directory */
+ return (sb_dirname(path));
+}
+
+char *
+get_sandbox_lib(char *sb_path)
+{
+ char path[255];
+
+#ifdef SB_HAVE_64BIT_ARCH
+ snprintf(path, sizeof(path), "%s", LIB_NAME);
+#else
+ snprintf(path, sizeof(path), "/lib/%s", LIB_NAME);
+ if (file_exist(path, 0) <= 0) {
+ snprintf(path, sizeof(path), "%s%s", sb_path, LIB_NAME);
+ }
+#endif
+ return (strdup(path));
+}
+
+char *
+get_sandbox_pids_file(void)
+{
+ if (0 < getenv("SANDBOX_PIDS_FILE")) {
+ return (strdup(getenv("SANDBOX_PIDS_FILE")));
+ }
+ return (strdup(PIDS_FILE));
+}
+
+char *
+get_sandbox_rc(char *sb_path)
+{
+ char path[255];
+
+ snprintf(path, sizeof(path), "/usr/lib/portage/lib/%s", BASHRC_NAME);
+ if (file_exist(path, 0) <= 0) {
+ snprintf(path, sizeof(path), "%s%s", sb_path, BASHRC_NAME);
+ }
+ return (strdup(path));
+}
+
+char *
+get_sandbox_log()
+{
+ char path[255];
+ char *sandbox_log_env = NULL;
+
+ /* THIS CHUNK BREAK THINGS BY DOING THIS:
+ * SANDBOX_LOG=/tmp/sandbox-app-admin/superadduser-1.0.7-11063.log
+ */
+
+ sandbox_log_env = getenv(ENV_SANDBOX_LOG);
+ snprintf(path, sizeof(path)-1, "%s%s%s%d%s", LOG_FILE_PREFIX,
+ ( sandbox_log_env == NULL ? "" : sandbox_log_env ),
+ ( sandbox_log_env == NULL ? "" : "-" ),
+ getpid(), LOG_FILE_EXT);
+ return (strdup(path));
+}
+
+/* Obtain base directory name. Do not allow trailing / */
+char *
+sb_dirname(const char *path)
+{
+ char *ret = NULL;
+ char *ptr = NULL;
+ int loc = 0, i;
+ int cut_len = -1;
+
+ /* don't think NULL will ever be passed, but just in case */
+ if (NULL == path)
+ return (strdup("."));
+
+ /* Grab pointer to last slash */
+ ptr = strrchr(path, '/');
+ if (NULL == ptr) {
+ return (strdup("."));
+ }
+
+ /* decimal location of pointer */
+ loc = ptr - path;
+
+ /* Remove any trailing slash */
+ for (i = loc - 1; i >= 0; i--) {
+ if (path[i] != '/') {
+ cut_len = i + 1; /* make cut_len the length of the string to keep */
+ break;
+ }
+ }
+
+ /* It could have been just a plain /, return a 1byte 0 filled string */
+ if (-1 == cut_len)
+ return (strdup(""));
+
+ /* Allocate memory, and return the directory */
+ ret = (char *) malloc((cut_len + 1) * sizeof (char));
+ memcpy(ret, path, cut_len);
+ ret[cut_len] = 0;
+
+ return (ret);
+}
+
+/*
+char* dirname(const char* path)
+{
+ char* base = NULL;
+ unsigned int length = 0;
+
+ base = strrchr(path, '/');
+ if (NULL == base)
+ {
+ return strdup(".");
+ }
+ while (base > path && *base == '/')
+ {
+ base--;
+ }
+ length = (unsigned int) 1 + base - path;
+
+ base = malloc(sizeof(char)*(length+1));
+ memmove(base, path, length);
+ base[length] = 0;
+
+ return base;
+}*/
+
+/* Convert text (string) modes to integer values */
+int
+file_getmode(char *mode)
+{
+ int mde = 0;
+ if (0 == strcasecmp(mode, "r+")) {
+ mde = O_RDWR | O_CREAT;
+ } else if (0 == strcasecmp(mode, "w+")) {
+ mde = O_RDWR | O_CREAT | O_TRUNC;
+ } else if (0 == strcasecmp(mode, "a+")) {
+ mde = O_RDWR | O_CREAT | O_APPEND;
+ } else if (0 == strcasecmp(mode, "r")) {
+ mde = O_RDONLY;
+ } else if (0 == strcasecmp(mode, "w")) {
+ mde = O_WRONLY | O_CREAT | O_TRUNC;
+ } else if (0 == strcasecmp(mode, "a")) {
+ mde = O_WRONLY | O_APPEND | O_CREAT;
+ } else {
+ mde = O_RDONLY;
+ }
+ return (mde);
+}
+
+/* Get current position in file */
+long
+file_tell(int fp)
+{
+ return (lseek(fp, 0L, SEEK_CUR));
+}
+
+/* lock the file, preferrably the POSIX way */
+int
+file_lock(int fd, int lock, char *filename)
+{
+ int err;
+#ifdef USE_FLOCK
+ if (flock(fd, lock) < 0) {
+ err = errno;
+ fprintf(stderr, ">>> %s flock file lock: %s\n", filename, strerror(err));
+ return 0;
+ }
+#else
+ struct flock fl;
+ fl.l_type = lock;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0L;
+ fl.l_len = 0L;
+ fl.l_pid = getpid();
+ if (fcntl(fd, F_SETLKW, &fl) < 0) {
+ err = errno;
+ fprintf(stderr, ">>> %s fcntl file lock: %s\n", filename, strerror(err));
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+/* unlock the file, preferrably the POSIX way */
+int
+file_unlock(int fd)
+{
+#ifdef USE_FLOCK
+ if (flock(fd, LOCK_UN) < 0) {
+ perror(">>> flock file unlock");
+ return 0;
+ }
+#else
+ struct flock fl;
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0L;
+ fl.l_len = 0L;
+ fl.l_pid = getpid();
+ if (fcntl(fd, F_SETLKW, &fl) < 0) {
+ perror(">>> fcntl file unlock");
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+/* Auto-determine from how the file was opened, what kind of lock to lock
+ * the file with
+ */
+int
+file_locktype(char *mode)
+{
+#ifdef USE_FLOCK
+ if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+'))
+ || (NULL != strchr(mode, 'a')))
+ return (LOCK_EX);
+ return (LOCK_SH);
+#else
+ if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+'))
+ || (NULL != strchr(mode, 'a')))
+ return (F_WRLCK);
+ return (F_RDLCK);
+#endif
+}
+
+/* Use standard fopen style modes to open the specified file. Also auto-determines and
+ * locks the file either in shared or exclusive mode depending on opening mode
+ */
+int
+file_open(char *filename, char *mode, int perm_specified, ...)
+{
+ int fd;
+ char error[250];
+ va_list ap;
+ int perm;
+ char *group = NULL;
+ struct group *group_struct;
+
+ file_security_check(filename);
+
+ if (perm_specified) {
+ va_start(ap, perm_specified);
+ perm = va_arg(ap, int);
+ group = va_arg(ap, char *);
+ va_end(ap);
+ }
+ fd = open(filename, file_getmode(mode));
+ file_security_check(filename);
+ if (-1 == fd) {
+ snprintf(error, sizeof(error), ">>> %s file mode: %s open", filename, mode);
+ perror(error);
+ return (fd);
+ }
+ if (perm_specified) {
+ if (fchmod(fd, 0664) && (0 == getuid())) {
+ snprintf(error, sizeof(error), ">>> Could not set mode: %s", filename);
+ perror(error);
+ }
+ }
+ if (NULL != group) {
+ group_struct = getgrnam(group);
+ if (NULL == group) {
+ snprintf(error, sizeof(error), ">>> Could not get grp number: %s", group);
+ perror(error);
+ } else {
+ if (fchown(fd, -1, group_struct->gr_gid) && (0 == getuid())) {
+ snprintf(error, sizeof(error), ">>> Could not set group: %s", filename);
+ perror(error);
+ }
+ }
+ }
+ /* Only lock the file if opening succeeded */
+ if (-1 != fd) {
+ if(file_security_check(filename) != 0) {
+ /* Security violation occured between the last check and the */
+ /* creation of the file. As SpanKY pointed out there is a race */
+ /* condition here, so if there is a problem here we'll mesg and */
+ /* bail out to avoid it until we can work and test a better fix. */
+ fprintf(stderr, "\n\nSECURITY RACE CONDITION: Problem recurred after creation!\nBAILING OUT\n\n");
+ exit(127);
+ }
+
+ if (0 == file_lock(fd, file_locktype(mode), filename)) {
+ close(fd);
+ return -1;
+ }
+ } else {
+ snprintf(error, sizeof(error), ">>> %s file mode:%s open", filename, mode);
+ perror(error);
+ }
+ return (fd);
+}
+
+/* Close and unlock file */
+void
+file_close(int fd)
+{
+ if (-1 != fd) {
+ file_unlock(fd);
+ close(fd);
+ }
+}
+
+/* Return length of file */
+long
+file_length(int fd)
+{
+ long pos, len;
+ pos = file_tell(fd);
+ len = lseek(fd, 0L, SEEK_END);
+ lseek(fd, pos, SEEK_SET);
+ return (len);
+}
+
+/* Zero out file */
+int
+file_truncate(int fd)
+{
+ lseek(fd, 0L, SEEK_SET);
+ if (ftruncate(fd, 0) < 0) {
+ perror(">>> file truncate");
+ return 0;
+ }
+ return 1;
+}
+
+/* Check to see if a file exists Return: 1 success, 0 file not found, -1 error */
+int
+file_exist(char *filename, int checkmode)
+{
+ struct stat mystat;
+
+ /* Verify file exists and is regular file (not sym link) */
+ if (checkmode) {
+ if (-1 == lstat(filename, &mystat)) {
+ /* file doesn't exist */
+ if (ENOENT == errno) {
+ return 0;
+ } else { /* permission denied or other error */
+ perror(">>> stat file");
+ return -1;
+ }
+ }
+ if (!S_ISREG(mystat.st_mode))
+ return -1;
+
+ /* Just plain verify the file exists */
+ } else {
+ if (-1 == stat(filename, &mystat)) {
+ /* file does not exist */
+ if (ENOENT == errno) {
+ return 0;
+ } else { /* permission denied or other error */
+ perror(">>> stat file");
+ return -1;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int file_security_check(char *filename) { /* 0 == fine, >0 == problem */
+ struct stat stat_buf;
+ struct group *group_buf;
+ struct passwd *passwd_buf;
+
+ passwd_buf = getpwnam("portage");
+ group_buf = getgrnam("portage");
+
+ if((lstat(filename, &stat_buf) == -1) && (errno == ENOENT)) {
+ /* Doesn't exist. */
+ return 0;
+ }
+ else {
+ if((stat_buf.st_nlink) > 1) { /* Security: We are handlinked... */
+ if(unlink(filename)) {
+ fprintf(stderr,
+ "Unable to delete file in security violation (hardlinked): %s\n",
+ filename);
+ exit(127);
+ }
+ fprintf(stderr,
+ "File in security violation (hardlinked): %s\n",
+ filename);
+ return 1;
+ }
+ else if(S_ISLNK(stat_buf.st_mode)) { /* Security: We are a symlink? */
+ fprintf(stderr,
+ "File in security violation (symlink): %s\n",
+ filename);
+ exit(127);
+ }
+ else if(0 == S_ISREG(stat_buf.st_mode)) { /* Security: special file */
+ fprintf(stderr,
+ "File in security violation (not regular): %s\n",
+ filename);
+ exit(127);
+ }
+ else if(stat_buf.st_mode & S_IWOTH) { /* Security: We are o+w? */
+ if(unlink(filename)) {
+ fprintf(stderr,
+ "Unable to delete file in security violation (world write): %s\n",
+ filename);
+ exit(127);
+ }
+ fprintf(stderr,
+ "File in security violation (world write): %s\n",
+ filename);
+ return 1;
+ }
+ else if(
+ !((stat_buf.st_uid == 0) || (stat_buf.st_uid == getuid()) || ((passwd_buf!=NULL) && (stat_buf.st_uid == passwd_buf->pw_uid))) ||
+ !((stat_buf.st_gid == 0) || (stat_buf.st_gid == getgid()) || ((group_buf !=NULL) && (stat_buf.st_gid == group_buf->gr_gid)))
+ ) { /* Security: Owner/Group isn't right. */
+
+ /* uid = 0 or myuid or portage */
+ /* gid = 0 or mygid or portage */
+
+ if(0) {
+ fprintf(stderr, "--1: %d,%d,%d,%d\n--2: %d,%d,%d,%d\n",
+
+ (stat_buf.st_uid == 0),
+ (stat_buf.st_uid == getuid()),
+ (passwd_buf!=NULL),
+ (passwd_buf!=NULL)? (stat_buf.st_uid == passwd_buf->pw_uid) : -1,
+
+ (stat_buf.st_gid == 0),
+ (stat_buf.st_gid == getgid()),
+ (group_buf !=NULL),
+ (group_buf !=NULL)? (stat_buf.st_gid == group_buf->gr_gid) : -1);
+ }
+
+ /* manpage: "The return value may point to static area" */
+ /* DO NOT ACTUALLY FREE THIS... It'll segfault. */
+ /* if(passwd_buf != NULL) { free(passwd_buf); } */
+ /* if(group_buf != NULL) { free(group_buf); } */
+
+ if(unlink(filename)) {
+ fprintf(stderr,
+ "Unable to delete file in security violation (bad owner/group): %s\n",
+ filename);
+ exit(127);
+ }
+ fprintf(stderr,
+ "File in security violation (bad owner/group): %s\n",
+ filename);
+ return 1;
+ }
+ } /* Stat */
+ return 0;
+}
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-dev/ChangeLog b/src/sandbox-dev/ChangeLog
new file mode 100644
index 00000000..3a052a12
--- /dev/null
+++ b/src/sandbox-dev/ChangeLog
@@ -0,0 +1,91 @@
+# ChangeLog for Path Sandbox
+# Copyright 1999-2004 Gentoo Foundation; Distributed under the GPL v2
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/ChangeLog,v 1.9 2004/10/04 14:08:46 vapier Exp $
+
+ 16 Dec 2002; J Robert Ray <jrray@gentoo.org> Makefile libsandbox.c :
+
+ Instead of parsing the SANDBOX_* env variables on each syscall, save the
+ result in a global sbcontext pointer and cache the value of the env vars
+ to detect later on if they have changed and need to be re-parsed. Works
+ around bug 233.
+
+ 16 Dec 2002; Martin Schlemmer <azarah@gentoo.org> create-localdecls :
+
+ Fix memory leak for mips, bug #12236. Thanks to Torgeir Hansen <torgeir@trenger.ro>
+ for this fix.
+
+ 4 Dec 2002; J Robert Ray <jrray@gentoo.org> sandbox.h sandbox_futils.c :
+
+ sandbox_futils defined a dirname() function that was masking the same
+ function in glibc and was broken (e.g.: SANDBOX_DIR was being set to
+ '/usr/lib/portage/bi/'). Fixed function to return expected results and
+ renamed it to sb_dirname() to no longer mask the glibc function. Closes bug
+ 11231.
+
+ 4 Dec 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Fix a segfault in libsandbox.c if canonicalize() was called with
+ first parameter = NULL.
+
+ 1 Sep 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Fix my braindead 'return 1;' in a void function. Updated sandbox.c,
+ cleanup() for this.
+
+ Change cleanup() in sandbox.c not to exit with fail status if
+ the pidsfile is missing. We really should still display sandbox
+ violations if they occured.
+
+ 31 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Update cleanup() in sandbox.c to remove the PIDSFILE if this is
+ the last sandbox running.
+
+ 25 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Major cleanups to mainly libsandbox.c again.
+
+ 22 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Add copyrights to sandbox.h and sandbox_futils.h. If wrong, the
+ parties involved should please contact me so that we can fix it.
+
+ Add opendir wrapper to libsandbox.c.
+
+ 21 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Do some more cleanups to ecanonicalize(), as it dropped filenames in
+ rare cases (after my symlink cleanups), and caused glibc to bork.
+ These fixes went into canonicalize.c.
+
+ 20 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Fix spawn_shell() and main() in sandbox.c to properly return fail
+ status.
+
+ 19 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ The new canonicalize() function in libsandbox.c also resolved symlinks,
+ which caused on cleaning sandbox errors if the symlink pointed to a
+ file in the live root. Ripped out canonicalize() and realpath() from
+ glibc; removed the symlink stuff, and changed them to ecanonicalize()
+ and erealpath().
+
+ 18 Aug 2002; Martin Schlemmer <azarah@gentoo.org> :
+
+ Ripped out all the wrappers, and implemented those of InstallWatch.
+ Losts of cleanups and bugfixes. Implement a execve that forces
+ $LIBSANDBOX in $LD_PRELOAD. We can now thus do away with the feared
+ /etc/ld.so.preload (*g*) ... Made the needed changes to sandbox.c,
+ sandbox.h and sandbox_futils.c. Rewrote the Makefile for most
+ parts; it now have an install target.
+
+ Reformat the whole thing to look somewhat like the reworked sandbox.c
+ and new sandbox.h and sandbox_futils.c from:
+
+ Brad House <brad@mainstreetsoftworks.com>.
+
+ Additional Copyrights now due to the InstallWatch code:
+
+ Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>
+
diff --git a/src/sandbox-dev/Makefile b/src/sandbox-dev/Makefile
new file mode 100644
index 00000000..83b00e30
--- /dev/null
+++ b/src/sandbox-dev/Makefile
@@ -0,0 +1,62 @@
+# Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+# Distributed under the terms of the GNU General Public License, v2 or later
+# Author : Geert Bevin <gbevin@uwyn.com>
+#
+# Modified 15 Apr 2002 Jon Nelson <jnelson@gentoo.org>
+# Clean up Makefile somewhat, and use make's implicit rules
+#
+# Modified 19 Aug 2002; Martin Schlemmer <azarah@gentoo.org>
+# Major rewrite to support new stuff
+#
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/Makefile,v 1.3 2002/12/16 22:28:05 jrray Exp $
+
+CC = gcc
+LD = ld
+CFLAGS =
+OBJ_DEFINES = -D_GNU_SOURCE -DPIC -fPIC -D_REENTRANT
+LIBS =
+LDFLAGS =
+DESTDIR =
+
+TARGETS = libsandbox.so sandbox
+
+all: $(TARGETS)
+
+sandbox: sandbox.o sandbox_futils.o
+ $(CC) $^ -ldl -lc -o $@
+
+sandbox.o: sandbox.c sandbox.h
+ $(CC) $(CFLAGS) -Wall -c sandbox.c
+
+sandbox_futils.o: sandbox_futils.c sandbox.h
+ $(CC) $(CFLAGS) -Wall -c $(OBJ_DEFINES) sandbox_futils.c
+
+libsandbox.so: libsandbox.o sandbox_futils.o canonicalize.o
+ $(LD) $^ -shared -fPIC -ldl -lc -lpthread -o $@
+
+libsandbox.o: libsandbox.c localdecls.h
+ $(CC) $(CFLAGS) -Wall -c $(OBJ_DEFINES) libsandbox.c
+
+canonicalize.o: canonicalize.c
+ $(CC) $(CFLAGS) -Wall -c $(OBJ_DEFINES) canonicalize.c
+
+localdecls.h: create-localdecls libctest.c
+ ./create-localdecls
+
+
+install: all
+ install -d -m 0755 $(DESTDIR)/lib
+ install -d -m 0755 $(DESTDIR)/usr/lib/portage/bin
+ install -d -m 0755 $(DESTDIR)/usr/lib/portage/lib
+ install -m 0755 libsandbox.so $(DESTDIR)/lib
+ install -m 0755 sandbox $(DESTDIR)/usr/lib/portage/bin
+ install -m 0644 sandbox.bashrc $(DESTDIR)/usr/lib/portage/lib
+
+
+clean:
+ rm -f $(TARGETS)
+ rm -f *.o *~ core
+ rm -f localdecls.h
+
+
+# vim:expandtab noai:cindent ai
diff --git a/src/sandbox-dev/canonicalize.c b/src/sandbox-dev/canonicalize.c
new file mode 100644
index 00000000..7ecd57ec
--- /dev/null
+++ b/src/sandbox-dev/canonicalize.c
@@ -0,0 +1,194 @@
+/* Return the canonical absolute name of a given file.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/*
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/canonicalize.c,v 1.2 2002/08/26 03:28:30 azarah Exp $
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stddef.h>
+
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+/* Return the canonical absolute name of file NAME. A canonical name
+ does not contain any `.', `..' components nor any repeated path
+ separators ('/') or symlinks. All path components must exist. If
+ RESOLVED is null, the result is malloc'd; otherwise, if the
+ canonical name is PATH_MAX chars or more, returns null with `errno'
+ set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
+ returns the name in RESOLVED. If the name cannot be resolved and
+ RESOLVED is non-NULL, it contains the path of the first component
+ that cannot be resolved. If the path can be resolved, RESOLVED
+ holds the same value as the value returned. */
+
+/* Modified: 19 Aug 2002; Martin Schlemmer <azarah@gentoo.org>
+ *
+ * Cleaned up unneeded stuff, and change so that it will not
+ * resolve symlinks. Also prepended a 'e' to functions that
+ * I did not rip out.
+ *
+ */
+
+static char *
+ecanonicalize (const char *name, char *resolved)
+{
+ char *rpath, *dest;
+ const char *start, *end, *rpath_limit;
+ long int path_max;
+
+ if (name == NULL)
+ {
+ /* As per Single Unix Specification V2 we must return an error if
+ either parameter is a null pointer. We extend this to allow
+ the RESOLVED parameter to be NULL in case the we are expected to
+ allocate the room for the return value. */
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ if (name[0] == '\0')
+ {
+ /* As per Single Unix Specification V2 we must return an error if
+ the name argument points to an empty string. */
+ __set_errno (ENOENT);
+ return NULL;
+ }
+
+#ifdef PATH_MAX
+ path_max = PATH_MAX;
+#else
+ path_max = pathconf (name, _PC_PATH_MAX);
+ if (path_max <= 0)
+ path_max = 1024;
+#endif
+
+ rpath = resolved ? alloca (path_max) : malloc (path_max);
+ rpath_limit = rpath + path_max;
+
+ if (name[0] != '/')
+ {
+ if (!getcwd (rpath, path_max))
+ {
+ rpath[0] = '\0';
+ goto error;
+ }
+ dest = strchr (rpath, '\0');
+ }
+ else
+ {
+ rpath[0] = '/';
+ dest = rpath + 1;
+ }
+
+ for (start = end = name; *start; start = end)
+ {
+ /* Skip sequence of multiple path-separators. */
+ while (*start == '/')
+ ++start;
+
+ /* Find end of path component. */
+ for (end = start; *end && *end != '/'; ++end)
+ /* Nothing. */;
+
+ if (end - start == 0)
+ break;
+ else if (end - start == 1 && start[0] == '.')
+ /* nothing */;
+ else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ {
+ /* Back up to previous component, ignore if at root already. */
+ if (dest > rpath + 1)
+ while ((--dest)[-1] != '/');
+ }
+ else
+ {
+ size_t new_size;
+
+ if (dest[-1] != '/')
+ *dest++ = '/';
+
+ if (dest + (end - start) >= rpath_limit)
+ {
+ ptrdiff_t dest_offset = dest - rpath;
+
+ if (resolved)
+ {
+ __set_errno (ENAMETOOLONG);
+ if (dest > rpath + 1)
+ dest--;
+ *dest = '\0';
+ goto error;
+ }
+ new_size = rpath_limit - rpath;
+ if (end - start + 1 > path_max)
+ new_size += end - start + 1;
+ else
+ new_size += path_max;
+ rpath = realloc (rpath, new_size);
+ rpath_limit = rpath + new_size;
+ if (rpath == NULL)
+ return NULL;
+
+ dest = rpath + dest_offset;
+ }
+
+ dest = __mempcpy (dest, start, end - start);
+ *dest = '\0';
+
+ }
+ }
+#if 0
+ if (dest > rpath + 1 && dest[-1] == '/')
+ --dest;
+#endif
+ *dest = '\0';
+
+ return resolved ? memcpy (resolved, rpath, dest - rpath + 1) : rpath;
+
+error:
+ if (resolved)
+ strcpy (resolved, rpath);
+ else
+ free (rpath);
+ return NULL;
+}
+
+
+char *
+erealpath (const char *name, char *resolved)
+{
+ if (resolved == NULL)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ return ecanonicalize (name, resolved);
+}
+
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-dev/create-localdecls b/src/sandbox-dev/create-localdecls
new file mode 100755
index 00000000..5cb1a4d0
--- /dev/null
+++ b/src/sandbox-dev/create-localdecls
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+# This is a quick'n'dirty hack to make the program behave correctly
+# under different systems.
+# Example:
+# when using libc5, (f)trucate's offset argument type is size_t with
+# libc5, but it's off_t with libc6 (glibc2).
+#
+# Uhm... time to learn GNU autoconf :-)
+#
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/create-localdecls,v 1.2 2002/12/16 19:19:27 azarah Exp $
+
+OUTFILE='localdecls.h'
+
+# if your arch needs to dlopen() glibc, add it here separated by space :]
+BROKEN_RTLD_ARCHLIST="mips"
+
+echo '/* This file is automatically generated *' > $OUTFILE
+echo ' * Modify create-localdecls instead of this */' >> $OUTFILE
+echo >> $OUTFILE
+echo '#ifndef __LOCALDECLS_H_' >> $OUTFILE
+echo '#define __LOCALDECLS_H_' >> $OUTFILE
+echo >> $OUTFILE
+
+###
+###
+###
+
+echo -n 'Checking truncate argument type... '
+if grep -q 'truncate.*size_t' /usr/include/unistd.h ; then
+ echo 'size_t'
+ echo '#define TRUNCATE_T size_t' >> $OUTFILE
+else
+ echo 'off_t' # At least, I HOPE it's off_t :-)
+ echo '#define TRUNCATE_T off_t' >> $OUTFILE
+fi
+
+###
+###
+###
+
+echo -n 'Checking libc version... '
+gcc -Wall -o libctest libctest.c
+VERSION=`ldd libctest | grep libc\\.so | awk '{print $1}'`
+rm libctest
+echo $VERSION
+echo "#define LIBC_VERSION \"$VERSION\"" >> $OUTFILE
+if test "$VERSION" = 'libc.so.5' ; then
+ echo '#define BROKEN_RTLD_NEXT' >> $OUTFILE
+ echo '#define LIBC 5' >> $OUTFILE
+else
+ # for the arch's that need to dlopen() libc to fetch real funcs!
+ # 16.12.02 -Torgeir Hansen <torgeir@trenger.ro>
+ MYARCH=`/bin/uname -m`
+ for x in $BROKEN_RTLD_ARCHLIST; do
+ if [ $x = $MYARCH ]; then
+ echo '#define BROKEN_RTLD_NEXT' >> $OUTFILE
+ fi
+ done
+
+fi
+
+if test "$VERSION" = 'libc.so.6' ; then
+ echo -n 'Checking glibc subversion... '
+ tmp="`ldd /bin/sh | grep libc.so 2> /dev/null`"
+ LibcPath=`expr "$tmp" : '[^/]*\(/[^ ]*\)'`
+ tmp="`strings $LibcPath | grep -i 'c library'`"
+ OsLibcMajor=`expr "$tmp" : '.* \([0-9][0-9]*\)'`
+ OsLibcMinor=`expr "$tmp" : '.* [0-9][0-9]*\.\([0-9][0-9]*\)'`
+ case "$OsLibcMajor" in
+ 2)
+ # 2 is the glibc version
+ case "$OsLibcMinor" in
+ 0)
+ echo '#define GLIBC_MINOR 0' >> $OUTFILE
+ SUBVERSION='glibc-2.0' ;;
+ 1)
+ echo '#define GLIBC_MINOR 1' >> $OUTFILE
+ SUBVERSION='glibc-2.1' ;;
+ 2)
+ echo '#define GLIBC_MINOR 2' >> $OUTFILE
+ SUBVERSION='glibc-2.2' ;;
+ *)
+ echo 'Treated as glibc >= 2.1 (finger crossed)'
+ echo '#define GLIBC_MINOR 1' >> $OUTFILE
+ SUBVERSION='glibc-2.1' ;;
+ esac
+ ;;
+ esac
+fi
+
+echo >> $OUTFILE
+echo '#endif' >> $OUTFILE
+echo
+
diff --git a/src/sandbox-dev/libctest.c b/src/sandbox-dev/libctest.c
new file mode 100644
index 00000000..5fc92b50
--- /dev/null
+++ b/src/sandbox-dev/libctest.c
@@ -0,0 +1,6 @@
+/* Dummy program to check your libc version */
+
+int main(void) {
+ return 0;
+}
+
diff --git a/src/sandbox-dev/libsandbox.c b/src/sandbox-dev/libsandbox.c
new file mode 100644
index 00000000..ffb50359
--- /dev/null
+++ b/src/sandbox-dev/libsandbox.c
@@ -0,0 +1,1214 @@
+/*
+ * Path sandbox for the gentoo linux portage package system, initially
+ * based on the ROCK Linux Wrapper for getting a list of created files
+ *
+ * to integrate with bash, bash should have been built like this
+ *
+ * ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
+ *
+ * it's very important that the --enable-static-link option is NOT specified
+ *
+ * Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+ * Distributed under the terms of the GNU General Public License, v2 or later
+ * Author : Geert Bevin <gbevin@uwyn.com>
+ *
+ * Post Bevin leaving Gentoo ranks:
+ * --------------------------------
+ * Ripped out all the wrappers, and implemented those of InstallWatch.
+ * Losts of cleanups and bugfixes. Implement a execve that forces $LIBSANDBOX
+ * in $LD_PRELOAD. Reformat the whole thing to look somewhat like the reworked
+ * sandbox.c from Brad House <brad@mainstreetsoftworks.com>.
+ *
+ * Martin Schlemmer <azarah@gentoo.org> (18 Aug 2002)
+ *
+ * Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>,
+ * as some of the InstallWatch code was used.
+ *
+ *
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/libsandbox.c,v 1.4 2002/12/16 22:28:05 jrray Exp $
+ *
+ */
+
+/* Uncomment below to enable wrapping of mknod().
+ * This is broken currently. */
+/* #define WRAP_MKNOD */
+
+
+#define open xxx_open
+#define open64 xxx_open64
+
+/* Wrapping mknod, do not have any effect, and
+ * wrapping __xmknod causes calls to it to segfault
+ */
+#ifdef WRAP_MKNOD
+# define __xmknod xxx___xmknod
+#endif
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <utime.h>
+#include <semaphore.h>
+
+#ifdef WRAP_MKNOD
+# undef __xmknod
+#endif
+
+#undef open
+#undef open64
+
+#include "localdecls.h"
+#include "sandbox.h"
+
+#define PIDS_FILE "/tmp/sandboxpids.tmp"
+
+#define FUNCTION_SANDBOX_SAFE(func, path) \
+ ((0 == is_sandbox_on()) || (1 == before_syscall(func, path)))
+
+#define FUNCTION_SANDBOX_SAFE_INT(func, path, flags) \
+ ((0 == is_sandbox_on()) || (1 == before_syscall_open_int(func, path, flags)))
+
+#define FUNCTION_SANDBOX_SAFE_CHAR(func, path, mode) \
+ ((0 == is_sandbox_on()) || (1 == before_syscall_open_char(func, path, mode)))
+
+
+/* Macro to check if a wrapper is defined, if not
+ * then try to resolve it again. */
+#define check_dlsym(name) \
+{ \
+ int old_errno=errno; \
+ if (!true_ ## name) true_ ## name=get_dlsym(#name); \
+ errno=old_errno; \
+}
+
+static char sandbox_lib[255];
+
+typedef struct {
+ char *last_env;
+ int count;
+ char **strs;
+} sbprefix_t;
+
+typedef struct {
+ int show_access_violation;
+ sbprefix_t deny;
+ sbprefix_t read;
+ sbprefix_t write;
+ sbprefix_t predict;
+} sbcontext_t;
+
+/* glibc modified realpath() functions */
+char *erealpath (const char *name, char *resolved);
+
+static void init_wrappers(void);
+static void *get_dlsym(const char *);
+static void canonicalize(const char *, char *);
+static int check_access(sbcontext_t *, const char *, const char *);
+static int check_syscall(sbcontext_t *, const char *, const char *);
+static int before_syscall(const char *, const char *);
+static int before_syscall_open_int(const char *, const char *, int);
+static int before_syscall_open_char(const char *, const char *, const char *);
+static void clean_env_entries(sbprefix_t *);
+static void init_context(sbcontext_t *);
+static void init_env_entries(sbprefix_t *, char *);
+static char* filter_path(const char*);
+static int is_sandbox_on();
+static int is_sandbox_pid();
+
+/* Wrapped functions */
+
+extern int chmod(const char *, mode_t);
+static int(*true_chmod)(const char *, mode_t);
+extern int chown(const char *, uid_t, gid_t);
+static int(*true_chown)(const char *, uid_t, gid_t);
+extern int creat(const char *, mode_t);
+static int(*true_creat)(const char *, mode_t);
+extern FILE *fopen(const char *,const char*);
+static FILE *(*true_fopen)(const char *,const char*);
+extern int lchown(const char *, uid_t, gid_t);
+static int(*true_lchown)(const char *, uid_t, gid_t);
+extern int link(const char *, const char *);
+static int(*true_link)(const char *, const char *);
+extern int mkdir(const char *, mode_t);
+static int(*true_mkdir)(const char *, mode_t);
+extern DIR *opendir(const char *);
+static DIR *(*true_opendir)(const char *);
+#ifdef WRAP_MKNOD
+extern int __xmknod(const char *, mode_t, dev_t);
+static int(*true___xmknod)(const char *, mode_t, dev_t);
+#endif
+extern int open(const char *, int, ...);
+static int(*true_open)(const char *, int, ...);
+extern int rename(const char *, const char *);
+static int(*true_rename)(const char *, const char *);
+extern int rmdir(const char *);
+static int(*true_rmdir)(const char *);
+extern int symlink(const char *, const char *);
+static int(*true_symlink)(const char *, const char *);
+extern int truncate(const char *, TRUNCATE_T);
+static int(*true_truncate)(const char *, TRUNCATE_T);
+extern int unlink(const char *);
+static int(*true_unlink)(const char *);
+
+#if (GLIBC_MINOR >= 1)
+
+extern int creat64(const char *, __mode_t);
+static int(*true_creat64)(const char *, __mode_t);
+extern FILE *fopen64(const char *,const char *);
+static FILE *(*true_fopen64)(const char *,const char *);
+extern int open64(const char *, int, ...);
+static int(*true_open64)(const char *, int, ...);
+extern int truncate64(const char *, __off64_t);
+static int(*true_truncate64)(const char *, __off64_t);
+
+#endif
+
+extern int execve(const char *filename, char *const argv [], char *const envp[]);
+static int (*true_execve)(const char *, char *const [], char *const []);
+
+static sbcontext_t* sbcontext = NULL;
+static sem_t ctxsem;
+
+/*
+ * Initialize the shabang
+ */
+
+static void init_wrappers(void)
+{
+ void *libc_handle = NULL;
+
+#ifdef BROKEN_RTLD_NEXT
+// printf ("RTLD_LAZY");
+ libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY);
+#else
+// printf ("RTLD_NEXT");
+ libc_handle = RTLD_NEXT;
+#endif
+
+ true_chmod = dlsym(libc_handle, "chmod");
+ true_chown = dlsym(libc_handle, "chown");
+ true_creat = dlsym(libc_handle, "creat");
+ true_fopen = dlsym(libc_handle, "fopen");
+ true_lchown = dlsym(libc_handle, "lchown");
+ true_link = dlsym(libc_handle, "link");
+ true_mkdir = dlsym(libc_handle, "mkdir");
+ true_opendir = dlsym(libc_handle, "opendir");
+#ifdef WRAP_MKNOD
+ true___xmknod = dlsym(libc_handle, "__xmknod");
+#endif
+ true_open = dlsym(libc_handle, "open");
+ true_rename = dlsym(libc_handle, "rename");
+ true_rmdir = dlsym(libc_handle, "rmdir");
+ true_symlink = dlsym(libc_handle, "symlink");
+ true_truncate = dlsym(libc_handle, "truncate");
+ true_unlink = dlsym(libc_handle, "unlink");
+
+#if (GLIBC_MINOR >= 1)
+ true_creat64 = dlsym(libc_handle, "creat64");
+ true_fopen64 = dlsym(libc_handle, "fopen64");
+ true_open64 = dlsym(libc_handle, "open64");
+ true_truncate64 = dlsym(libc_handle, "truncate64");
+#endif
+
+ true_execve = dlsym(libc_handle, "execve");
+}
+
+void _init(void)
+{
+ int old_errno = errno;
+ char *tmp_string = NULL;
+
+ if (sem_init(&ctxsem, 0, 1)) {
+ fprintf(stderr, "Failed to create semaphore\n");
+ abort();
+ }
+
+ init_wrappers();
+
+ /* Get the path and name to this library */
+ tmp_string = get_sandbox_lib("/");
+ strncpy(sandbox_lib, tmp_string, 254);
+
+ if (tmp_string) free(tmp_string);
+ tmp_string = NULL;
+
+ errno = old_errno;
+}
+
+void _fini(void)
+{
+ if (sbcontext) {
+ clean_env_entries(&sbcontext->deny);
+ clean_env_entries(&sbcontext->read);
+ clean_env_entries(&sbcontext->write);
+ clean_env_entries(&sbcontext->predict);
+ free(sbcontext);
+ sbcontext = NULL;
+ }
+
+ /* free the semaphore */
+ sem_destroy(&ctxsem);
+}
+
+static void canonicalize(const char *path, char *resolved_path)
+{
+ int old_errno = errno;
+
+ /* If path == NULL, return or we get a segfault */
+ if (NULL == path) return;
+
+ if(!erealpath(path, resolved_path) && (path[0] != '/')) {
+ /* The path could not be canonicalized, append it
+ * to the current working directory if it was not
+ * an absolute path
+ */
+ getcwd(resolved_path, MAXPATHLEN - 2);
+ strcat(resolved_path, "/");
+ strncat(resolved_path, path, MAXPATHLEN - 1 - strlen(resolved_path));
+ erealpath(resolved_path, resolved_path);
+ }
+
+ errno = old_errno;
+}
+
+static void *get_dlsym(const char *symname)
+{
+ void *libc_handle = NULL;
+ void *symaddr = NULL;
+
+#ifdef BROKEN_RTLD_NEXT
+ libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY);
+ if (!libc_handle) {
+ printf("libsandbox.so: Can't dlopen libc: %s\n", dlerror());
+ abort();
+ }
+#else
+ libc_handle = RTLD_NEXT;
+#endif
+
+ symaddr = dlsym(libc_handle, symname);
+ if (!symaddr) {
+ printf("libsandbox.so: Can't resolve %s: %s\n", symname, dlerror());
+ abort();
+ }
+
+ return symaddr;
+}
+
+/*
+ * Wrapper Functions
+ */
+
+int chmod(const char *path, mode_t mode)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("chmod", canonic) {
+ check_dlsym(chmod);
+ result = true_chmod(path, mode);
+ }
+
+ return result;
+}
+
+int chown(const char *path, uid_t owner, gid_t group)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("chown", canonic) {
+ check_dlsym(chown);
+ result = true_chown(path, owner, group);
+ }
+
+ return result;
+}
+
+int creat(const char *pathname, mode_t mode)
+{
+/* Is it a system call? */
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("creat", canonic) {
+ check_dlsym(open);
+ result = true_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
+ }
+
+ return result;
+}
+
+FILE *fopen(const char *pathname, const char *mode)
+{
+ FILE *result = NULL;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_CHAR("fopen", canonic, mode) {
+ check_dlsym(fopen);
+ result = true_fopen(pathname,mode);
+ }
+
+ return result;
+}
+
+int lchown(const char *path, uid_t owner, gid_t group)
+{
+/* Linux specific? */
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("lchown", canonic) {
+ check_dlsym(chown);
+ result = true_chown(path, owner, group);
+ }
+
+ return result;
+}
+
+int link(const char *oldpath, const char *newpath)
+{
+ int result = -1;
+ char old_canonic[MAXPATHLEN], new_canonic[MAXPATHLEN];
+
+ canonicalize(oldpath, old_canonic);
+ canonicalize(newpath, new_canonic);
+
+ if FUNCTION_SANDBOX_SAFE("link", new_canonic) {
+ check_dlsym(link);
+ result = true_link(oldpath, newpath);
+ }
+
+ return result;
+}
+
+int mkdir(const char *pathname, mode_t mode)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("mkdir", canonic) {
+ check_dlsym(mkdir);
+ result = true_mkdir(pathname, mode);
+ }
+
+ return result;
+}
+
+DIR *opendir(const char *name)
+{
+ DIR *result = NULL;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(name, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("opendir", canonic) {
+ check_dlsym(opendir);
+ result = true_opendir(name);
+ }
+
+ return result;
+}
+
+#ifdef WRAP_MKNOD
+
+int __xmknod(const char *pathname, mode_t mode, dev_t dev)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("__xmknod", canonic) {
+ check_dlsym(__xmknod);
+ result = true___xmknod(pathname, mode, dev);
+ }
+
+ return result;
+}
+
+#endif
+
+int open(const char *pathname, int flags, ...)
+{
+/* Eventually, there is a third parameter: it's mode_t mode */
+ va_list ap;
+ mode_t mode = 0;
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ if (flags & O_CREAT) {
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+ }
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_INT("open", canonic, flags) {
+ /* We need to resolve open() realtime in some cases,
+ * else we get a segfault when running /bin/ps, etc
+ * in a sandbox */
+ check_dlsym(open);
+ result=true_open(pathname, flags, mode);
+ }
+
+ return result;
+}
+
+int rename(const char *oldpath, const char *newpath)
+{
+ int result = -1;
+ char old_canonic[MAXPATHLEN], new_canonic[MAXPATHLEN];
+
+ canonicalize(oldpath, old_canonic);
+ canonicalize(newpath, new_canonic);
+
+ if FUNCTION_SANDBOX_SAFE("rename", new_canonic) {
+ check_dlsym(rename);
+ result = true_rename(oldpath, newpath);
+ }
+
+ return result;
+}
+
+int rmdir(const char *pathname)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("rmdir", canonic) {
+ check_dlsym(rmdir);
+ result = true_rmdir(pathname);
+ }
+
+ return result;
+}
+
+int symlink(const char *oldpath, const char *newpath)
+{
+ int result = -1;
+ char old_canonic[MAXPATHLEN], new_canonic[MAXPATHLEN];
+
+ canonicalize(oldpath, old_canonic);
+ canonicalize(newpath, new_canonic);
+
+ if FUNCTION_SANDBOX_SAFE("symlink", new_canonic) {
+ check_dlsym(symlink);
+ result = true_symlink(oldpath, newpath);
+ }
+
+ return result;
+}
+
+int truncate(const char *path, TRUNCATE_T length)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("truncate", canonic) {
+ check_dlsym(truncate);
+ result = true_truncate(path, length);
+ }
+
+ return result;
+}
+
+int unlink(const char *pathname)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("unlink", canonic) {
+ check_dlsym(unlink);
+ result = true_unlink(pathname);
+ }
+
+ return result;
+}
+
+#if (GLIBC_MINOR >= 1)
+
+int creat64(const char *pathname, __mode_t mode)
+{
+/* Is it a system call? */
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("creat64", canonic) {
+ check_dlsym(open64);
+ result = true_open64(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
+ }
+
+ return result;
+}
+
+FILE *fopen64(const char *pathname, const char *mode)
+{
+ FILE *result = NULL;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_CHAR("fopen64", canonic, mode) {
+ check_dlsym(fopen64);
+ result = true_fopen(pathname,mode);
+ }
+
+ return result;
+}
+
+int open64(const char *pathname, int flags, ...)
+{
+/* Eventually, there is a third parameter: it's mode_t mode */
+ va_list ap;
+ mode_t mode = 0;
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ if (flags & O_CREAT) {
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+ }
+
+ canonicalize(pathname, canonic);
+
+ if FUNCTION_SANDBOX_SAFE_INT("open64", canonic, flags) {
+ check_dlsym(open64);
+ result=true_open64(pathname, flags, mode);
+ }
+
+ return result;
+}
+
+int truncate64(const char *path, __off64_t length)
+{
+ int result = -1;
+ char canonic[MAXPATHLEN];
+
+ canonicalize(path, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("truncate64", canonic) {
+ check_dlsym(truncate64);
+ result = true_truncate64(path, length);
+ }
+
+ return result;
+}
+
+#endif /* GLIBC_MINOR >= 1 */
+
+/*
+ * Exec Wrappers
+ */
+
+int execve(const char *filename, char *const argv [], char *const envp[])
+{
+ int old_errno = errno;
+ int result = -1;
+ int count = 0;
+ char canonic[MAXPATHLEN];
+ char *old_envp = NULL;
+ char *new_envp = NULL;
+
+ canonicalize(filename, canonic);
+
+ if FUNCTION_SANDBOX_SAFE("execve", canonic) {
+ while (envp[count] != NULL) {
+ if (strstr(envp[count], "LD_PRELOAD=") == envp[count]) {
+ if (NULL != strstr(envp[count], sandbox_lib)) {
+ break;
+ } else {
+ const int max_envp_len = strlen(envp[count]) + strlen(sandbox_lib) + 1;
+
+ /* Backup envp[count], and set it to our own one which
+ * contains sandbox_lib */
+ old_envp = envp[count];
+ new_envp = strndupa(old_envp, max_envp_len - 1);
+
+ /* LD_PRELOAD already have variables other than sandbox_lib,
+ * thus we have to add sandbox_lib via a white space. */
+ if (0 != strcmp(envp[count], "LD_PRELOAD=")) {
+ strncpy(new_envp + strlen(old_envp), ":",
+ max_envp_len - strlen(new_envp));
+ strncpy(new_envp + strlen(old_envp) + 1, sandbox_lib,
+ max_envp_len - strlen(new_envp));
+ } else {
+ strncpy(new_envp + strlen(old_envp), sandbox_lib,
+ max_envp_len - strlen(new_envp));
+ }
+
+ /* Valid string? */
+ new_envp[max_envp_len] = '\0';
+
+ /* envp[count] = new_envp;
+ *
+ * Get rid of the "read-only" warnings */
+ memcpy((void *)&envp[count], &new_envp, sizeof(new_envp));
+
+ break;
+ }
+ }
+ count++;
+ }
+
+ errno = old_errno;
+ check_dlsym(execve);
+ result = true_execve(filename, argv, envp);
+ old_errno = errno;
+
+ if (old_envp) {
+ /* Restore envp[count] again.
+ *
+ * envp[count] = old_envp; */
+ memcpy((void *)&envp[count], &old_envp, sizeof(old_envp));
+ old_envp = NULL;
+ }
+ }
+
+ errno = old_errno;
+
+ return result;
+}
+
+/*
+ * Internal Functions
+ */
+
+#if (GLIBC_MINOR == 1)
+
+/* This hack is needed for glibc 2.1.1 (and others?)
+ * (not really needed, but good example) */
+extern int fclose(FILE *);
+static int (*true_fclose)(FILE *) = NULL;
+int fclose(FILE *file)
+{
+ int result = - 1;
+
+ check_dlsym(fclose);
+ result = true_fclose(file);
+
+ return result;
+}
+
+#endif /* GLIBC_MINOR == 1 */
+
+static void init_context(sbcontext_t* context)
+{
+ memset(context, 0, sizeof(sbcontext_t));
+ context->show_access_violation = 1;
+}
+
+static int is_sandbox_pid()
+{
+ int old_errno = errno;
+ int result = 0;
+ FILE* pids_stream = NULL;
+ int pids_file = -1;
+ int current_pid = 0;
+ int tmp_pid = 0;
+
+ init_wrappers();
+
+ pids_stream = true_fopen(PIDS_FILE, "r");
+
+ if (NULL == pids_stream) {
+ perror(">>> pids file fopen");
+ }
+ else
+ {
+ pids_file = fileno(pids_stream);
+
+ if (pids_file < 0) {
+ perror(">>> pids file fileno");
+ } else {
+ current_pid = getpid();
+
+ while (EOF != fscanf(pids_stream, "%d\n", &tmp_pid)) {
+ if (tmp_pid == current_pid) {
+ result = 1;
+ break;
+ }
+ }
+ }
+ if (EOF == fclose(pids_stream)) {
+ perror(">>> pids file fclose");
+ }
+ pids_stream = NULL;
+ pids_file = -1;
+ }
+
+ errno = old_errno;
+
+ return result;
+}
+
+static void clean_env_entries(sbprefix_t* prefix)
+{
+ int old_errno = errno;
+ int i = 0;
+
+ if (NULL != prefix->strs) {
+ for (i = 0; i < prefix->count; i++) {
+ if (NULL != prefix->strs[i]) {
+ free(prefix->strs[i]);
+ prefix->strs[i] = NULL;
+ }
+ }
+ free(prefix->strs);
+ prefix->strs = NULL;
+ prefix->count = 0;
+ }
+ if (prefix->last_env) {
+ free(prefix->last_env);
+ prefix->last_env = NULL;
+ }
+
+ errno = old_errno;
+}
+
+static void init_env_entries(sbprefix_t* prefix, char* env)
+{
+ int old_errno = errno;
+ char* prefixes_env = getenv(env);
+
+ if (NULL == prefixes_env) {
+ fprintf(stderr,
+ "Sandbox error : the %s environmental variable should be defined.\n",
+ env);
+ } else {
+ char *ptr;
+ int num_colons = 0;
+
+ /* Check to see if the env value has changed since the
+ last time this was initalized, don't do the work again
+ if it hasn't.
+ */
+
+ if (prefix->last_env && !strcmp(prefix->last_env, prefixes_env)) {
+ errno = old_errno;
+ return;
+ }
+
+ /* Clean any existing entries */
+ clean_env_entries(prefix);
+
+ /* Env value is different, update the cached copy */
+ prefix->last_env = strdup(prefixes_env);
+
+ ptr = prefixes_env;
+ while (*ptr) {
+ if (*ptr++ == ':') ++num_colons;
+ }
+
+ if (prefix->strs) {
+ free(prefix->strs);
+ prefix->strs = 0;
+ }
+ prefix->strs = (char**)malloc((num_colons+1) * sizeof(char*));
+ if (!prefix->strs) return;
+ memset(prefix->strs, 0, (num_colons+1) * sizeof(char*));
+ prefix->count = 0;
+
+ ptr = prefixes_env;
+ while (*ptr) {
+ char *next_colon = strchr(ptr, ':');
+ if (next_colon) {
+ if (next_colon != ptr) {
+ char *str = strndup(ptr, next_colon-ptr);
+ if (!str) return;
+ prefix->strs[prefix->count++] = filter_path(str);
+ free(str);
+ }
+ } else {
+ prefix->strs[prefix->count++] = filter_path(ptr);
+ break;
+ }
+
+ ptr = next_colon+1;
+ }
+ }
+ errno = old_errno;
+}
+
+static char* filter_path(const char* path)
+{
+ int old_errno = errno;
+ char* filtered_path = (char *)malloc(MAXPATHLEN * sizeof(char));
+ filtered_path[0] = 0;
+
+ canonicalize(path, filtered_path);
+
+ errno = old_errno;
+
+ return filtered_path;
+}
+
+static int check_access(sbcontext_t* sbcontext, const char* func, const char* path)
+{
+ int old_errno = errno;
+ int result = -1;
+ int i = 0;
+ char* filtered_path = filter_path(path);
+
+ if (!filtered_path) {
+ errno = old_errno;
+ return 0;
+ }
+
+ if ('/' != filtered_path[0]) {
+ free(filtered_path);
+ errno = old_errno;
+ return 0;
+ }
+
+ if ((0 == strncmp(filtered_path, "/etc/ld.so.preload", 18)) && (is_sandbox_pid())) {
+ result = 1;
+ }
+
+ if (-1 == result) {
+ if (NULL != sbcontext->deny.strs) {
+ for (i = 0; i < sbcontext->deny.count; i++) {
+ if (NULL != sbcontext->deny.strs[i]) {
+ if (0 == strncmp(filtered_path,
+ sbcontext->deny.strs[i],
+ strlen(sbcontext->deny.strs[i]))) {
+ result = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ if (-1 == result) {
+ if ((NULL != sbcontext->read.strs) &&
+ ((0 == strncmp(func, "open_rd", 7)) ||
+ (0 == strncmp(func, "popen", 5)) ||
+ (0 == strncmp(func, "opendir", 7)) ||
+ (0 == strncmp(func, "system", 6)) ||
+ (0 == strncmp(func, "execl", 5)) ||
+ (0 == strncmp(func, "execlp", 6)) ||
+ (0 == strncmp(func, "execle", 6)) ||
+ (0 == strncmp(func, "execv", 5)) ||
+ (0 == strncmp(func, "execvp", 6)) ||
+ (0 == strncmp(func, "execve", 6))
+ )
+ ) {
+ for (i = 0; i < sbcontext->read.count; i++) {
+ if (NULL != sbcontext->read.strs[i]) {
+ if (0 == strncmp(filtered_path,
+ sbcontext->read.strs[i],
+ strlen(sbcontext->read.strs[i]))) {
+ result = 1;
+ break;
+ }
+ }
+ }
+ }
+ else if ((NULL != sbcontext->write.strs) &&
+ ((0 == strncmp(func, "open_wr", 7)) ||
+ (0 == strncmp(func, "creat", 5)) ||
+ (0 == strncmp(func, "creat64", 7)) ||
+ (0 == strncmp(func, "mkdir", 5)) ||
+ (0 == strncmp(func, "mknod", 5)) ||
+ (0 == strncmp(func, "mkfifo", 6)) ||
+ (0 == strncmp(func, "link", 4)) ||
+ (0 == strncmp(func, "symlink", 7)) ||
+ (0 == strncmp(func, "rename", 6)) ||
+ (0 == strncmp(func, "utime", 5)) ||
+ (0 == strncmp(func, "utimes", 6)) ||
+ (0 == strncmp(func, "unlink", 6)) ||
+ (0 == strncmp(func, "rmdir", 5)) ||
+ (0 == strncmp(func, "chown", 5)) ||
+ (0 == strncmp(func, "lchown", 6)) ||
+ (0 == strncmp(func, "chmod", 5)) ||
+ (0 == strncmp(func, "truncate", 8)) ||
+ (0 == strncmp(func, "ftruncate", 9)) ||
+ (0 == strncmp(func, "truncate64", 10)) ||
+ (0 == strncmp(func, "ftruncate64", 11))
+ )
+ ) {
+ struct stat tmp_stat;
+
+#if 0 // write_denied is never set
+
+ for (i = 0; i < sbcontext->write_denied.count; i++) {
+ if (NULL != sbcontext->write_denied.strs[i]) {
+ if (0 == strncmp(filtered_path,
+ sbcontext->write_denied.strs[i],
+ strlen(sbcontext->write_denied.strs[i]))) {
+ result = 0;
+ break;
+ }
+ }
+ }
+#endif
+
+ if (-1 == result) {
+ for (i = 0; i < sbcontext->write.count; i++) {
+ if (NULL != sbcontext->write.strs[i]) {
+ if (0 == strncmp(filtered_path,
+ sbcontext->write.strs[i],
+ strlen(sbcontext->write.strs[i]))) {
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ if (-1 == result) {
+ /* hack to prevent mkdir of existing dirs to show errors */
+ if (0 == strncmp(func, "mkdir", 5)) {
+ if (0 == stat(filtered_path, &tmp_stat)) {
+ sbcontext->show_access_violation = 0;
+ result = 0;
+ }
+ }
+
+ if (-1 == result) {
+ for (i = 0; i < sbcontext->predict.count; i++) {
+ if (NULL != sbcontext->predict.strs[i]) {
+ if (0 == strncmp(filtered_path,
+ sbcontext->predict.strs[i],
+ strlen(sbcontext->predict.strs[i]))) {
+ sbcontext->show_access_violation = 0;
+ result = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (-1 == result) {
+ result = 0;
+ }
+
+ if (filtered_path) free(filtered_path);
+ filtered_path = NULL;
+
+ errno = old_errno;
+
+ return result;
+}
+
+static int check_syscall(sbcontext_t* sbcontext, const char* func, const char* file)
+{
+ int old_errno = errno;
+ int result = 1;
+ struct stat log_stat;
+ char* log_path = NULL;
+ char* absolute_path = NULL;
+ char* tmp_buffer = NULL;
+ int log_file = 0;
+ struct stat debug_log_stat;
+ char* debug_log_env = NULL;
+ char* debug_log_path = NULL;
+ int debug_log_file = 0;
+ char buffer[512];
+
+ init_wrappers();
+
+ if ('/' == file[0]) {
+ absolute_path = (char *)malloc((strlen(file) + 1) * sizeof(char));
+ sprintf(absolute_path, "%s", file);
+ } else {
+ tmp_buffer = get_current_dir_name();
+ absolute_path = (char *)malloc((strlen(tmp_buffer) + 1 + strlen(file) + 1) * sizeof(char));
+ sprintf(absolute_path,"%s/%s", tmp_buffer, file);
+
+ if (tmp_buffer) free(tmp_buffer);
+ tmp_buffer = NULL;
+ }
+
+ log_path = getenv("SANDBOX_LOG");
+ debug_log_env = getenv("SANDBOX_DEBUG");
+ debug_log_path = getenv("SANDBOX_DEBUG_LOG");
+
+ if (((NULL == log_path) ||
+ (0 != strncmp(absolute_path, log_path, strlen(log_path)))) &&
+ ((NULL == debug_log_env) ||
+ (NULL == debug_log_path) ||
+ (0 != strncmp(absolute_path, debug_log_path, strlen(debug_log_path)))) &&
+ (0 == check_access(sbcontext, func, absolute_path))
+ ) {
+ if (1 == sbcontext->show_access_violation) {
+ fprintf(stderr, "\e[31;01mACCESS DENIED\033[0m %s:%*s%s\n",
+ func, (int)(10 - strlen(func)), "", absolute_path);
+
+ if (NULL != log_path) {
+ sprintf(buffer, "%s:%*s%s\n", func, (int)(10 - strlen(func)), "", absolute_path);
+
+ if ((0 == lstat(log_path, &log_stat)) &&
+ (0 == S_ISREG(log_stat.st_mode))
+ ) {
+ fprintf(stderr,
+ "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n",
+ log_path);
+ } else {
+ log_file = true_open(log_path,
+ O_APPEND | O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if(log_file >= 0) {
+ write(log_file, buffer, strlen(buffer));
+ close(log_file);
+ }
+ }
+ }
+ }
+
+ result = 0;
+ }
+ else if (NULL != debug_log_env) {
+ if (NULL != debug_log_path) {
+ if (0 != strncmp(absolute_path, debug_log_path, strlen(debug_log_path))) {
+ sprintf(buffer, "%s:%*s%s\n", func, (int)(10 - strlen(func)), "", absolute_path);
+
+ if ((0 == lstat(debug_log_path, &debug_log_stat)) &&
+ (0 == S_ISREG(debug_log_stat.st_mode))
+ ) {
+ fprintf(stderr,
+ "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n",
+ log_path);
+ } else {
+ debug_log_file = true_open(debug_log_path,
+ O_APPEND | O_WRONLY | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if(debug_log_file >= 0) {
+ write(debug_log_file, buffer, strlen(buffer));
+ close(debug_log_file);
+ }
+ }
+ }
+ } else {
+ fprintf(stderr, "\e[32;01mACCESS ALLOWED\033[0m %s:%*s%s\n",
+ func, (int)(10 - strlen(func)), "", absolute_path);
+ }
+ }
+
+ if (absolute_path) free(absolute_path);
+ absolute_path = NULL;
+
+ errno = old_errno;
+
+ return result;
+}
+
+static int is_sandbox_on()
+{
+ int old_errno = errno;
+
+ /* $SANDBOX_ACTIVE is an env variable that should ONLY
+ * be used internal by sandbox.c and libsanbox.c. External
+ * sources should NEVER set it, else the sandbox is enabled
+ * in some cases when run in parallel with another sandbox,
+ * but not even in the sandbox shell.
+ *
+ * Azarah (3 Aug 2002)
+ */
+ if ((NULL != getenv("SANDBOX_ON")) &&
+ (0 == strncmp(getenv("SANDBOX_ON"), "1", 1)) &&
+ (NULL != getenv("SANDBOX_ACTIVE")) &&
+ (0 == strncmp(getenv("SANDBOX_ACTIVE"), "armedandready", 13))
+ ) {
+ errno = old_errno;
+
+ return 1;
+ } else {
+ errno = old_errno;
+
+ return 0;
+ }
+}
+
+static int before_syscall(const char* func, const char* file)
+{
+ int old_errno = errno;
+ int result = 1;
+
+ /* Only allow one thread to access sbcontext at a time */
+ sem_wait(&ctxsem);
+
+ if (!sbcontext) {
+ sbcontext = (sbcontext_t*)malloc(sizeof(sbcontext_t));
+ init_context(sbcontext);
+ } else {
+ /* sometimes this value gets set to 0 */
+ sbcontext->show_access_violation = 1;
+ }
+
+ init_env_entries(&sbcontext->deny, "SANDBOX_DENY");
+ init_env_entries(&sbcontext->read, "SANDBOX_READ");
+ init_env_entries(&sbcontext->write, "SANDBOX_WRITE");
+ init_env_entries(&sbcontext->predict, "SANDBOX_PREDICT");
+
+ result = check_syscall(sbcontext, func, file);
+
+ if (sem_post(&ctxsem)) {
+ fprintf(stderr, "Failed trying to release semaphore\n");
+ }
+
+ errno = old_errno;
+
+ if (0 == result) {
+ errno = EACCES;
+ }
+
+ return result;
+}
+
+static int before_syscall_open_int(const char* func, const char* file, int flags)
+{
+ if ((flags & O_WRONLY) || (flags & O_RDWR)) {
+ return before_syscall("open_wr", file);
+ } else {
+ return before_syscall("open_rd", file);
+ }
+}
+
+static int before_syscall_open_char(const char* func, const char* file, const char* mode)
+{
+ if ((strcmp(mode, "r") == 0) || (strcmp(mode, "rb") == 0)) {
+ return before_syscall("open_rd", file);
+ } else {
+ return before_syscall("open_wr", file);
+ }
+}
+
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-dev/sandbox.bashrc b/src/sandbox-dev/sandbox.bashrc
new file mode 100644
index 00000000..35fa89b6
--- /dev/null
+++ b/src/sandbox-dev/sandbox.bashrc
@@ -0,0 +1,8 @@
+# Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+# Distributed under the terms of the GNU General Public License, v2 or later
+# Author : Geert Bevin <gbevin@uwyn.com>
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/sandbox.bashrc,v 1.1 2002/08/25 06:09:05 azarah Exp $
+source /etc/profile
+export LD_PRELOAD="$SANDBOX_LIB"
+alias make="make LD_PRELOAD=$SANDBOX_LIB"
+alias su="su -c '/bin/bash -rcfile $SANDBOX_DIR/sandbox.bashrc'"
diff --git a/src/sandbox-dev/sandbox.c b/src/sandbox-dev/sandbox.c
new file mode 100644
index 00000000..7dccf62b
--- /dev/null
+++ b/src/sandbox-dev/sandbox.c
@@ -0,0 +1,816 @@
+/*
+** Path sandbox for the gentoo linux portage package system, initially
+** based on the ROCK Linux Wrapper for getting a list of created files
+**
+** to integrate with bash, bash should have been built like this
+**
+** ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
+**
+** it's very important that the --enable-static-link option is NOT specified
+**
+** Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+** Distributed under the terms of the GNU General Public License, v2 or later
+** Author : Geert Bevin <gbevin@uwyn.com>
+** $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/sandbox.c,v 1.4 2002/10/20 21:37:30 azarah Exp $
+*/
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "sandbox.h"
+
+int preload_adaptable = 1;
+int cleaned_up = 0;
+int print_debug = 0;
+
+/* Read pids file, and load active pids into an array. Return number of pids in array */
+int load_active_pids(int fd, int **pids)
+{
+ char *data = NULL;
+ char *ptr = NULL, *ptr2 = NULL;
+ int my_pid;
+ int num_pids = 0;
+ long len;
+
+ pids[0] = NULL;
+
+ len = file_length(fd);
+
+ /* Allocate and zero datablock to read pids file */
+ data = (char *)malloc((len + 1)*sizeof(char));
+ memset(data, 0, len + 1);
+
+ /* Start at beginning of file */
+ lseek(fd, 0L, SEEK_SET);
+
+ /* read entire file into a buffer */
+ read(fd, data, len);
+
+ ptr = data;
+
+ /* Loop and read all pids */
+ while (1) {
+ /* Find new line */
+ ptr2 = strchr(ptr, '\n');
+ if (ptr2 == NULL) break; /* No more PIDs */
+
+ /* clear the \n. And ptr should have a null-terminated decimal string */
+ ptr2[0] = 0;
+
+ my_pid = atoi(ptr);
+
+ /* If the PID is still alive, add it to our array */
+ if ((0 != my_pid) && (0 == kill(my_pid, 0))) {
+ pids[0] = (int *)realloc(pids[0], (num_pids + 1)*sizeof(int));
+ pids[0][num_pids] = my_pid;
+ num_pids++;
+ }
+
+ /* Put ptr past the NULL we just wrote */
+ ptr = ptr2 + 1;
+ }
+
+ if (data) free(data);
+
+ return num_pids;
+}
+
+/* Read ld.so.preload file, and loads dirs into an array. Return number of entries in array */
+int load_preload_libs(int fd, char ***preloads)
+{
+ char *data = NULL;
+ char *ptr = NULL, *ptr2 = NULL;
+ int num_entries = 0;
+ long len;
+
+ preloads[0] = NULL;
+
+ len = file_length(fd);
+
+ /* Allocate and zero datablock to read pids file */
+ data = (char *)malloc((len + 1)*sizeof(char));
+ memset(data, 0, len + 1);
+
+ /* Start at beginning of file */
+ lseek(fd, 0L, SEEK_SET);
+
+ /* read entire file into a buffer */
+ read(fd, data, len);
+
+ ptr = data;
+
+ /* Loop and read all pids */
+ while (1) {
+ /* Find new line */
+ ptr2 = strchr(ptr, '\n');
+
+ /* clear the \n. And ptr should have a null-terminated decimal string
+ * Don't break from the loop though because the last line may not
+ * terminated with a \n
+ */
+ if (NULL != ptr2) ptr2[0] = 0;
+
+ /* If listing does not match our libname, add it to the array */
+ if ((strlen(ptr)) && (NULL == strstr(ptr, LIB_NAME))) {
+ preloads[0] = (char **)realloc(preloads[0], (num_entries + 1)*sizeof(char **));
+ preloads[0][num_entries] = strdup(ptr);
+ num_entries++;
+ }
+
+ if (NULL == ptr2) break; /* No more PIDs */
+
+ /* Put ptr past the NULL we just wrote */
+ ptr = ptr2 + 1;
+ }
+
+ if (data) free(data);
+
+ return num_entries;
+}
+
+
+void cleanup()
+{
+ int i = 0;
+ int success = 1;
+ int pids_file = -1, num_of_pids = 0;
+ int *pids_array = NULL;
+ char pid_string[255];
+#ifdef USE_LD_SO_PRELOAD
+ int preload_file = -1, num_of_preloads = 0;
+ char preload_entry[255];
+ char **preload_array = NULL;
+#endif
+
+
+ /* remove this sandbox's bash pid from the global pids
+ * file if it has rights to adapt the ld.so.preload file */
+ if ((1 == preload_adaptable) && (0 == cleaned_up)) {
+ cleaned_up = 1;
+ success = 1;
+
+ if (print_debug) printf("Cleaning up pids file.\n");
+
+ /* Stat the PIDs file, make sure it exists and is a regular file */
+ if (file_exist(PIDS_FILE, 1) <= 0) {
+ perror(">>> pids file is not a regular file");
+ success = 0;
+ /* We should really not fail if the pidsfile is missing here, but
+ * rather just exit cleanly, as there is still some cleanup to do */
+ return;
+ }
+
+ pids_file = file_open(PIDS_FILE, "r+", 0);
+ if (-1 == pids_file) {
+ success = 0;
+ /* Nothing more to do here */
+ return;
+ }
+
+ /* Load "still active" pids into an array */
+ num_of_pids = load_active_pids(pids_file, &pids_array);
+ //printf("pids: %d\r\n", num_of_pids);
+
+#ifdef USE_LD_SO_PRELOAD
+ /* clean the /etc/ld.so.preload file if no other sandbox
+ * processes are running anymore */
+ if (1 == num_of_pids) {
+ success = 1;
+
+ if (print_debug) printf("Cleaning up /etc/ld.so.preload.\n");
+
+ preload_file = file_open("/etc/ld.so.preload", "r+", 0);
+ if (-1 != preload_file) {
+ /* Load all the preload libraries into an array */
+ num_of_preloads = load_preload_libs(preload_file, &preload_array);
+ //printf("num preloads: %d\r\n", num_of_preloads);
+ /* Clear file */
+ file_truncate(preload_file);
+
+ /* store the other preload libraries back into the /etc/ld.so.preload file */
+ if(num_of_preloads > 0) {
+ for (i = 0; i < num_of_preloads; i++) {
+ sprintf(preload_entry, "%s\n", preload_array[i]);
+ if (write(preload_file, preload_entry, strlen(preload_entry)) != strlen(preload_entry)) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+ }
+
+ /* Free memory used to store preload array */
+ for (i = 0; i < num_of_preloads; i++) {
+ if (preload_array[i]) free(preload_array[i]);
+ preload_array[i] = NULL;
+ }
+ if (preload_array) free(preload_array);
+ preload_array = NULL;
+
+ file_close(preload_file);
+ preload_file = -1;
+ }
+ }
+#endif
+
+ file_truncate(pids_file);
+
+ /* if pids are still running, write only the running pids back to the file */
+ if(num_of_pids > 1) {
+ for (i = 0; i < num_of_pids; i++) {
+ sprintf(pid_string, "%d\n", pids_array[i]);
+ if (write(pids_file, pid_string, strlen(pid_string)) != strlen(pid_string)) {
+ perror(">>> pids file write");
+ success = 0;
+ break;
+ }
+ }
+
+ file_close(pids_file);
+ pids_file = -1;
+ } else {
+
+ file_close(pids_file);
+ pids_file = -1;
+
+ /* remove the pidsfile, as this was the last sandbox */
+ unlink(PIDS_FILE);
+ }
+
+ if (pids_array != NULL) {
+ free(pids_array);
+ pids_array = NULL;
+ }
+ }
+
+ if (0 == success) {
+ return;
+ }
+}
+
+void stop(int signum)
+{
+ printf("Caught signal %d\r\n", signum);
+ cleanup();
+}
+
+void setenv_sandbox_write(char *home_dir, char *portage_tmp_dir, char *var_tmp_dir, char *tmp_dir)
+{
+ char sandbox_write_var[1024];
+
+ if (!getenv(ENV_SANDBOX_WRITE)) {
+ /* these should go into make.globals later on */
+ strcpy(sandbox_write_var, "");
+ strcat(sandbox_write_var, "/dev/zero:/dev/fd/:/dev/null:/dev/pts/:/dev/vc/:/dev/tty:/tmp/");
+ strcat(sandbox_write_var, ":");
+ /* NGPT support */
+ strcat(sandbox_write_var, "/dev/shm/ngpt");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/log/scrollkeeper.log");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, home_dir);
+ strcat(sandbox_write_var, "/.gconfd/lock");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, home_dir);
+ strcat(sandbox_write_var, "/.bash_history");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/tmp/conftest");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/lib/conftest");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/tmp/cf");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/lib/cf");
+ strcat(sandbox_write_var, ":");
+ if (NULL == portage_tmp_dir) {
+ strcat(sandbox_write_var, tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, var_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/tmp/");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/tmp/");
+
+ /* How the heck is this possible?? we just set it above! */
+ } else if (0 == strcmp(sandbox_write_var, "/var/tmp/")) {
+ strcat(sandbox_write_var, portage_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/tmp/");
+
+ /* Still don't think this is possible, am I just stupid or something? */
+ } else if (0 == strcmp(sandbox_write_var, "/tmp/")) {
+ strcat(sandbox_write_var, portage_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, var_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/tmp/");
+
+ /* Amazing, one I think is possible */
+ } else {
+ strcat(sandbox_write_var, portage_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, var_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/tmp/");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/tmp/");
+ }
+
+ setenv(ENV_SANDBOX_WRITE, sandbox_write_var, 1);
+ }
+}
+
+
+void setenv_sandbox_predict(char *home_dir)
+{
+ char sandbox_predict_var[1024];
+
+ if (!getenv(ENV_SANDBOX_PREDICT)) {
+ /* these should go into make.globals later on */
+ strcpy(sandbox_predict_var, "");
+ strcat(sandbox_predict_var, home_dir);
+ strcat(sandbox_predict_var, "/.");
+ strcat(sandbox_predict_var, ":");
+ strcat(sandbox_predict_var, "/usr/lib/python2.0/");
+ strcat(sandbox_predict_var, ":");
+ strcat(sandbox_predict_var, "/usr/lib/python2.1/");
+ strcat(sandbox_predict_var, ":");
+ strcat(sandbox_predict_var, "/usr/lib/python2.2/");
+ setenv(ENV_SANDBOX_PREDICT, sandbox_predict_var, 1);
+ }
+}
+
+int print_sandbox_log(char *sandbox_log)
+{
+ int sandbox_log_file = -1;
+ char *beep_count_env = NULL;
+ int i, beep_count = 0;
+ long len = 0;
+ char *buffer = NULL;
+
+ sandbox_log_file=file_open(sandbox_log, "r", 0);
+ if (-1 == sandbox_log_file) {
+ return 0;
+ }
+
+ len = file_length(sandbox_log_file);
+ buffer = (char *)malloc((len + 1)*sizeof(char));
+ memset(buffer, 0, len + 1);
+ read(sandbox_log_file, buffer, len);
+ file_close(sandbox_log_file);
+
+ printf("\e[31;01m--------------------------- ACCESS VIOLATION SUMMARY ---------------------------\033[0m\n");
+ printf("\e[31;01mLOG FILE = \"%s\"\033[0m\n", sandbox_log);
+ printf("\n");
+ printf("%s", buffer);
+ if (buffer) free(buffer); buffer = NULL;
+ printf("\e[31;01m--------------------------------------------------------------------------------\033[0m\n");
+
+ beep_count_env = getenv(ENV_SANDBOX_BEEP);
+ if (beep_count_env) {
+ beep_count = atoi(beep_count_env);
+ } else {
+ beep_count = DEFAULT_BEEP_COUNT;
+ }
+
+ for (i = 0; i < beep_count; i++) {
+ fputc('\a', stderr);
+ if (i < beep_count -1) {
+ sleep(1);
+ }
+ }
+ return 1;
+}
+
+int spawn_shell(char *argv_bash[])
+{
+#ifdef USE_SYSTEM_SHELL
+ int i = 0;
+ char *sh = NULL;
+ int first = 1;
+ int ret;
+ long len = 0;
+
+ while (1) {
+ if (NULL == argv_bash[i]) break;
+ if (NULL != sh) len = strlen(sh);
+ sh = (char *)realloc(sh, len+strlen(argv_bash[i]) + 5);
+ if (first) {
+ sh[0] = 0;
+ first = 0;
+ }
+ strcat(sh, "\"");
+ strcat(sh, argv_bash[i]);
+ strcat(sh, "\" ");
+
+ //printf("%s\n", argv_bash[i]);
+ i++;
+ }
+ printf("%s\n", sh);
+ ret = system(sh);
+ if (sh) free(sh);
+ sh = NULL;
+
+ if (-1 == ret) return 0;
+ return 1;
+
+#else
+# ifndef NO_FORK
+ int pid;
+ int status = 0;
+ int ret = 0;
+
+ pid = fork();
+
+ /* Child's process */
+ if (0 == pid) {
+# endif
+ execv(argv_bash[0], argv_bash);
+# ifndef NO_FORK
+ return 0;
+ } else if (pid < 0) {
+ return 0;
+ }
+ ret = waitpid(pid, &status, 0);
+ if ((-1 == ret) || (status > 0)) return 0;
+# endif
+ return 1;
+#endif
+}
+
+int main(int argc, char** argv)
+{
+ int i = 0, success = 1;
+ int preload_file = -1;
+ int sandbox_log_presence = 0;
+ int sandbox_log_file = -1;
+ int pids_file = -1;
+ long len;
+
+ int *pids_array = NULL;
+ int num_of_pids = 0;
+
+ // char run_arg[255];
+ char portage_tmp_dir[PATH_MAX];
+ char var_tmp_dir[PATH_MAX];
+ char tmp_dir[PATH_MAX];
+ char sandbox_log[255];
+ char sandbox_debug_log[255];
+ char sandbox_dir[255];
+ char sandbox_lib[255];
+ char sandbox_rc[255];
+ char pid_string[255];
+ char **argv_bash = NULL;
+
+ char *run_str = "-c";
+ char *home_dir = NULL;
+ char *tmp_string = NULL;
+#ifdef USE_LD_SO_PRELOAD
+ char **preload_array = NULL;
+ int num_of_preloads = 0;
+#endif
+
+ /* Only print info if called with no arguments .... */
+ if (argc < 2) {
+ print_debug = 1;
+ }
+
+ if (print_debug) printf("========================== Gentoo linux path sandbox ===========================\n");
+
+
+ /* check if a sandbox is already running */
+ if (NULL != getenv(ENV_SANDBOX_ON)) {
+ fprintf(stderr, "Not launching a new sandbox instance\nAnother one is already running in this process hierarchy.\n");
+ exit(1);
+ } else {
+
+ /* determine the location of all the sandbox support files */
+ if (print_debug) printf("Detection of the support files.\n");
+
+ /* Generate base sandbox path */
+ tmp_string = get_sandbox_path(argv[0]);
+ strncpy(sandbox_dir, tmp_string, 254);
+ if (tmp_string) free(tmp_string);
+ tmp_string = NULL;
+ strcat(sandbox_dir, "/");
+
+ /* Generate sandbox lib path */
+ tmp_string = get_sandbox_lib(sandbox_dir);
+ strncpy(sandbox_lib, tmp_string, 254);
+ if (tmp_string) free(tmp_string);
+ tmp_string = NULL;
+
+ /* Generate sandbox bashrc path */
+ tmp_string = get_sandbox_rc(sandbox_dir);
+ strncpy(sandbox_rc, tmp_string, 254);
+ if (tmp_string) free(tmp_string);
+ tmp_string = NULL;
+
+ /* verify the existance of required files */
+ if (print_debug) printf("Verification of the required files.\n");
+
+ if (file_exist(sandbox_lib, 0) <= 0) {
+ fprintf(stderr, "Could not open the sandbox library at '%s'.\n", sandbox_lib);
+ return -1;
+ } else if (file_exist(sandbox_rc, 0) <= 0) {
+ fprintf(stderr, "Could not open the sandbox rc file at '%s'.\n", sandbox_rc);
+ return -1;
+ }
+
+#ifdef USE_LD_SO_PRELOAD
+ /* ensure that the /etc/ld.so.preload file contains an entry for the sandbox lib */
+ if (print_debug) printf("Setting up the ld.so.preload file.\n");
+#endif
+
+ /* check if the /etc/ld.so.preload is a regular file */
+ if (file_exist("/etc/ld.so.preload", 1) < 0) {
+ fprintf(stderr, ">>> /etc/ld.so.preload file is not a regular file\n");
+ exit(1);
+ }
+
+ /* Our r+ also will create the file if it doesn't exist */
+ preload_file=file_open("/etc/ld.so.preload", "r+", 1, 0644);
+ if (-1 == preload_file) {
+ preload_adaptable = 0;
+/* exit(1);*/
+ }
+
+#ifdef USE_LD_SO_PRELOAD
+ /* Load entries of preload table */
+ num_of_preloads = load_preload_libs(preload_file, &preload_array);
+
+ /* Zero out our ld.so.preload file */
+ file_truncate(preload_file);
+
+ /* Write contents of preload file */
+ for (i = 0; i < num_of_preloads + 1; i++) {
+ /* First entry should be our sandbox library */
+ if (0 == i) {
+ if (write(preload_file, sandbox_lib, strlen(sandbox_lib)) != strlen(sandbox_lib)) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ } else {
+ /* Output all other preload entries */
+ if (write(preload_file, preload_array[i - 1], strlen(preload_array[i - 1])) != strlen(preload_array[i - 1])) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+ /* Don't forget the return character after each line! */
+ if (1 != write(preload_file, "\n", 1)) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+
+ for (i = 0; i < num_of_preloads; i++) {
+ if (preload_array[i]) free(preload_array[i]);
+ preload_array[i] = NULL;
+ }
+ if (preload_array) free(preload_array);
+ num_of_preloads = 0;
+ preload_array = NULL;
+#endif
+
+ /* That's all we needed to do with the preload file */
+ file_close(preload_file);
+ preload_file = -1;
+
+ /* set up the required environment variables */
+ if (print_debug) printf("Setting up the required environment variables.\n");
+
+ /* Generate sandbox log full path */
+ tmp_string=get_sandbox_log();
+ strncpy(sandbox_log, tmp_string, 254);
+ if (tmp_string) free(tmp_string);
+ tmp_string = NULL;
+
+ setenv(ENV_SANDBOX_LOG, sandbox_log, 1);
+
+ snprintf(sandbox_debug_log, 254, "%s%s%s", DEBUG_LOG_FILE_PREFIX, pid_string, LOG_FILE_EXT);
+ setenv(ENV_SANDBOX_DEBUG_LOG, sandbox_debug_log, 1);
+
+ home_dir = getenv("HOME");
+
+ /* drobbins: we need to expand these paths using realpath() so that PORTAGE_TMPDIR
+ * can contain symlinks (example, /var is a symlink, /var/tmp is a symlink.) Without
+ * this, access is denied to /var/tmp, hurtin' ebuilds.
+ */
+
+ realpath(getenv("PORTAGE_TMPDIR"),portage_tmp_dir);
+ realpath("/var/tmp",var_tmp_dir);
+ realpath("/tmp",tmp_dir);
+
+ setenv(ENV_SANDBOX_DIR, sandbox_dir, 1);
+ setenv(ENV_SANDBOX_LIB, sandbox_lib, 1);
+ setenv("LD_PRELOAD", sandbox_lib, 1);
+
+ if (!getenv(ENV_SANDBOX_DENY)) {
+ setenv(ENV_SANDBOX_DENY, LD_PRELOAD_FILE, 1);
+ }
+
+ if (!getenv(ENV_SANDBOX_READ)) {
+ setenv(ENV_SANDBOX_READ, "/", 1);
+ }
+
+ /* Set up Sandbox Write path */
+ setenv_sandbox_write(home_dir, portage_tmp_dir, var_tmp_dir, tmp_dir);
+ setenv_sandbox_predict(home_dir);
+
+ setenv(ENV_SANDBOX_ON, "1", 0);
+
+ /* if the portage temp dir was present, cd into it */
+ if (NULL != portage_tmp_dir) {
+ chdir(portage_tmp_dir);
+ }
+
+ argv_bash=(char **)malloc(6 * sizeof(char *));
+ argv_bash[0] = strdup("/bin/bash");
+ argv_bash[1] = strdup("-rcfile");
+ argv_bash[2] = strdup(sandbox_rc);
+ if (argc < 2) {
+ argv_bash[3] = NULL;
+ } else {
+ argv_bash[3] = strdup(run_str); /* "-c" */
+ }
+ argv_bash[4] = NULL; /* strdup(run_arg); */
+ argv_bash[5] = NULL;
+
+ if (argc >= 2) {
+ for (i = 1; i< argc; i++) {
+ if (NULL == argv_bash[4]) len = 0;
+ else len = strlen(argv_bash[4]);
+ argv_bash[4]=(char *)realloc(argv_bash[4], (len + strlen(argv[i]) + 2) * sizeof(char));
+ if (0 == len) argv_bash[4][0] = 0;
+ if (1 != i) strcat(argv_bash[4], " ");
+ strcat(argv_bash[4], argv[i]);
+ }
+ }
+#if 0
+ char* argv_bash[] = {
+ "/bin/bash",
+ "-rcfile",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ /* adding additional bash arguments */
+ for (i = 1; i < argc; i++) {
+ if (1 == i) {
+ argv_bash[3] = run_str;
+ argv_bash[4] = run_arg;
+ strcpy(argv_bash[4], argv[i]);
+ } else {
+ strcat(argv_bash[4], " ");
+ strcat(argv_bash[4], argv[i]);
+ }
+ }
+#endif
+
+ /* set up the required signal handlers */
+ signal(SIGHUP, &stop);
+ signal(SIGINT, &stop);
+ signal(SIGQUIT, &stop);
+ signal(SIGTERM, &stop);
+
+ /* this one should NEVER be set in ebuilds, as it is the one
+ * private thing libsandbox.so use to test if the sandbox
+ * should be active for this pid, or not.
+ *
+ * azarah (3 Aug 2002)
+ */
+
+ setenv("SANDBOX_ACTIVE", "armedandready", 1);
+
+
+ /* Load our PID into PIDs file if environment is adaptable */
+ if (preload_adaptable) {
+ success = 1;
+ if (file_exist(PIDS_FILE, 1) < 0) {
+ success = 0;
+ fprintf(stderr, ">>> pids file is not a regular file");
+ } else {
+ pids_file=file_open(PIDS_FILE, "r+", 1, 0644);
+ if (-1 == pids_file) {
+ success = 0;
+ } else {
+ /* Grab still active pids */
+ num_of_pids = load_active_pids(pids_file, &pids_array);
+
+ /* Zero out file */
+ file_truncate(pids_file);
+
+ /* Output active pids, and append our pid */
+ for (i = 0; i < num_of_pids + 1; i++) {
+ /* Time for our entry */
+ if (i == num_of_pids) {
+ sprintf(pid_string, "%d\n", getpid());
+ } else {
+ sprintf(pid_string, "%d\n", pids_array[i]);
+ }
+ if (write(pids_file, pid_string, strlen(pid_string)) != strlen(pid_string)) {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+ /* Clean pids_array */
+ if (pids_array) free(pids_array);
+ pids_array = NULL;
+ num_of_pids = 0;
+
+ /* We're done with the pids file */
+ file_close(pids_file);
+ }
+ }
+
+ /* Something went wrong, bail out */
+ if (success == 0)
+ exit(1);
+ }
+
+ /* STARTING PROTECTED ENVIRONMENT */
+ if (print_debug) {
+ printf("The protected environment has been started.\n");
+ printf("--------------------------------------------------------------------------------\n");
+ }
+
+ if (print_debug) printf("Shell being started in forked process.\n");
+
+ /* Start Bash */
+ if (!spawn_shell(argv_bash)) {
+ if (print_debug) fprintf(stderr, ">>> shell process failed to spawn\n");
+ success = 0;
+ }
+
+ /* Free bash stuff */
+ for (i = 0; i < 6; i++) {
+ if (argv_bash[i]) free(argv_bash[i]);
+ argv_bash[i] = NULL;
+ }
+ if (argv_bash) free(argv_bash);
+ argv_bash = NULL;
+
+ if (print_debug) {
+ printf("Cleaning up sandbox process\n");
+ }
+
+ cleanup();
+
+ if (print_debug) {
+ printf("========================== Gentoo linux path sandbox ===========================\n");
+ printf("The protected environment has been shut down.\n");
+ }
+
+ if (file_exist(sandbox_log, 0)) {
+ sandbox_log_presence = 1;
+ success = 1;
+ if (!print_sandbox_log(sandbox_log)) {
+ success = 0;
+ }
+
+#if 0
+ if (!success) {
+ exit(1);
+ }
+#endif
+ sandbox_log_file = -1;
+ } else if (print_debug) {
+ printf("--------------------------------------------------------------------------------\n");
+ }
+
+ if ((sandbox_log_presence) || (!success)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-dev/sandbox.h b/src/sandbox-dev/sandbox.h
new file mode 100644
index 00000000..d750fdd7
--- /dev/null
+++ b/src/sandbox-dev/sandbox.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2002 Brad House <brad@mainstreetsoftworks.com>,
+ * Possibly based on code from Geert Bevin, Uwyn, http://www.uwyn.com
+ * Distributed under the terms of the GNU General Public License, v2 or later
+ * Author: Brad House <brad@mainstreetsoftworks.com>
+ *
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/sandbox.h,v 1.2 2002/12/04 18:11:32 azarah Exp $
+ */
+
+#ifndef __SANDBOX_H__
+#define __SANDBOX_H__
+
+/* Uncomment below to use flock instead of fcntl (POSIX way) to lock/unlock files */
+/* #define USE_FLOCK */
+
+/* Uncomment below to use system() to execute the shell rather than execv */
+/* #define USE_SYSTEM_SHELL */
+
+/* Uncomment below to use /etc/ld.so.preload (could be very intrusive!!) */
+/* #define USE_LD_SO_PRELOAD */
+
+/* Uncommend to not have the protected shell forked, just run in parent process */
+/* ONLY FOR DEBUGGING PURPOSES!! (strace needs it like that) */
+/* #define NO_FORK */
+
+
+#define LD_PRELOAD_FILE "/etc/ld.so.preload"
+#define LIB_NAME "libsandbox.so"
+#define BASHRC_NAME "sandbox.bashrc"
+#define PIDS_FILE "/tmp/sandboxpids.tmp"
+#define LOG_FILE_PREFIX "/tmp/sandbox-"
+#define DEBUG_LOG_FILE_PREFIX "/tmp/sandbox-debug-"
+#define LOG_FILE_EXT ".log"
+
+#define ENV_SANDBOX_DEBUG_LOG "SANDBOX_DEBUG_LOG"
+#define ENV_SANDBOX_LOG "SANDBOX_LOG"
+#define ENV_SANDBOX_DIR "SANDBOX_DIR"
+#define ENV_SANDBOX_LIB "SANDBOX_LIB"
+
+#define ENV_SANDBOX_DENY "SANDBOX_DENY"
+#define ENV_SANDBOX_READ "SANDBOX_READ"
+#define ENV_SANDBOX_WRITE "SANDBOX_WRITE"
+#define ENV_SANDBOX_PREDICT "SANDBOX_PREDICT"
+
+#define ENV_SANDBOX_ON "SANDBOX_ON"
+#define ENV_SANDBOX_BEEP "SANDBOX_BEEP"
+
+#define DEFAULT_BEEP_COUNT 3
+
+char *get_sandbox_path(char *argv0);
+char *get_sandbox_lib(char *sb_path);
+char *get_sandbox_rc(char *sb_path);
+char *get_sandbox_log();
+char *sb_dirname(const char *path);
+int file_getmode(char *mode);
+long file_tell(int fp);
+int file_lock(int fd, int lock, char *filename);
+int file_unlock(int fd);
+int file_locktype(char *mode);
+int file_open(char *filename, char *mode, int perm_specified, ...);
+void file_close(int fd);
+long file_length(int fd);
+int file_truncate(int fd);
+int file_exist(char *filename, int checkmode);
+
+#endif
+
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox-dev/sandbox_futils.c b/src/sandbox-dev/sandbox_futils.c
new file mode 100644
index 00000000..e2aab3f6
--- /dev/null
+++ b/src/sandbox-dev/sandbox_futils.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2002 Brad House <brad@mainstreetsoftworks.com>
+ * Distributed under the terms of the GNU General Public License, v2 or later
+ * Author: Brad House <brad@mainstreetsoftworks.com>
+ *
+ * $Header: /var/cvsroot/gentoo-src/portage/src/sandbox-dev/Attic/sandbox_futils.c,v 1.3 2002/12/04 18:11:32 azarah Exp $
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "sandbox.h"
+
+
+char *get_sandbox_path(char *argv0)
+{
+ char path[255];
+ char *cwd = NULL;
+
+ /* ARGV[0] specifies full path */
+ if (argv0[0] == '/') {
+ strncpy(path, argv0, 254);
+
+ /* ARGV[0] specifies relative path */
+ } else {
+ getcwd(cwd, 253);
+ sprintf(path, "%s/%s", cwd, argv0);
+ if (cwd) free(cwd);
+ cwd = NULL;
+ }
+
+ /* Return just directory */
+ return(sb_dirname(path));
+}
+
+char *get_sandbox_lib(char *sb_path)
+{
+ char path[255];
+
+ snprintf(path, 254, "/lib/%s", LIB_NAME);
+ if (file_exist(path, 0) <= 0) {
+ snprintf(path, 254, "%s%s", sb_path, LIB_NAME);
+ }
+ return(strdup(path));
+}
+
+char *get_sandbox_rc(char *sb_path)
+{
+ char path[255];
+
+ snprintf(path, 254, "/usr/lib/portage/lib/%s", BASHRC_NAME);
+ if (file_exist(path, 0) <= 0) {
+ snprintf(path, 254, "%s%s", sb_path, BASHRC_NAME);
+ }
+ return(strdup(path));
+}
+
+char *get_sandbox_log()
+{
+ char path[255];
+ char pid_string[20];
+ char *sandbox_log_env = NULL;
+
+ sprintf(pid_string, "%d", getpid());
+
+ strcpy(path, LOG_FILE_PREFIX);
+ sandbox_log_env = getenv(ENV_SANDBOX_LOG);
+ if (sandbox_log_env) {
+ strcat(path, sandbox_log_env);
+ strcat(path, "-");
+ }
+ strcat(path, pid_string);
+ strcat(path, LOG_FILE_EXT);
+ return(strdup(path));
+}
+
+/* Obtain base directory name. Do not allow trailing / */
+char *sb_dirname(const char *path)
+{
+ char *ret = NULL;
+ char *ptr = NULL;
+ int loc = 0, i;
+ int cut_len = -1;
+
+ /* don't think NULL will ever be passed, but just in case */
+ if (NULL == path) return(strdup("."));
+
+ /* Grab pointer to last slash */
+ ptr = strrchr(path, '/');
+ if (NULL == ptr) {
+ return(strdup("."));
+ }
+
+ /* decimal location of pointer */
+ loc = ptr - path;
+
+ /* Remove any trailing slash */
+ for (i = loc-1; i >= 0; i--) {
+ if (path[i] != '/') {
+ cut_len = i + 1; /* make cut_len the length of the string to keep */
+ break;
+ }
+ }
+
+ /* It could have been just a plain /, return a 1byte 0 filled string */
+ if (-1 == cut_len) return(strdup(""));
+
+ /* Allocate memory, and return the directory */
+ ret = (char *)malloc((cut_len + 1) * sizeof(char));
+ memcpy(ret, path, cut_len);
+ ret[cut_len] = 0;
+
+ return(ret);
+}
+
+/*
+char* dirname(const char* path)
+{
+ char* base = NULL;
+ unsigned int length = 0;
+
+ base = strrchr(path, '/');
+ if (NULL == base)
+ {
+ return strdup(".");
+ }
+ while (base > path && *base == '/')
+ {
+ base--;
+ }
+ length = (unsigned int) 1 + base - path;
+
+ base = malloc(sizeof(char)*(length+1));
+ memmove(base, path, length);
+ base[length] = 0;
+
+ return base;
+}*/
+
+/* Convert text (string) modes to integer values */
+int file_getmode(char *mode)
+{
+ int mde = 0;
+ if (0 == strcasecmp(mode, "r+")) {
+ mde = O_RDWR | O_CREAT;
+ } else if (0 == strcasecmp(mode, "w+")) {
+ mde = O_RDWR | O_CREAT | O_TRUNC;
+ } else if (0 == strcasecmp(mode, "a+")) {
+ mde = O_RDWR | O_CREAT | O_APPEND;
+ } else if (0 == strcasecmp(mode, "r")) {
+ mde = O_RDONLY;
+ } else if (0 == strcasecmp(mode, "w")) {
+ mde = O_WRONLY | O_CREAT | O_TRUNC;
+ } else if (0 == strcasecmp(mode, "a")) {
+ mde = O_WRONLY | O_APPEND | O_CREAT;
+ } else {
+ mde = O_RDONLY;
+ }
+ return(mde);
+}
+
+/* Get current position in file */
+long file_tell(int fp)
+{
+ return(lseek(fp, 0L, SEEK_CUR));
+}
+
+/* lock the file, preferrably the POSIX way */
+int file_lock(int fd, int lock, char *filename)
+{
+ int err;
+#ifdef USE_FLOCK
+ if (flock(fd, lock) < 0) {
+ err = errno;
+ fprintf(stderr, ">>> %s flock file lock: %s\n", filename, strerror(err));
+ return 0;
+ }
+#else
+ struct flock fl;
+ fl.l_type = lock;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0L;
+ fl.l_len = 0L;
+ fl.l_pid = getpid();
+ if (fcntl(fd, F_SETLKW, &fl) < 0) {
+ err = errno;
+ fprintf(stderr, ">>> %s fcntl file lock: %s\n", filename, strerror(err));
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+/* unlock the file, preferrably the POSIX way */
+int file_unlock(int fd)
+{
+#ifdef USE_FLOCK
+ if (flock(fd, LOCK_UN) < 0) {
+ perror(">>> flock file unlock");
+ return 0;
+ }
+#else
+ struct flock fl;
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0L;
+ fl.l_len = 0L;
+ fl.l_pid = getpid();
+ if (fcntl(fd, F_SETLKW, &fl) < 0) {
+ perror(">>> fcntl file unlock");
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+/* Auto-determine from how the file was opened, what kind of lock to lock
+ * the file with
+ */
+int file_locktype(char *mode)
+{
+#ifdef USE_FLOCK
+ if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+')) || (NULL != strchr(mode, 'a')))
+ return(LOCK_EX);
+ return(LOCK_SH);
+#else
+ if (NULL != (strchr(mode, 'w')) || (NULL != strchr(mode, '+')) || (NULL != strchr(mode, 'a')))
+ return(F_WRLCK);
+ return(F_RDLCK);
+#endif
+}
+
+/* Use standard fopen style modes to open the specified file. Also auto-determines and
+ * locks the file either in shared or exclusive mode depending on opening mode
+ */
+int file_open(char *filename, char *mode, int perm_specified, ...)
+{
+ int fd;
+ char error[250];
+ va_list ap;
+ int perm;
+
+ if (perm_specified) {
+ va_start(ap, perm_specified);
+ perm = va_arg(ap, int);
+ va_end(ap);
+ }
+ if (perm_specified) {
+ fd = open(filename, file_getmode(mode), perm);
+ } else {
+ fd = open(filename, file_getmode(mode));
+ }
+ if (-1 == fd) {
+ snprintf(error, 249, ">>> %s file mode: %s open", filename, mode);
+ perror(error);
+ return(fd);
+ }
+ /* Only lock the file if opening succeeded */
+ if (-1 != fd) {
+ if (0 == file_lock(fd, file_locktype(mode), filename)) {
+ close(fd);
+ return -1;
+ }
+ } else {
+ snprintf(error, 249, ">>> %s file mode:%s open", filename, mode);
+ perror(error);
+ }
+ return(fd);
+}
+
+/* Close and unlock file */
+void file_close(int fd)
+{
+ if (-1 != fd) {
+ file_unlock(fd);
+ close(fd);
+ }
+}
+
+/* Return length of file */
+long file_length(int fd)
+{
+ long pos, len;
+ pos = file_tell(fd);
+ len = lseek(fd, 0L, SEEK_END);
+ lseek(fd, pos, SEEK_SET);
+ return(len);
+}
+
+/* Zero out file */
+int file_truncate(int fd)
+{
+ lseek(fd, 0L, SEEK_SET);
+ if (ftruncate(fd, 0) < 0) {
+ perror(">>> file truncate");
+ return 0;
+ }
+ return 1;
+}
+
+/* Check to see if a file exists Return: 1 success, 0 file not found, -1 error */
+int file_exist(char *filename, int checkmode)
+{
+ struct stat mystat;
+
+ /* Verify file exists and is regular file (not sym link) */
+ if (checkmode) {
+ if (-1 == lstat(filename, &mystat)) {
+ /* file doesn't exist */
+ if (ENOENT == errno) {
+ return 0;
+ } else { /* permission denied or other error */
+ perror(">>> stat file");
+ return -1;
+ }
+ }
+ if (!S_ISREG(mystat.st_mode))
+ return -1;
+
+ /* Just plain verify the file exists */
+ } else {
+ if (-1 == stat(filename, &mystat)) {
+ /* file does not exist */
+ if (ENOENT == errno) {
+ return 0;
+ } else { /* permission denied or other error */
+ perror(">>> stat file");
+ return -1;
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+// vim:expandtab noai:cindent ai
diff --git a/src/sandbox/Makefile b/src/sandbox/Makefile
new file mode 100644
index 00000000..9c8fe960
--- /dev/null
+++ b/src/sandbox/Makefile
@@ -0,0 +1,30 @@
+# Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+# Distributed under the terms of the GNU General Public License, v2 or later
+# Author : Geert Bevin <gbevin@uwyn.com>
+#
+# Modified 15 Apr 2002 Jon Nelson <jnelson@gentoo.org>
+# Clean up Makefile somewhat, and use make's implicit rules
+#
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/Attic/Makefile,v 1.5 2002/08/05 16:44:34 drobbins Exp $
+
+.SUFFIXES:
+.SUFFIXES: .c .o .so
+.PRECIOUS: %.o
+
+%.so: LIBS=-ldl
+%.so: LDFLAGS=--shared
+%.so: %.o
+ $(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ $(LIBS) $(LDFLAGS)
+
+CC = gcc
+CFLAGS = -Wall -O0 -fPIC
+LIBS =
+LDFLAGS =
+
+TARGETS = sandbox libsandbox.so
+
+all: $(TARGETS)
+
+clean:
+ rm -f $(TARGETS)
+ rm -f *.o *~
diff --git a/src/sandbox/libsandbox.c b/src/sandbox/libsandbox.c
new file mode 100644
index 00000000..d850554c
--- /dev/null
+++ b/src/sandbox/libsandbox.c
@@ -0,0 +1,873 @@
+/*
+** Path sandbox for the gentoo linux portage package system, initially
+** based on the ROCK Linux Wrapper for getting a list of created files
+**
+** to integrate with bash, bash should have been built like this
+**
+** ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
+**
+** it's very important that the --enable-static-link option is NOT specified
+**
+** Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+** Distributed under the terms of the GNU General Public License, v2 or later
+** Author : Geert Bevin <gbevin@uwyn.com>
+** $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/Attic/libsandbox.c,v 1.8 2002/08/05 05:51:39 drobbins Exp $
+*/
+
+#define _GNU_SOURCE
+#define _REENTRANT
+
+#define open xxx_open
+#define open64 xxx_open64
+# include <dirent.h>
+# include <dlfcn.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/file.h>
+# include <sys/stat.h>
+# include <sys/types.h>
+# include <unistd.h>
+# include <utime.h>
+#undef open
+#undef open64
+
+#define PIDS_FILE "/tmp/sandboxpids.tmp"
+
+typedef struct {
+ int show_access_violation;
+ char** deny_prefixes;
+ int num_deny_prefixes;
+ char** read_prefixes;
+ int num_read_prefixes;
+ char** write_prefixes;
+ int num_write_prefixes;
+ char** predict_prefixes;
+ int num_predict_prefixes;
+ char** write_denied_prefixes;
+ int num_write_denied_prefixes;
+} sbcontext_t;
+
+int check_access(sbcontext_t*, const char*, const char*);
+int check_syscall(sbcontext_t*, const char*, const char*);
+int before_syscall(const char*, const char*);
+int before_syscall_open_int(const char*, const char*, int);
+int before_syscall_open_char(const char*, const char*, const char*);
+void clean_env_entries(char***, int*);
+char* filter_path(const char*);
+void* get_dl_symbol(char*);
+void init_context(sbcontext_t*);
+void init_env_entries(char***, int*, char*, int);
+int is_sandbox_on();
+int is_sandbox_pid();
+
+/* Wrapper macros and functions */
+
+/* macro definition to wrap functions before and after the
+ execution of basic file related system-calls.
+
+ nr : the argument number of the system-call's argument that
+ contains the file name to monitor
+ rt : the return type of the system call
+ name : the name of the function call
+ arg1, arg2, arg3 : the types of the function call's arguments
+ fl : the argument number of the system-call's argument that
+ contains the file access flags
+ md : the argument number of the system-call's argument that
+ contains the file access mode
+*/
+#define wrsysc3(nr, rt, name, arg1, arg2, arg3) \
+ \
+/* the function call is defined externally from this file */ \
+extern rt name(arg1, arg2, arg3); \
+ \
+/* orig_ ## name is a pointer to a function with three arguments and the
+ return type of the system call. This will be used to store the pointer
+ to the system call function and call it. */ \
+rt (*orig_ ## name)(arg1, arg2, arg3) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2, arg3 a3) \
+{ \
+ rt result = -1; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || 1 == before_syscall(#name, a ## nr)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1, a2, a3); \
+ } \
+ return result; \
+}
+
+#define wrsysc2(nr, rt, name, arg1, arg2) \
+extern rt name(arg1, arg2); \
+rt (*orig_ ## name)(arg1, arg2) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2) \
+{ \
+ rt result = -1; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || 1 == before_syscall(#name, a ## nr)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1, a2); \
+ } \
+ return result; \
+}
+
+#define wrsysc1(nr, rt, name, arg1) \
+extern rt name(arg1); \
+rt (*orig_ ## name)(arg1) = NULL; \
+ \
+rt name(arg1 a1) \
+{ \
+ rt result = -1; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || 1 == before_syscall(#name, a ## nr)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1); \
+ } \
+ return result; \
+}
+
+#define wrsysc1ptr(nr, rt, name, arg1) \
+extern rt name(arg1); \
+rt (*orig_ ## name)(arg1) = NULL; \
+ \
+rt name(arg1 a1) \
+{ \
+ rt result = NULL; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || 1 == before_syscall(#name, a ## nr)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1); \
+ } \
+ return result; \
+}
+
+#define wropenint3(nr, fl, rt, name, arg1, arg2, arg3) \
+extern rt name(arg1, arg2, arg3); \
+rt (*orig_ ## name)(arg1, arg2, arg3) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2, arg3 a3) \
+{ \
+ rt result = -1; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || \
+ 1 == before_syscall_open_int(#name, a ## nr, a ## fl)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1, a2, a3); \
+ } \
+ return result; \
+}
+
+#define wropenchar2(nr, md, rt, name, arg1, arg2) \
+extern rt name(arg1, arg2); \
+rt (*orig_ ## name)(arg1, arg2) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2) \
+{ \
+ rt result = NULL; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || \
+ 1 == before_syscall_open_char(#name, a ## nr, a ## md)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1, a2); \
+ } \
+ return result; \
+}
+
+#define wropenchar3(nr, md, rt, name, arg1, arg2, arg3) \
+extern rt name(arg1, arg2, arg3); \
+rt (*orig_ ## name)(arg1, arg2, arg3) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2, arg3 a3) \
+{ \
+ rt result = NULL; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || \
+ 1 == before_syscall_open_char(#name, a ## nr, a ## md)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1, a2, a3); \
+ } \
+ return result; \
+}
+
+#define wrexec3(nr, rt, name, arg1, arg2, arg3) \
+extern rt name(arg1, arg2, arg3); \
+rt (*orig_ ## name)(arg1, arg2, arg3) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2, arg3 a3) \
+{ \
+ rt result = -1; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || 1 == before_syscall(#name, a ## nr)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1, a2, a3); \
+ } \
+ return result; \
+}
+
+#define wrexec2(nr, rt, name, arg1, arg2) \
+extern rt name(arg1, arg2); \
+rt (*orig_ ## name)(arg1, arg2) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2) \
+{ \
+ rt result = -1; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || 1 == before_syscall(#name, a ## nr)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = orig_ ## name(a1, a2); \
+ } \
+ return result; \
+}
+
+#define wrexec2va(nr, rt, name, arg1, arg2) \
+extern rt name(arg1, arg2, ...); \
+rt (*orig_ ## name)(arg1, arg2, ...) = NULL; \
+ \
+rt name(arg1 a1, arg2 a2, ...) \
+{ \
+ void* result = NULL; \
+ int old_errno = errno; \
+ if (0 == is_sandbox_on() || 1 == before_syscall(#name, a ## nr)) \
+ { \
+ if (!orig_ ## name) \
+ { \
+ orig_ ## name = get_dl_symbol(#name); \
+ } \
+ errno = old_errno; \
+ result = __builtin_apply( (void(*)()) orig_ ## name, \
+ __builtin_apply_args(), 32 ); \
+ old_errno = errno; \
+ } \
+ if (NULL == result) \
+ { \
+ return -1; \
+ } \
+ else \
+ { \
+ __builtin_return(result); \
+ } \
+}
+
+wropenint3(1, 2, int, open, const char*, int, mode_t)
+wropenint3(1, 2, int, open64, const char*, int, mode_t)
+
+wropenchar2(1, 2, FILE*, fopen, const char*, const char*)
+wropenchar2(1, 2, FILE*, fopen64, const char*, const char*)
+wropenchar3(1, 2, FILE*, freopen, const char*, const char*, FILE*)
+
+wropenchar2(1, 2, FILE*, popen, const char*, const char*)
+
+// write syscalls
+
+wrsysc2(1, int, creat, const char*, mode_t)
+wrsysc2(1, int, creat64, const char*, mode_t)
+
+wrsysc2(1, int, mkdir, const char*, mode_t)
+wrsysc3(1, int, mknod, const char*, mode_t, dev_t)
+wrsysc2(1, int, mkfifo, const char*, mode_t)
+
+wrsysc2(2, int, link, const char*, const char*)
+wrsysc2(2, int, symlink, const char*, const char*)
+wrsysc2(2, int, rename, const char*, const char*)
+
+wrsysc2(1, int, utime, const char*, const struct utimbuf*)
+wrsysc2(1, int, utimes, const char*, struct timeval*)
+
+wrsysc1(1, int, unlink, const char*)
+wrsysc1(1, int, rmdir, const char*)
+
+wrsysc3(1, int, chown, const char*, uid_t, gid_t)
+wrsysc3(1, int, lchown, const char*, uid_t, gid_t)
+
+wrsysc2(1, int, chmod, const char*, mode_t)
+
+/* read syscalls */
+
+wrsysc1ptr(1, DIR*, opendir, const char*)
+
+/* execution syscalls */
+wrsysc1(1, int, system, const char*)
+
+wrexec2va(1, int, execl, const char*, const char*)
+wrexec2va(1, int, execle, const char*, const char*)
+wrexec2(1, int, execv, const char*, char* const*)
+wrexec3(1, int, execve, const char*, char* const*, char* const*)
+/* execlp is redirected to execvp */
+/* execvp is special since it should search the PATH var entries */
+extern int execvp(const char*, char* const*);
+int(*orig_execvp)(const char*, char* const*) = NULL;
+int execvp(const char* file, char* const* argv)
+{
+ int result = -1;
+ int old_errno = errno;
+ int i = 0;
+ int allowed = 1;
+ char** path_entries = NULL;
+ int num_path_entries = 0;
+ char constructed_path[255];
+
+ if (1 == is_sandbox_on())
+ {
+ init_env_entries(&path_entries, &num_path_entries, "PATH", 0);
+ for (i = 0; i < num_path_entries; i++)
+ {
+ strcpy(constructed_path, path_entries[i]);
+ strcat(constructed_path, "/");
+ strcat(constructed_path, file);
+ if (0 == before_syscall("execvp", constructed_path))
+ {
+ allowed = 0;
+ break;
+ }
+ }
+ clean_env_entries(&path_entries, &num_path_entries);
+ }
+
+ if (1 == allowed)
+ {
+ if (!orig_execvp)
+ {
+ orig_execvp = get_dl_symbol("execvp");
+ }
+ errno = old_errno;
+ result = orig_execvp(file, argv);
+ old_errno = errno;
+ }
+ errno = old_errno;
+ return result;
+}
+
+/* lseek, lseek64, fdopen, fchown, fchmod, fcntl, lockf
+ are not wrapped since they can't be used if open is wrapped correctly
+ and unaccessible file descriptors are not possible to create */
+
+void* get_dl_symbol(char* symname)
+{
+ void* result = dlsym(RTLD_NEXT, symname);
+ if (0 == result)
+ {
+ fprintf(stderr, "Sandbox : can't resolve %s: %s.\n", symname, dlerror());
+ abort();
+ }
+ return result;
+}
+
+void init_context(sbcontext_t* context)
+{
+ context->show_access_violation = 1;
+ context->deny_prefixes = NULL;
+ context->num_deny_prefixes = 0;
+ context->read_prefixes = NULL;
+ context->num_read_prefixes = 0;
+ context->write_prefixes = NULL;
+ context->num_write_prefixes = 0;
+ context->predict_prefixes = NULL;
+ context->num_predict_prefixes = 0;
+ context->write_denied_prefixes = NULL;
+ context->num_write_denied_prefixes = 0;
+}
+
+int is_sandbox_pid()
+{
+ int result = 0;
+ FILE* pids_stream = NULL;
+ int pids_file = -1;
+ int current_pid = 0;
+ int tmp_pid = 0;
+
+ pids_stream = fopen(PIDS_FILE, "r");
+ if (NULL == pids_stream)
+ {
+ perror(">>> pids file fopen");
+ }
+ else
+ {
+ pids_file = fileno(pids_stream);
+ if (pids_file < 0)
+ {
+ perror(">>> pids file fileno");
+ }
+ else
+ {
+ current_pid = getpid();
+
+ while (EOF != fscanf(pids_stream, "%d\n", &tmp_pid))
+ {
+ if (tmp_pid == current_pid)
+ {
+ result = 1;
+ break;
+ }
+ }
+ }
+ if (EOF == fclose(pids_stream))
+ {
+ perror(">>> pids file fclose");
+ }
+ pids_stream = NULL;
+ pids_file = -1;
+ }
+
+ return result;
+}
+
+void clean_env_entries(char*** prefixes_array, int* prefixes_num)
+{
+ int i = 0;
+ if (NULL != *prefixes_array)
+ {
+ for (i = 0; i < *prefixes_num; i++)
+ {
+ if (NULL != (*prefixes_array)[i])
+ {
+ free((*prefixes_array)[i]);
+ (*prefixes_array)[i] = NULL;
+ }
+ }
+ free(*prefixes_array);
+ *prefixes_array = NULL;
+
+ *prefixes_num = 0;
+ }
+}
+
+void init_env_entries(char*** prefixes_array, int* prefixes_num, char* env, int warn)
+{
+ char* prefixes_env = getenv(env);
+
+ if (NULL == prefixes_env)
+ {
+ fprintf(stderr, "Sandbox error : the %s environmental variable should be defined.\n", env);
+ }
+ else
+ {
+ char* buffer = NULL;
+ int prefixes_env_length = strlen(prefixes_env);
+ int i = 0;
+ int num_delimiters = 0;
+ char* token = NULL;
+ char* prefix = NULL;
+
+ for (i = 0; i < prefixes_env_length; i++)
+ {
+ if (':' == prefixes_env[i])
+ {
+ num_delimiters++;
+ }
+ }
+
+ if (num_delimiters > 0)
+ {
+ buffer = (char*)malloc(sizeof(char)*(prefixes_env_length+1));
+ *prefixes_array = (char**)malloc(sizeof(char*)*(num_delimiters+1));
+
+ strcpy(buffer, prefixes_env);
+ token = strtok(buffer, ":");
+ while (NULL != token &&
+ strlen(token) > 0)
+ {
+ prefix = (char*)malloc(sizeof(char)*(strlen(token)+1));
+ strcpy(prefix, token);
+ (*prefixes_array)[(*prefixes_num)++] = filter_path(prefix);
+ free(prefix);
+ token = strtok(NULL, ":");
+ }
+ free(buffer);
+ buffer = NULL;
+ }
+ else if(prefixes_env_length > 0)
+ {
+ (*prefixes_array) = (char**)malloc(sizeof(char*));
+
+ prefix = (char*)malloc(sizeof(char)*(prefixes_env_length+1));
+ strcpy(prefix, prefixes_env);
+ (*prefixes_array)[(*prefixes_num)++] = filter_path(prefix);
+ free(prefix);
+ }
+ }
+}
+
+char* filter_path(const char* path)
+{
+ int initial_path_length = strlen(path);
+ char* filtered_path = (char*)malloc(sizeof(char)*(initial_path_length+1));
+ int i = 0;
+ int j = 0;
+
+ for (i = 0, j = 0; i < initial_path_length;)
+ {
+ filtered_path[j] = path[i];
+ if ('/' == filtered_path[j])
+ {
+ while ('/' == path[i] &&
+ i < initial_path_length)
+ {
+ i++;
+ }
+ }
+ else
+ {
+ i++;
+ }
+ j++;
+ }
+ filtered_path[j] = 0;
+
+ return filtered_path;
+}
+
+int check_access(sbcontext_t* sbcontext, const char* func, const char* path)
+{
+ int result = -1;
+ int i = 0;
+ char* filtered_path = filter_path(path);
+
+ if ('/' != path[0])
+ {
+ return 0;
+ }
+
+ if (0 == strcmp(filtered_path, "/etc/ld.so.preload") &&
+ is_sandbox_pid())
+ {
+ result = 1;
+ }
+
+ if (-1 == result)
+ {
+ if (NULL != sbcontext->deny_prefixes)
+ {
+ for (i = 0; i < sbcontext->num_deny_prefixes; i++)
+ {
+ if (0 == strncmp(filtered_path, sbcontext->deny_prefixes[i], strlen(sbcontext->deny_prefixes[i])))
+ {
+ result = 0;
+ break;
+ }
+ }
+ }
+
+ if (-1 == result)
+ {
+ if (NULL != sbcontext->read_prefixes &&
+ (0 == strcmp(func, "open_rd") ||
+ 0 == strcmp(func, "popen") ||
+ 0 == strcmp(func, "opendir") ||
+ 0 == strcmp(func, "system") ||
+ 0 == strcmp(func, "execl") ||
+ 0 == strcmp(func, "execlp") ||
+ 0 == strcmp(func, "execle") ||
+ 0 == strcmp(func, "execv") ||
+ 0 == strcmp(func, "execvp") ||
+ 0 == strcmp(func, "execve")))
+ {
+ for (i = 0; i < sbcontext->num_read_prefixes; i++)
+ {
+ if (0 == strncmp(filtered_path, sbcontext->read_prefixes[i], strlen(sbcontext->read_prefixes[i])))
+ {
+ result = 1;
+ break;
+ }
+ }
+ }
+ else if (NULL != sbcontext->write_prefixes &&
+ (0 == strcmp(func, "open_wr") ||
+ 0 == strcmp(func, "creat") ||
+ 0 == strcmp(func, "creat64") ||
+ 0 == strcmp(func, "mkdir") ||
+ 0 == strcmp(func, "mknod") ||
+ 0 == strcmp(func, "mkfifo") ||
+ 0 == strcmp(func, "link") ||
+ 0 == strcmp(func, "symlink") ||
+ 0 == strcmp(func, "rename") ||
+ 0 == strcmp(func, "utime") ||
+ 0 == strcmp(func, "utimes") ||
+ 0 == strcmp(func, "unlink") ||
+ 0 == strcmp(func, "rmdir") ||
+ 0 == strcmp(func, "chown") ||
+ 0 == strcmp(func, "lchown") ||
+ 0 == strcmp(func, "chmod")))
+ {
+ struct stat tmp_stat;
+
+ for (i = 0; i < sbcontext->num_write_denied_prefixes; i++)
+ {
+ if (0 == strncmp(filtered_path, sbcontext->write_denied_prefixes[i], strlen(sbcontext->write_denied_prefixes[i])))
+ {
+ result = 0;
+ break;
+ }
+ }
+ if (-1 == result)
+ {
+ for (i = 0; i < sbcontext->num_write_prefixes; i++)
+ {
+ if (0 == strncmp(filtered_path, sbcontext->write_prefixes[i], strlen(sbcontext->write_prefixes[i])))
+ {
+ result = 1;
+ break;
+ }
+ }
+
+ if (-1 == result)
+ {
+ /* hack to prevent mkdir of existing dirs to show errors */
+ if (strcmp(func, "mkdir") == 0)
+ {
+ if (0 == stat(filtered_path, &tmp_stat))
+ {
+ sbcontext->show_access_violation = 0;
+ result = 0;
+ }
+ }
+
+ if (-1 == result)
+ {
+ for (i = 0; i < sbcontext->num_predict_prefixes; i++)
+ {
+ if (0 == strncmp(filtered_path, sbcontext->predict_prefixes[i], strlen(sbcontext->predict_prefixes[i])))
+ {
+ sbcontext->show_access_violation = 0;
+ result = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (-1 == result)
+ {
+ result = 0;
+ }
+
+ free(filtered_path);
+
+ return result;
+}
+
+int check_syscall(sbcontext_t* sbcontext, const char* func, const char* file)
+{
+ int result = 1;
+ char* absolute_path = NULL;
+ char* tmp_buffer = NULL;
+ struct stat log_stat;
+ char* log_path = NULL;
+ int log_file = 0;
+ struct stat debug_log_stat;
+ char* debug_log_env = NULL;
+ char* debug_log_path = NULL;
+ int debug_log_file = 0;
+ char buffer[512];
+
+ if ('/' == file[0])
+ {
+ absolute_path = (char*)malloc(sizeof(char)*(strlen(file)+1));
+ sprintf(absolute_path, "%s", file);
+ }
+ else
+ {
+ tmp_buffer = get_current_dir_name();
+ absolute_path = (char*)malloc(sizeof(char)*(strlen(tmp_buffer)+1+strlen(file)+1));
+ sprintf(absolute_path,"%s/%s", tmp_buffer, file);
+ free(tmp_buffer);
+ tmp_buffer = NULL;
+ }
+
+ log_path = getenv("SANDBOX_LOG");
+ debug_log_env = getenv("SANDBOX_DEBUG");
+ debug_log_path = getenv("SANDBOX_DEBUG_LOG");
+
+ if ((NULL == log_path || 0 != strcmp(absolute_path, log_path)) &&
+ (NULL == debug_log_env || NULL == debug_log_path || 0 != strcmp(absolute_path, debug_log_path)) &&
+ 0 == check_access(sbcontext, func, absolute_path))
+ {
+ if (1 == sbcontext->show_access_violation)
+ {
+ fprintf(stderr, "\e[31;01mACCESS DENIED\033[0m %s:%*s%s\n", func, (int)(10-strlen(func)), "", absolute_path);
+
+ if (NULL != log_path)
+ {
+ sprintf(buffer, "%s:%*s%s\n", func, (int)(10-strlen(func)), "", absolute_path);
+ if (0 == lstat(log_path, &log_stat) &&
+ 0 == S_ISREG(log_stat.st_mode))
+ {
+ fprintf(stderr, "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n", log_path);
+ }
+ else
+ {
+ log_file = open(log_path, O_APPEND|O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if(log_file >= 0)
+ {
+ write(log_file, buffer, strlen(buffer));
+ close(log_file);
+ }
+ }
+ }
+ }
+
+ result = 0;
+ }
+ else if (NULL != debug_log_env)
+ {
+ if (NULL != debug_log_path)
+ {
+ if (0 != strcmp(absolute_path, debug_log_path))
+ {
+ sprintf(buffer, "%s:%*s%s\n", func, (int)(10-strlen(func)), "", absolute_path);
+ if (0 == lstat(debug_log_path, &debug_log_stat) &&
+ 0 == S_ISREG(debug_log_stat.st_mode))
+ {
+ fprintf(stderr, "\e[31;01mSECURITY BREACH\033[0m %s already exists and is not a regular file.\n", log_path);
+ }
+ else
+ {
+ debug_log_file = open(debug_log_path, O_APPEND|O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ if(debug_log_file >= 0)
+ {
+ write(debug_log_file, buffer, strlen(buffer));
+ close(debug_log_file);
+ }
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr, "\e[32;01mACCESS ALLOWED\033[0m %s:%*s%s\n", func, (int)(10-strlen(func)), "", absolute_path);
+ }
+ }
+
+ free(absolute_path);
+ absolute_path = NULL;
+
+ return result;
+}
+
+int is_sandbox_on()
+{
+ /* $SANDBOX_ACTIVE is an env variable that should ONLY
+ * be used internal by sandbox.c and libsanbox.c. External
+ * sources should NEVER set it, else the sandbox is enabled
+ * in some cases when run in parallel with another sandbox,
+ * but not even in the sandbox shell.
+ *
+ * Azarah (3 Aug 2002)
+ */
+ if (NULL != getenv("SANDBOX_ON") &&
+ 0 == strcmp(getenv("SANDBOX_ON"), "1") &&
+ NULL != getenv("SANDBOX_ACTIVE") &&
+ 0 == strcmp(getenv("SANDBOX_ACTIVE"), "armedandready"))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int before_syscall(const char* func, const char* file)
+{
+ int result = 1;
+
+ sbcontext_t sbcontext;
+
+ init_context(&sbcontext);
+
+ init_env_entries(&(sbcontext.deny_prefixes), &(sbcontext.num_deny_prefixes), "SANDBOX_DENY", 1);
+ init_env_entries(&(sbcontext.read_prefixes), &(sbcontext.num_read_prefixes), "SANDBOX_READ", 1);
+ init_env_entries(&(sbcontext.write_prefixes), &(sbcontext.num_write_prefixes), "SANDBOX_WRITE", 1);
+ init_env_entries(&(sbcontext.predict_prefixes), &(sbcontext.num_predict_prefixes), "SANDBOX_PREDICT", 1);
+
+ result = check_syscall(&sbcontext, func, file);
+
+ clean_env_entries(&(sbcontext.deny_prefixes), &(sbcontext.num_deny_prefixes));
+ clean_env_entries(&(sbcontext.read_prefixes), &(sbcontext.num_read_prefixes));
+ clean_env_entries(&(sbcontext.write_prefixes), &(sbcontext.num_write_prefixes));
+ clean_env_entries(&(sbcontext.predict_prefixes), &(sbcontext.num_predict_prefixes));
+
+ if (0 == result)
+ {
+ errno = EACCES;
+ }
+
+ return result;
+}
+
+int before_syscall_open_int(const char* func, const char* file, int flags)
+{
+ if (flags & O_WRONLY ||
+ flags & O_RDWR)
+ {
+ return before_syscall("open_wr", file);
+ }
+ else
+ {
+ return before_syscall("open_rd", file);
+ }
+}
+
+int before_syscall_open_char(const char* func, const char* file, const char* mode)
+{
+ if (strcmp(mode, "r") == 0 ||
+ strcmp(mode, "rb") == 0)
+ {
+ return before_syscall("open_rd", file);
+ }
+ else
+ {
+ return before_syscall("open_wr", file);
+ }
+}
diff --git a/src/sandbox/problems/Makefile b/src/sandbox/problems/Makefile
new file mode 100644
index 00000000..b44189bd
--- /dev/null
+++ b/src/sandbox/problems/Makefile
@@ -0,0 +1,31 @@
+# Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+# Distributed under the terms of the GNU General Public License, v2 or later
+# Author : Geert Bevin <gbevin@uwyn.com>
+#
+# Modified 15 Apr 2002 Jon Nelson <jnelson@gentoo.org>
+# Clean up Makefile somewhat, and use make's implicit rules
+#
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/problems/Attic/Makefile,v 1.2 2002/04/16 01:06:55 jnelson Exp $
+
+.SUFFIXES:
+.SUFFIXES: .c .o .so
+.PRECIOUS: %.o
+
+%.so: LIBS=-ldl
+%.so: LDFLAGS=--shared
+%.so: %.o
+ $(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@ $(LIBS) $(LDFLAGS)
+
+CC = gcc
+CFLAGS = -Wall -O2
+LIBS =
+LDFLAGS =
+
+TARGETS = sandbox_muttbug sandbox_dev_fd_foo \
+ libsandbox_muttbug.so libsandbox_emacsbug.so
+
+all: $(TARGETS)
+
+clean:
+ rm -f $(TARGETS)
+ rm -f *.o *~
diff --git a/src/sandbox/problems/libsandbox_emacsbug.c b/src/sandbox/problems/libsandbox_emacsbug.c
new file mode 100644
index 00000000..11e861b9
--- /dev/null
+++ b/src/sandbox/problems/libsandbox_emacsbug.c
@@ -0,0 +1,34 @@
+/* $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/problems/Attic/libsandbox_emacsbug.c,v 1.2 2003/03/22 14:24:38 carpaski Exp $ */
+
+#define _GNU_SOURCE
+#define _REENTRANT
+
+#define open xxx_open
+# include <dlfcn.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <stdlib.h>
+# include <sys/stat.h>
+# include <sys/types.h>
+#undef open
+
+extern int open(const char*, int, mode_t);
+int (*orig_open)(const char*, int, mode_t) = NULL;
+int open(const char* pathname, int flags, mode_t mode)
+{
+ int old_errno = errno;
+
+ /* code that makes xemacs' compilation produce a segfaulting executable */
+/* char** test = NULL;
+ test = (char**)malloc(sizeof(char*));
+ free(test);*/
+ /* end of that code */
+
+ if (!orig_open)
+ {
+ orig_open = dlsym(RTLD_NEXT, "open");
+ }
+ errno = old_errno;
+ return orig_open(pathname, flags, mode);
+}
+
diff --git a/src/sandbox/problems/libsandbox_muttbug.c b/src/sandbox/problems/libsandbox_muttbug.c
new file mode 100644
index 00000000..1d6e18c4
--- /dev/null
+++ b/src/sandbox/problems/libsandbox_muttbug.c
@@ -0,0 +1,24 @@
+/* $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/problems/Attic/libsandbox_muttbug.c,v 1.2 2003/03/22 14:24:38 carpaski Exp $ */
+
+#define _GNU_SOURCE
+#define _REENTRANT
+
+#define open xxx_open
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdio.h>
+#undef open
+
+extern FILE* fopen(const char*, const char*);
+FILE* (*orig_fopen)(const char*, const char*) = 0;
+FILE* fopen(const char* a1, const char* a2)
+{
+ int old_errno = errno;
+ if (!orig_fopen)
+ {
+ orig_fopen = dlsym(RTLD_NEXT, "fopen");
+ }
+ errno = old_errno;
+ return orig_fopen(a1, a2);
+}
+
diff --git a/src/sandbox/problems/sandbox_dev_fd_foo.c b/src/sandbox/problems/sandbox_dev_fd_foo.c
new file mode 100644
index 00000000..c36a095c
--- /dev/null
+++ b/src/sandbox/problems/sandbox_dev_fd_foo.c
@@ -0,0 +1,42 @@
+/* $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/problems/Attic/sandbox_dev_fd_foo.c,v 1.2 2003/03/22 14:24:38 carpaski Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+void cleanup_1(void)
+{
+ puts("Unlinking file...");
+ unlink("/tmp/_sandbox_test.file");
+}
+
+int main(void)
+{
+ struct stat s1, s2;
+ FILE *fp1, *fp2;
+ char *file = "/tmp/_sandbox_test.file";
+ char devfd[32];
+
+ printf("Opening file...\n");
+ if (!(fp1 = fopen(file, "w")))
+ exit(1);
+ atexit(cleanup_1);
+ printf("fstat'ing file...\n");
+ if (fstat(fileno(fp1), &s1) < 0)
+ exit(2);
+ sprintf(devfd, "/dev/fd/%d", fileno(fp1));
+ printf("fopening %s...\n", devfd);
+ if (!(fp2 = fopen(devfd, "w")))
+ exit(3);
+ printf("fstat'ing %s...\n", devfd);
+ if (fstat(fileno(fp2), &s2) < 0)
+ exit(4);
+ printf("Checking %ld == %ld and %ld == %ld...\n",
+ (long int) s1.st_dev, (long int) s2.st_dev, s1.st_ino, s2.st_ino);
+ if (s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino)
+ exit(5);
+ printf("Success!\n");
+ return(0);
+}
diff --git a/src/sandbox/problems/sandbox_muttbug.c b/src/sandbox/problems/sandbox_muttbug.c
new file mode 100644
index 00000000..cccdc43e
--- /dev/null
+++ b/src/sandbox/problems/sandbox_muttbug.c
@@ -0,0 +1,43 @@
+/* $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/problems/Attic/sandbox_muttbug.c,v 1.3 2003/03/22 14:24:38 carpaski Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ FILE *fd ;
+
+ printf("unlink\n");
+ unlink("/tmp/test");
+ printf("... done\n");
+
+ printf("fopen\n");
+ fd = fopen("/tmp/test", "a+");
+ printf("... done\n");
+
+ printf("fputc\n");
+ fputc('7', fd);
+ printf("... done\n");
+
+ printf("fseek\n");
+ fseek(fd, 0, SEEK_SET);
+ printf("... done\n");
+
+ printf("freopen\n");
+ fd = freopen("/tmp/test", "r", fd);
+ printf("... done\n");
+
+ printf("fgetc ");
+ printf("%c\n", fgetc(fd));
+ printf("... done\n");
+
+ printf("fseek\n");
+ fseek(fd, 0, SEEK_SET);
+ printf("... done\n");
+
+ printf("fclose\n");
+ fclose(fd);
+ printf("... done\n");
+ return 0;
+}
diff --git a/src/sandbox/sandbox.bashrc b/src/sandbox/sandbox.bashrc
new file mode 100644
index 00000000..be25349d
--- /dev/null
+++ b/src/sandbox/sandbox.bashrc
@@ -0,0 +1,8 @@
+# Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+# Distributed under the terms of the GNU General Public License, v2 or later
+# Author : Geert Bevin <gbevin@uwyn.com>
+# $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/Attic/sandbox.bashrc,v 1.2 2002/03/06 09:51:02 gbevin Exp $
+source /etc/profile
+export LD_PRELOAD="$SANDBOX_LIB"
+alias make="make LD_PRELOAD=$SANDBOX_LIB"
+alias su="su -c '/bin/bash -rcfile $SANDBOX_DIR/sandbox.bashrc'"
diff --git a/src/sandbox/sandbox.c b/src/sandbox/sandbox.c
new file mode 100644
index 00000000..5a2295e7
--- /dev/null
+++ b/src/sandbox/sandbox.c
@@ -0,0 +1,921 @@
+/*
+** Path sandbox for the gentoo linux portage package system, initially
+** based on the ROCK Linux Wrapper for getting a list of created files
+**
+** to integrate with bash, bash should have been built like this
+**
+** ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
+**
+** it's very important that the --enable-static-link option is NOT specified
+**
+** Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
+** Distributed under the terms of the GNU General Public License, v2 or later
+** Author : Geert Bevin <gbevin@uwyn.com>
+** $Header: /var/cvsroot/gentoo-src/portage/src/sandbox/Attic/sandbox.c,v 1.13 2002/08/05 05:51:39 drobbins Exp $
+*/
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define LD_PRELOAD_FILE "/etc/ld.so.preload"
+#define LIB_NAME "libsandbox.so"
+#define BASHRC_NAME "sandbox.bashrc"
+#define PIDS_FILE "/tmp/sandboxpids.tmp"
+#define LOG_FILE_PREFIX "/tmp/sandbox-"
+#define DEBUG_LOG_FILE_PREFIX "/tmp/sandbox-debug-"
+#define LOG_FILE_EXT ".log"
+
+#define ENV_SANDBOX_DEBUG_LOG "SANDBOX_DEBUG_LOG"
+#define ENV_SANDBOX_LOG "SANDBOX_LOG"
+#define ENV_SANDBOX_DIR "SANDBOX_DIR"
+#define ENV_SANDBOX_LIB "SANDBOX_LIB"
+
+#define ENV_SANDBOX_DENY "SANDBOX_DENY"
+#define ENV_SANDBOX_READ "SANDBOX_READ"
+#define ENV_SANDBOX_WRITE "SANDBOX_WRITE"
+#define ENV_SANDBOX_PREDICT "SANDBOX_PREDICT"
+
+#define ENV_SANDBOX_ON "SANDBOX_ON"
+#define ENV_SANDBOX_BEEP "SANDBOX_BEEP"
+
+#define DEFAULT_BEEP_COUNT 3
+
+int preload_adaptable = 1;
+int cleaned_up = 0;
+
+char* dirname(const char* path)
+{
+ char* base = NULL;
+ unsigned int length = 0;
+
+ base = strrchr(path, '/');
+ if (NULL == base)
+ {
+ return strdup(".");
+ }
+ while (base > path &&
+ *base == '/')
+ {
+ base--;
+ }
+ length = (unsigned int) 1 + base - path;
+
+ base = malloc(sizeof(char)*(length+1));
+ memmove(base, path, length);
+ base[length] = 0;
+
+ return base;
+}
+
+void cleanup()
+{
+ int i = 0;
+ int success = 1;
+
+ FILE* preload_stream = NULL;
+ int preload_file = -1;
+ char preload_entry[255];
+ char** preload_array = NULL;
+ int num_of_preloads = 0;
+
+ FILE* pids_stream = NULL;
+ struct stat pids_stat;
+ int pids_file = -1;
+ char pid_string[255];
+ int tmp_pid = 0;
+ int* pids_array = NULL;
+ int num_of_pids = 0;
+
+ /* remove this sandbox's bash pid from the global pids file if it has rights to adapt the ld.so.preload file*/
+ if (1 == preload_adaptable &&
+ 0 == cleaned_up)
+ {
+ cleaned_up = 1;
+ success = 1;
+ if (0 == lstat(PIDS_FILE, &pids_stat) &&
+ 0 == S_ISREG(pids_stat.st_mode))
+ {
+ perror(">>> pids file is not a regular file");
+ success = 0;
+ }
+ else
+ {
+ pids_stream = fopen(PIDS_FILE, "r+");
+ if (NULL == pids_stream)
+ {
+ perror(">>> pids file fopen");
+ success = 0;
+ }
+ else
+ {
+ pids_file = fileno(pids_stream);
+ if (pids_file < 0)
+ {
+ perror(">>> pids file fileno");
+ success = 0;
+ }
+ else
+ {
+ if (flock(pids_file, LOCK_EX) < 0)
+ {
+ perror(">>> pids file lock");
+ success = 0;
+ }
+ else
+ {
+ /* check which sandbox pids are still running */
+ while (EOF != fscanf(pids_stream, "%d\n", &tmp_pid))
+ {
+ if (0 == kill(tmp_pid, 0))
+ {
+ if (NULL == pids_array)
+ {
+ pids_array = (int*)malloc(sizeof(int));
+ }
+ else
+ {
+ pids_array = (int*)realloc(pids_array, sizeof(int)*(num_of_pids+1));
+ }
+ pids_array[num_of_pids++] = tmp_pid;
+ }
+ }
+
+ /* clean the /etc/ld.so.preload file if no other sandbox processes are running anymore*/
+ if(num_of_pids == 1)
+ {
+ success = 1;
+ preload_stream = fopen("/etc/ld.so.preload", "r+");
+ if (NULL == preload_stream)
+ {
+ perror(">>> /etc/ld.so.preload file fopen");
+ success = 0;
+ }
+ else
+ {
+ preload_file = fileno(preload_stream);
+ if (preload_file < 0)
+ {
+ perror(">>> /etc/ld.so.preload file fileno");
+ success = 0;
+ }
+ else
+ {
+ if (flock(preload_file, LOCK_EX) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file lock");
+ success = 0;
+ }
+ else
+ {
+ /* only get the entries that don't contain the sandbox library from the /etc/ld.so.preload file */
+ while (EOF != fscanf(preload_stream, "%s\n", preload_entry))
+ {
+ if (NULL == strstr(preload_entry, LIB_NAME))
+ {
+ if (NULL == preload_array)
+ {
+ preload_array = (char**)malloc(sizeof(char*));
+ }
+ else
+ {
+ preload_array = (char**)realloc(pids_array, sizeof(char*)*(num_of_preloads+1));
+ }
+ preload_array[num_of_preloads++] = strdup(preload_entry);
+ }
+ }
+
+ if (fseek(preload_stream, 0, SEEK_SET) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file fseek");
+ success = 0;
+ }
+ else
+ {
+ /* empty the /etc/ld.so.preload file */
+ if (ftruncate(preload_file, 0) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file ftruncate");
+ success = 0;
+ }
+ else
+ {
+ /* store the other preload libraries back into the /etc/ld.so.preload file */
+ if(num_of_preloads > 0)
+ {
+ for (i = 0; i < num_of_preloads; i++)
+ {
+ sprintf(preload_entry, "%s\n", preload_array[i]);
+ if (write(preload_file, preload_entry, strlen(preload_entry)) != strlen(preload_entry))
+ {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (NULL != preload_array)
+ {
+ for (i = 0; i < num_of_preloads; i++)
+ {
+ free(preload_array[i]);
+ preload_array[i] = NULL;
+ }
+ free(preload_array);
+ preload_array = NULL;
+ }
+
+ if (flock(preload_file, LOCK_UN) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file unlock");
+ success = 0;
+ }
+ }
+ }
+ if (EOF == fclose(preload_stream))
+ {
+ perror(">>> /etc/ld.so.preload file fclose");
+ success = 0;
+ }
+ preload_stream = NULL;
+ preload_file = -1;
+ }
+ }
+
+ if (fseek(pids_stream, 0, SEEK_SET) < 0)
+ {
+ perror(">>> pids file fseek");
+ success = 0;
+ }
+ else
+ {
+ /* empty the pids file */
+ if (ftruncate(pids_file, 0) < 0)
+ {
+ perror(">>> pids file ftruncate");
+ success = 0;
+ }
+ else
+ {
+ /* if pids are still running, write only the running pids back to the file */
+ if(num_of_pids > 1)
+ {
+ for (i = 0; i < num_of_pids; i++)
+ {
+ sprintf(pid_string, "%d\n", pids_array[i]);
+ if (write(pids_file, pid_string, strlen(pid_string)) != strlen(pid_string))
+ {
+ perror(">>> pids file write");
+ success = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (NULL != pids_array)
+ {
+ free(pids_array);
+ pids_array = NULL;
+ }
+
+ if (flock(pids_file, LOCK_UN) < 0)
+ {
+ perror(">>> pids file unlock");
+ success = 0;
+ }
+ }
+ }
+ if (EOF == fclose(pids_stream))
+ {
+ perror(">>> pids file fclose");
+ success = 0;
+ }
+ pids_stream = NULL;
+ pids_file = -1;
+ }
+ }
+ if (0 == success)
+ {
+ exit(1);
+ }
+ }
+}
+
+void stop(int signum)
+{
+ cleanup();
+}
+
+int main(int argc, char** argv)
+{
+ int i = 0;
+ int success = 1;
+ int status = 0;
+ char* run_str = "-c";
+ char run_arg[255];
+
+ struct stat preload_stat;
+ FILE* preload_stream = NULL;
+ int preload_file = -1;
+ char preload_entry[255];
+ int preload_lib_present = 0;
+
+ int bash_pid = 0;
+ char* home_dir = NULL;
+ char portage_tmp_dir[PATH_MAX];
+ char var_tmp_dir[PATH_MAX];
+ char tmp_dir[PATH_MAX];
+ char sandbox_write_var[255];
+ char sandbox_predict_var[255];
+ char* tmp_string = NULL;
+ char full_sandbox_path[255];
+ char sandbox_log[255];
+ char* sandbox_log_env;
+ struct stat sandbox_log_stat;
+ int sandbox_log_presence = 0;
+ int sandbox_log_file = -1;
+ char sandbox_debug_log[255];
+ char sandbox_dir[255];
+ char sandbox_lib[255];
+ struct stat sandbox_lib_stat;
+ char sandbox_rc[255];
+ struct stat sandbox_rc_stat;
+
+ struct stat pids_stat;
+ int pids_file = -1;
+ char pid_string[255];
+
+ // Only print info if called with no arguments ....
+ if (argc < 2)
+ {
+ printf("========================== Gentoo linux path sandbox ===========================\n");
+ }
+
+ /* check if a sandbox is already running */
+ if (NULL != getenv(ENV_SANDBOX_ON))
+ {
+ fprintf(stderr, "Not launching a new sandbox instance\nAnother one is already running in this process hierarchy.\n");
+
+ exit(1);
+ }
+ else
+ {
+ char* argv_bash[] =
+ {
+ "/bin/bash",
+ "-rcfile",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ /* determine the location of all the sandbox support files */
+ if (argc < 2)
+ printf("Detection of the support files.\n");
+ if ('/' == argv[0][0])
+ {
+ strcpy(full_sandbox_path, argv[0]);
+ }
+ else
+ {
+ tmp_string = get_current_dir_name();
+ strcpy(full_sandbox_path, tmp_string);
+ free(tmp_string);
+ tmp_string = NULL;
+ strcat(full_sandbox_path, "/");
+ strcat(full_sandbox_path, argv[0]);
+ }
+ tmp_string = dirname(full_sandbox_path);
+ strcpy(sandbox_dir, tmp_string);
+ free(tmp_string);
+ tmp_string = NULL;
+ strcat(sandbox_dir, "/");
+ strcpy(sandbox_lib, "/lib/");
+ strcat(sandbox_lib, LIB_NAME);
+ if (-1 == stat(sandbox_lib, &sandbox_lib_stat))
+ {
+ strcpy(sandbox_lib, sandbox_dir);
+ strcat(sandbox_lib, LIB_NAME);
+ }
+ strcpy(sandbox_rc, "/usr/lib/portage/lib/");
+ strcat(sandbox_rc, BASHRC_NAME);
+ if (-1 == stat(sandbox_rc, &sandbox_rc_stat))
+ {
+ strcpy(sandbox_rc, sandbox_dir);
+ strcat(sandbox_rc, BASHRC_NAME);
+ }
+
+ /* verify the existance of required files */
+ if (argc < 2)
+ {
+ printf("Verification of the required files.\n");
+ }
+ if (-1 == stat(sandbox_lib, &sandbox_lib_stat))
+ {
+ fprintf(stderr, "Could not open the sandbox library at '%s'.\n", sandbox_lib);
+ return -1;
+ }
+ else if (-1 == stat(sandbox_rc, &sandbox_rc_stat))
+ {
+ fprintf(stderr, "Could not open the sandbox rc file at '%s'.\n", sandbox_rc);
+ return -1;
+ }
+ else
+ {
+ /* ensure that the /etc/ld.so.preload file contains an entry for the sandbox lib */
+ if (argc < 2)
+ {
+ printf("Setting up the ld.so.preload file.\n");
+ }
+
+ /* check if the /etc/ld.so.preload file exists */
+ if (stat("/etc/ld.so.preload", &preload_stat) < 0 &&
+ ENOENT == errno)
+ {
+ /* if not, try to create it and write the path of the sandbox lib to it */
+ success = 1;
+ preload_file = open("/etc/ld.so.preload", O_WRONLY|O_CREAT, 0644);
+ if (preload_file < 0)
+ {
+ /* if access was denied, warn the user about it */
+ if (EACCES == errno)
+ {
+ preload_adaptable = 0;
+ printf(">>> Couldn't adapt the /etc/ld.so.preload file.\n>>> It's possible that not all function calls are trapped\n");
+ }
+ else
+ {
+ perror(">>> /etc/ld.so.preload file open");
+ success = 0;
+ }
+ }
+ else
+ {
+ if (flock(preload_file, LOCK_EX) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file lock");
+ success = 0;
+ }
+ else
+ {
+ if (write(preload_file, sandbox_lib, strlen(sandbox_lib)) != strlen(sandbox_lib))
+ {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ }
+
+ if (flock(preload_file, LOCK_UN) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file unlock");
+ success = 0;
+ }
+ }
+ if (close(preload_file) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file close");
+ success = 0;
+ }
+ pids_file = -1;
+ }
+ if (0 == success)
+ {
+ exit(1);
+ }
+ }
+ else
+ {
+ /* if the /etc/ld.so.preload file exists, try to open it in read/write mode */
+ success = 1;
+ if (0 == S_ISREG(preload_stat.st_mode))
+ {
+ perror(">>> /etc/ld.so.preload file is not a regular file");
+ success = 0;
+ }
+ else
+ {
+ preload_stream = fopen("/etc/ld.so.preload", "r+");
+ if (NULL == preload_stream)
+ {
+ if (EACCES == errno)
+ {
+ /* if access was denied, warn the user about it */
+ preload_adaptable = 0;
+ printf(">>> Couldn't adapt the /etc/ld.so.preload file.\n>>> It's possible that not all function calls are trapped\n");
+ }
+ else
+ {
+ perror(">>> /etc/ld.so.preload file fopen");
+ success = 0;
+ }
+ }
+ else
+ {
+ preload_file = fileno(preload_stream);
+ if (preload_file < 0)
+ {
+ perror(">>> /etc/ld.so.preload file fileno");
+ success = 0;
+ }
+ else
+ {
+ if (flock(preload_file, LOCK_EX) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file lock");
+ success = 0;
+ }
+ else
+ {
+ /* check if the sandbox library is already present in the /etc/ld.so.preload file */
+ while (EOF != fscanf(preload_stream, "%s\n", preload_entry))
+ {
+ if (NULL != strstr(preload_entry, LIB_NAME))
+ {
+ preload_lib_present = 1;
+ break;
+ }
+ }
+
+ /* if it's not present, add the sandbox lib path to the end of the /etc/ld.so.preload file */
+ if (0 == preload_lib_present)
+ {
+ if (fseek(preload_stream, 0, SEEK_END) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file fseek");
+ success = 0;
+ }
+ else
+ {
+ if (write(preload_file, sandbox_lib, strlen(sandbox_lib)) != strlen(sandbox_lib))
+ {
+ perror(">>> /etc/ld.so.preload file write");
+ success = 0;
+ }
+ }
+ }
+
+ if (flock(preload_file, LOCK_UN) < 0)
+ {
+ perror(">>> /etc/ld.so.preload file unlock");
+ success = 0;
+ }
+ }
+ }
+ if (EOF == fclose(preload_stream))
+ {
+ perror(">>> /etc/ld.so.preload file fclose");
+ success = 0;
+ }
+ preload_stream = NULL;
+ preload_file = -1;
+ }
+ }
+ if (0 == success)
+ {
+ exit(1);
+ }
+ }
+
+ /* set up the required environment variables */
+ if (argc < 2)
+ {
+ printf("Setting up the required environment variables.\n");
+ }
+ argv_bash[2] = sandbox_rc;
+
+ sprintf(pid_string, "%d", getpid());
+ strcpy(sandbox_log, LOG_FILE_PREFIX);
+ sandbox_log_env = getenv(ENV_SANDBOX_LOG);
+ if (sandbox_log_env)
+ {
+ strcat(sandbox_log, sandbox_log_env);
+ strcat(sandbox_log, "-");
+ }
+ strcat(sandbox_log, pid_string);
+ strcat(sandbox_log, LOG_FILE_EXT);
+ setenv(ENV_SANDBOX_LOG, sandbox_log, 1);
+ strcpy(sandbox_debug_log, DEBUG_LOG_FILE_PREFIX);
+ strcat(sandbox_debug_log, pid_string);
+ strcat(sandbox_debug_log, LOG_FILE_EXT);
+ setenv(ENV_SANDBOX_DEBUG_LOG, sandbox_debug_log, 1);
+ home_dir = getenv("HOME");
+
+ // drobbins: we need to expand these paths using realpath() so that PORTAGE_TMPDIR
+ // can contain symlinks (example, /var is a symlink, /var/tmp is a symlink.) Without
+ // this, access is denied to /var/tmp, hurtin' ebuilds.
+
+ realpath(getenv("PORTAGE_TMPDIR"),portage_tmp_dir);
+ realpath("/var/tmp",var_tmp_dir);
+ realpath("/tmp",tmp_dir);
+
+ setenv(ENV_SANDBOX_DIR, sandbox_dir, 1);
+ setenv(ENV_SANDBOX_LIB, sandbox_lib, 1);
+ setenv("LD_PRELOAD", sandbox_lib, 1);
+ if (NULL == getenv(ENV_SANDBOX_DENY))
+ {
+ setenv(ENV_SANDBOX_DENY, LD_PRELOAD_FILE, 1);
+ }
+ if (NULL == getenv(ENV_SANDBOX_READ))
+ {
+ setenv(ENV_SANDBOX_READ, "/", 1);
+ }
+ if (NULL == getenv(ENV_SANDBOX_WRITE))
+ {
+ /* these should go into make.globals later on */
+ strcpy(sandbox_write_var, "");
+ strcat(sandbox_write_var, "/dev/zero:/dev/fd/:/dev/null:/dev/pts/:/dev/vc/:/dev/tty:/tmp/");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/log/scrollkeeper.log");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, home_dir);
+ strcat(sandbox_write_var, "/.gconfd/lock");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, home_dir);
+ strcat(sandbox_write_var, "/.bash_history");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/tmp/conftest");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/lib/conftest");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/tmp/cf");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/usr/lib/cf");
+ strcat(sandbox_write_var, ":");
+ if (NULL == portage_tmp_dir)
+ {
+ strcat(sandbox_write_var, tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, var_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/tmp/");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/tmp/");
+ }
+ else if (0 == strcmp(sandbox_write_var, "/var/tmp/"))
+ {
+ strcat(sandbox_write_var, portage_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/tmp/");
+ }
+ else if (0 == strcmp(sandbox_write_var, "/tmp/"))
+ {
+ strcat(sandbox_write_var, portage_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, var_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/tmp/");
+ }
+ else
+ {
+ strcat(sandbox_write_var, portage_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, var_tmp_dir);
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/tmp/");
+ strcat(sandbox_write_var, ":");
+ strcat(sandbox_write_var, "/var/tmp/");
+ }
+ /* */
+ setenv(ENV_SANDBOX_WRITE, sandbox_write_var, 1);
+ }
+ if (NULL == getenv(ENV_SANDBOX_PREDICT))
+ {
+ /* these should go into make.globals later on */
+ strcpy(sandbox_predict_var, "");
+ strcat(sandbox_predict_var, home_dir);
+ strcat(sandbox_predict_var, "/.");
+ strcat(sandbox_predict_var, ":");
+ strcat(sandbox_predict_var, "/usr/lib/python2.0/");
+ strcat(sandbox_predict_var, ":");
+ strcat(sandbox_predict_var, "/usr/lib/python2.1/");
+ strcat(sandbox_predict_var, ":");
+ strcat(sandbox_predict_var, "/usr/lib/python2.2/");
+ setenv(ENV_SANDBOX_PREDICT, sandbox_predict_var, 1);
+ /* */
+ }
+ setenv(ENV_SANDBOX_ON, "1", 0);
+
+ /* if the portage temp dir was present, cd into it */
+ if (NULL != portage_tmp_dir)
+ {
+ chdir(portage_tmp_dir);
+ }
+
+ /* adding additional bash arguments */
+ for (i = 1; i < argc; i++)
+ {
+ if (1 == i)
+ {
+ argv_bash[3] = run_str;
+ argv_bash[4] = run_arg;
+ strcpy(argv_bash[4], argv[i]);
+ }
+ else
+ {
+ strcat(argv_bash[4], " ");
+ strcat(argv_bash[4], argv[i]);
+ }
+ }
+
+ /* set up the required signal handlers */
+ signal(SIGHUP, &stop);
+ signal(SIGINT, &stop);
+ signal(SIGQUIT, &stop);
+ signal(SIGTERM, &stop);
+
+ /* this one should NEVER be set in ebuilds, as it is the one
+ * private thing libsandbox.so use to test if the sandbox
+ * should be active for this pid, or not.
+ *
+ * azarah (3 Aug 2002)
+ */
+ setenv("SANDBOX_ACTIVE", "armedandready", 1);
+
+ /* fork to executing bash */
+ if (argc < 2)
+ {
+ printf("Creating a seperate process the run the shell in.\n");
+ }
+ bash_pid = fork();
+
+ if (0 == bash_pid)
+ {
+ /* launch bash */
+ execv(argv_bash[0], argv_bash);
+ }
+ else
+ {
+ int wait_pid = 0;
+
+ if (argc < 2)
+ {
+ printf("The protected environment has been started.\n");
+ printf("--------------------------------------------------------------------------------\n");
+ }
+
+ /* store his sandbox's bash pid in the global pids file if it has rights to adapt the ld.so.preload file*/
+ if (1 == preload_adaptable)
+ {
+ success = 1;
+ if (0 == lstat(PIDS_FILE, &pids_stat) &&
+ 0 == S_ISREG(pids_stat.st_mode))
+ {
+ perror(">>> pids file is not a regular file");
+ success = 0;
+ }
+ else
+ {
+ pids_file = open(PIDS_FILE, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ if (pids_file < 0)
+ {
+ perror(">>> pids file open");
+ success = 0;
+ }
+ else
+ {
+ if (flock(pids_file, LOCK_EX) < 0)
+ {
+ perror(">>> pids file lock");
+ success = 0;
+ }
+ else
+ {
+ sprintf(pid_string, "%d\n", getpid());
+ if (write(pids_file, pid_string, strlen(pid_string)) != strlen(pid_string))
+ {
+ perror(">>> pids file write");
+ success = 0;
+ }
+
+ if (flock(pids_file, LOCK_UN) < 0)
+ {
+ perror(">>> pids file unlock");
+ success = 0;
+ }
+ }
+ if (close(pids_file) < 0)
+ {
+ perror(">>> pids file close");
+ success = 0;
+ }
+ pids_file = -1;
+ }
+ }
+ if (0 == success)
+ {
+ exit(1);
+ }
+ }
+
+ /* wait until bash exits */
+ wait_pid = waitpid(bash_pid, &status, 0);
+ }
+ }
+
+ cleanup();
+
+ if (argc < 2)
+ {
+ printf("========================== Gentoo linux path sandbox ===========================\n");
+ printf("The protected environment has been shut down.\n");
+ }
+ if (0 == stat(sandbox_log, &sandbox_log_stat))
+ {
+ sandbox_log_presence = 1;
+ success = 1;
+ sandbox_log_file = open(sandbox_log, O_RDONLY, 0);
+ if (sandbox_log_file < 0)
+ {
+ perror(">>> sandbox log file open");
+ success = 0;
+ }
+ else
+ {
+ int i = 0;
+ char* beep_count_env = NULL;
+ int beep_count = 0;
+ int length = 0;
+ char buffer[255];
+
+ printf("\e[31;01m--------------------------- ACCESS VIOLATION SUMMARY ---------------------------\033[0m\n");
+ printf("\e[31;01mLOG FILE = \"%s\"\033[0m\n", sandbox_log);
+ printf("\n");
+ while ((length = read(sandbox_log_file, buffer, sizeof(buffer)-1)) > 0)
+ {
+ if (length < sizeof(buffer))
+ {
+ buffer[length] = 0;
+ }
+ printf("%s", buffer);
+ }
+ printf("\e[31;01m--------------------------------------------------------------------------------\033[0m\n");
+
+ if (close(sandbox_log_file) < 0)
+ {
+ perror(">>> sandbox log close");
+ success = 0;
+ }
+
+ beep_count_env = getenv(ENV_SANDBOX_BEEP);
+ if (beep_count_env)
+ {
+ beep_count = atoi(beep_count_env);
+ }
+ else
+ {
+ beep_count = DEFAULT_BEEP_COUNT;
+ }
+ for (i = 0; i < beep_count; i++)
+ {
+ fputc('\a', stderr);
+ if (i < beep_count -1)
+ {
+ sleep(1);
+ }
+ }
+
+ }
+ if (0 == success)
+ {
+ exit(1);
+ }
+ sandbox_log_file = -1;
+ }
+ else if (argc < 2)
+ {
+ printf("--------------------------------------------------------------------------------\n");
+ }
+
+ if (status > 0 ||
+ 1 == sandbox_log_presence)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
diff --git a/src/tbz2tool.c b/src/tbz2tool.c
new file mode 100644
index 00000000..c740d443
--- /dev/null
+++ b/src/tbz2tool.c
@@ -0,0 +1,228 @@
+/* $Header: /var/cvsroot/gentoo-src/portage/src/tbz2tool.c,v 1.3.2.1 2004/11/05 13:49:22 jstubbs Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+/*buffered reading/writing size*/
+#define BUFLEN 262144
+char *myname="tbz2tool";
+struct stat *mystat=NULL;
+void *mybuf;
+FILE *datafile, *dbfile, *outfile, *infile;
+unsigned char endbuf[8];
+long seekto,insize;
+
+int exists(const char *myfile) {
+ int result;
+ result=stat(myfile,mystat);
+ if (result==-1)
+ return 0;
+ return 1;
+}
+
+void writefile(FILE *src, FILE *dest) {
+ int count=1;
+ while (count) {
+ count=fread(mybuf, 1, BUFLEN, src);
+ fwrite(mybuf, 1, count, dest);
+ }
+}
+
+void writefileto(FILE *src, FILE *dest, int endpos) {
+ int pos=ftell(src);
+ int thiscount;
+ while (pos < endpos) {
+ /* thiscount=how much to read */
+ thiscount=endpos-pos;
+ if (thiscount>BUFLEN)
+ thiscount=BUFLEN;
+ thiscount=fread(mybuf, 1, thiscount , src);
+ /* thiscount=how much we actually did read */
+ if (thiscount==0)
+ /* eof -- shouldn't happen */
+ break;
+ /* update internal position counter */
+ pos+=thiscount;
+ fwrite(mybuf, 1, thiscount, dest);
+ }
+}
+
+int main(int argc, char **argv) {
+ if ((argc==2) && (!(strcmp(argv[1],"--help"))))
+ goto usage;
+ if (argc!=5) {
+ printf("%s: four arguments expected\n",myname);
+ goto error;
+ }
+ if (!(mystat=(struct stat *) malloc(sizeof(struct stat))))
+ goto memalloc;
+
+ if (!(mybuf=(void *) malloc(BUFLEN))) {
+ free(mystat);
+ goto memalloc;
+ }
+
+ /* JOIN MODE */
+ if (!(strcmp(argv[1],"join"))) {
+
+ /* check if datafile exists */
+ if (!(exists(argv[2]))) {
+ printf("%s: %s doesn't exist\n",myname,argv[2]);
+ free(mystat);
+ goto error;
+ }
+
+ /* check if dbfile exists */
+ if (!(exists(argv[3]))) {
+ printf("%s: %s doesn't exist\n",myname,argv[3]);
+ free(mystat);
+ goto error;
+ }
+ /* create end buffer for later use */
+ endbuf[0]=((mystat->st_size) & 0xff000000) >> 24;
+ endbuf[1]=((mystat->st_size) & 0x00ff0000) >> 16;
+ endbuf[2]=((mystat->st_size) & 0x0000ff00) >> 8;
+ endbuf[3]=(mystat->st_size) & 0x000000ff;
+ endbuf[4]='S';
+ endbuf[5]='T';
+ endbuf[6]='O';
+ endbuf[7]='P';
+
+ /* if outfile exists, unlink first (safer) */
+ if (exists(argv[4]))
+ unlink(argv[4]);
+
+ /* open datafile for reading */
+ if ((datafile=fopen(argv[2],"r"))==NULL) {
+ free(mybuf);
+ free(mystat);
+ printf("%s: Error opening %s\n",myname,argv[2]);
+ goto error;
+ }
+
+ /* open dbfile for reading */
+ if ((dbfile=fopen(argv[3],"r"))==NULL) {
+ fclose(datafile);
+ free(mybuf);
+ free(mystat);
+ printf("%s: Error opening %s\n",myname,argv[3]);
+ goto error;
+ }
+
+ /* open outfile for writing */
+ if ((outfile=fopen(argv[4],"a"))==NULL) {
+ fclose(dbfile);
+ fclose(datafile);
+ free(mybuf);
+ free(mystat);
+ printf("%s: Error opening %s\n",myname,argv[4]);
+ goto error;
+ }
+
+ writefile(datafile,outfile);
+ writefile(dbfile,outfile);
+ fwrite(endbuf,1,8,outfile);
+ fclose(outfile);
+ fclose(dbfile);
+ fclose(datafile);
+ free(mybuf);
+ free(mystat);
+ exit(0);
+
+ /* SPLIT MODE */
+ } else if (!(strcmp(argv[1],"split"))) {
+
+ /* check if infile exists */
+ if (!(exists(argv[2]))) {
+ printf("%s: %s doesn't exist\n",myname,argv[2]);
+ free(mystat);
+ goto error;
+ }
+
+ /* store infile size for later use */
+
+ insize=mystat->st_size;
+
+ /* if datafile exists, unlink first (safer) */
+ if (exists(argv[3]))
+ unlink(argv[3]);
+
+ /* if dbfile exists, unlink first (safer) */
+ if (exists(argv[4]))
+ unlink(argv[4]);
+
+ /* open infile for reading */
+ if ((infile=fopen(argv[2],"r"))==NULL) {
+ free(mybuf);
+ free(mystat);
+ printf("%s: Error opening %s\n",myname,argv[2]);
+ goto error;
+ }
+
+ /* read in end buffer */
+ fseek(infile,-8,SEEK_END);
+ fread(endbuf,1,8,infile);
+ /* quick end buffer read and verification */
+ if ( (endbuf[4]!='S') || (endbuf[5]!='T') || (endbuf[6]!='O') || (endbuf[7]!='P') ) {
+ fclose(infile);
+ free(mybuf);
+ free(mystat);
+ printf("%s: %s appears to be corrupt (end buffer invalid)\n",myname,argv[2]);
+ goto error;
+ }
+
+ seekto=0;
+ seekto=seekto+endbuf[0]*256*256*256;
+ seekto=seekto+endbuf[1]*256*256;
+ seekto=seekto+endbuf[2]*256;
+ seekto=seekto+endbuf[3];
+
+ /* open datafile for writing */
+ if ((datafile=fopen(argv[3],"a"))==NULL) {
+ fclose(infile);
+ free(mybuf);
+ free(mystat);
+ printf("%s: Error opening %s\n",myname,argv[3]);
+ goto error;
+ }
+
+ /* open dbfile for writing */
+ if ((dbfile=fopen(argv[4],"a"))==NULL) {
+ fclose(datafile);
+ fclose(infile);
+ free(mybuf);
+ free(mystat);
+ printf("%s: Error opening %s\n",myname,argv[4]);
+ goto error;
+ }
+
+ rewind(infile);
+ writefileto(infile,datafile,insize-(seekto+8));
+ fseek(infile,-(seekto+8),SEEK_END);
+ writefileto(infile,dbfile,insize-8);
+ fclose(infile);
+ fclose(dbfile);
+ fclose(datafile);
+ free(mybuf);
+ free(mystat);
+ exit(0);
+
+ } else {
+ free(mybuf);
+ free(mystat);
+ goto usage;
+ }
+
+ usage:
+ printf("Usage: %s join DATAFILE DBFILE OUTFILE (datafile + dbfile -> outfile)\n %s split INFILE DATAFILE DBFILE (infile -> datafile + dbfile)\n",myname,myname);
+error:
+ exit(1);
+memalloc:
+ printf("%s: memory allocation error\n",myname);
+ exit(2);
+}
diff --git a/tabcheck.py b/tabcheck.py
new file mode 100755
index 00000000..1699e988
--- /dev/null
+++ b/tabcheck.py
@@ -0,0 +1,6 @@
+#!/usr/bin/python -O
+
+import tabnanny,sys
+
+for x in sys.argv:
+ tabnanny.check(x)
diff --git a/tarball.sh b/tarball.sh
new file mode 100755
index 00000000..254955c4
--- /dev/null
+++ b/tarball.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# $Header: /var/cvsroot/gentoo-src/portage/Attic/tarball.sh,v 1.181.2.2 2005/05/01 16:04:51 jstubbs Exp $
+
+if [ -z "$1" ]; then
+ echo
+ echo "You need to have the version specified."
+ echo "e.g.: $0 2.0.39-r37"
+ echo
+ exit 0
+fi
+
+export PKG="portage"
+export TMP="/tmp"
+export V="$1"
+export DEST="${TMP}/${PKG}-${V}"
+export PREVEB="2.0.49_pre2"
+
+./tabcheck.py bin/emerge `find ./ -type f -name '*.py'`
+
+if [ -e $TMP/${PKG}-${V} ]; then
+ echo EXISTS ALREADY
+ exit 1
+fi
+
+rm -rf ${DEST}
+install -d -m0755 ${DEST}
+#get any binaries out of the way
+cd src/sandbox-1.1
+make clean
+cd ../..
+for x in bin cnf man pym src
+do
+ cp -ax $x ${DEST}
+done
+# Clean invalid sandbox sources
+rm -rf ${DEST}/src/{sandbox,sandbox-dev}
+cp ${DEST}/pym/portage.py ${DEST}/pym/portage.py.orig
+sed '/^VERSION=/s/^.*$/VERSION="'${V}'"/' < ${DEST}/pym/portage.py.orig > ${DEST}/pym/portage.py
+cp ${DEST}/man/emerge.1 ${DEST}/man/emerge.1.orig
+sed "s/##VERSION##/${V}/g" < ${DEST}/man/emerge.1.orig > ${DEST}/man/emerge.1
+rm ${DEST}/pym/portage.py.orig ${DEST}/man/emerge.1.orig
+rm ${DEST}/man/*.eclass.5
+
+sed -i -e "s:\t: :g" ChangeLog
+cp ChangeLog ${DEST}
+
+cd ${DEST}
+find -name CVS -exec rm -rf {} \;
+find -name '*~' -exec rm -rf {} \;
+find -name '*.pyc' -exec rm -rf {} \;
+find -name '*.pyo' -exec rm -rf {} \;
+chown -R root:root ${DEST}
+cd $TMP
+rm -f ${PKG}-${V}/bin/emerge.py ${PKG}-${V}/bin/{pmake,sandbox} ${PKG}-${V}/{bin,pym}/'.#'* ${PKG}-${V}/{bin,pym}/*.{orig,diff} ${PKG}-${V}/{bin,pym}/*.py[oc]
+tar cjvf ${TMP}/${PKG}-${V}.tar.bz2 ${PKG}-${V}
+
+#scp ${TMP}/${PKG}-${V}.tar.bz2 carpaski@twobit.net:/home/html/gentoo/portage/
+#scp ${TMP}/${PKG}-${V}.tar.bz2 carpaski@zarquon.twobit.net:/home/www/localhost/htdocs/gentoo/portage/