Autoconfify razor.
authorRichard Hughes <rhughes@redhat.com>
Mon Jun 16 15:40:30 2008 -0400 (2008-06-16)
changeset 241c3eb520e2219
parent 240 edd5fe0a00ba
child 242 f2218527ad4a
Autoconfify razor.

committer: Kristian H?gsberg <krh@redhat.com>
.gitignore
AUTHORS
DEPSOLVE.txt
Makefile
Makefile.am
NEWS
REPO.txt
autogen.sh
bash-completion.sh
configure.ac
contrib/razor.spec
data/.gitignore
data/Makefile.am
data/bash-completion.sh
data/razor.pc.in
docs/DEPSOLVE.txt
docs/Makefile.am
docs/REPO.txt
librazor/.gitignore
librazor/Makefile.am
librazor/razor-internal.h
librazor/razor-root.c
librazor/razor.c
librazor/razor.h
librazor/rpm.c
librazor/types.c
librazor/types.h
librazor/util.c
main.c
po/.gitignore
po/LINGUAS
po/POTFILES.in
razor-internal.h
razor-root.c
razor.c
razor.h
rpm-razor.c
rpm.c
src/.gitignore
src/Makefile.am
src/import-rpmdb.c
src/import-yum.c
src/main.c
src/rpm.c
src/test-driver.c
src/test.xml
test-driver.c
test.xml
types.c
types.h
util.c
yum.c
     1.1 --- a/.gitignore	Sun Jun 15 23:15:59 2008 -0400
     1.2 +++ b/.gitignore	Mon Jun 16 15:40:30 2008 -0400
     1.3 @@ -1,10 +1,32 @@
     1.4 -.gitignore
     1.5 +aclocal.m4
     1.6 +autom4te.cache
     1.7 +compile
     1.8 +config.guess
     1.9 +config.h
    1.10 +config.h.in
    1.11 +config.log
    1.12 +config.status
    1.13 +config.sub
    1.14 +configure
    1.15 +depcomp
    1.16 +INSTALL
    1.17 +install-sh
    1.18 +intltool-extract
    1.19 +intltool-extract.in
    1.20 +intltool-merge
    1.21 +intltool-merge.in
    1.22 +intltool-update
    1.23 +intltool-update.in
    1.24 +libtool
    1.25 +ltmain.sh
    1.26 +Makefile
    1.27 +Makefile.in
    1.28 +missing
    1.29 +mkinstalldirs
    1.30 +py-compile
    1.31 +stamp-h1
    1.32  *.o
    1.33 +ChangeLog
    1.34 +*.tar.gz
    1.35  *~
    1.36 -*.repo
    1.37 -razor
    1.38 -test-driver
    1.39 -pkgs
    1.40 -set
    1.41 -primary.xml.gz
    1.42 -filelists.xml.gz
    1.43 +
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/AUTHORS	Mon Jun 16 15:40:30 2008 -0400
     2.3 @@ -0,0 +1,2 @@
     2.4 +Kristian Høgsberg <krh@redhat.com>
     2.5 +
     3.1 --- a/DEPSOLVE.txt	Sun Jun 15 23:15:59 2008 -0400
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,364 +0,0 @@
     3.4 -YUM vs RAZOR
     3.5 -------------
     3.6 -
     3.7 -At a very high level, yum's depsolver does something roughly
     3.8 -equivalent to:
     3.9 -
    3.10 -    - For each package being installed or removed
    3.11 -
    3.12 -	- For each relevant property (provides, requires, conflicts,
    3.13 -          obsoletes):
    3.14 -
    3.15 -	    - Figure out what additional packages need to be added to
    3.16 -	      or removed from the system to satisfy this property
    3.17 -
    3.18 -which ends up being roughly O(N^2 * M) where N is the total number of
    3.19 -properties and M is the number of packages being acted on.
    3.20 -
    3.21 -(I just figured that out off the top of my head, and I'm not totally
    3.22 -familiar with the yum code, so it may be wrong.)
    3.23 -
    3.24 -Razor's depsolver is something like:
    3.25 -
    3.26 -    - do {
    3.27 -
    3.28 -	- For each property to be added to or removed from the system:
    3.29 -
    3.30 -	    - Figure out what packages need to be added to or removed
    3.31 -	      from the system to satisfy this property
    3.32 -
    3.33 -    - } until we stop adding/remove more packages
    3.34 -
    3.35 -with the key being that it's very easy to find the PROVIDES
    3.36 -corresponding to a REQUIRES and vice versa, because the property
    3.37 -arrays are sorted, and so all properties with the same "name" will be
    3.38 -adjacent to one another in the array, allowing many dependencies to be
    3.39 -satisified in essentially constant time. (Actually... we've been
    3.40 -calling it constant, but it's really O(log N) for heavily-depended-on
    3.41 -packages, because the more packages you have, the more variations on
    3.42 -"requires foo", "requires foo = 1.1", "requires foo > 1.0", etc you're
    3.43 -going to have to scan through.)
    3.44 -
    3.45 -Ideally though, each iteration of the inner loop body happens in
    3.46 -constant time, and thus the inner loop as a whole is O(N), and thus
    3.47 -the depsolver as a whole is O(N * M) (or at least, less than
    3.48 -O(N * M * log N).
    3.49 -
    3.50 -
    3.51 -FILE DEPENDENCIES
    3.52 ------------------
    3.53 -
    3.54 -Whenever we add a package with a file REQUIRES to a razor_set, we also
    3.55 -add a PROVIDES for that file to the package or packages which provide
    3.56 -that file. This means that if we later add another package that
    3.57 -requires the same file (eg, /bin/sh or /usr/bin/perl), we can resolve
    3.58 -its file requirement exactly like we would resolve a property
    3.59 -requirement, in nearly constant time.
    3.60 -
    3.61 -When adding a *new* file requirement (ie, a requirement on a file that
    3.62 -no existing package depends on), we still have to scan through the
    3.63 -file tree, which is O(log N) in the number of files.
    3.64 -
    3.65 -(AFAICT, there's no reason yum couldn't do the same optimization.
    3.66 -Also, AFAICT, yum currently sticks property dependencies and file
    3.67 -dependencies into the same hash table, so that if any package in the
    3.68 -transaction has a file dependency, it causes *property* dependencies
    3.69 -to become slower to resolve as well...)
    3.70 -
    3.71 -
    3.72 -THE RULES
    3.73 ----------
    3.74 -
    3.75 -This is what we have figured out for transaction-solving rules;
    3.76 -neither yum nor rpm's algorithm seems to be explained in full
    3.77 -anywhere...
    3.78 -
    3.79 -    1. Every requested install in the initial package set must be
    3.80 -       satisfied as either a new install or an update:
    3.81 -
    3.82 -	- if the requested package name is the name of an upstream
    3.83 -          package:
    3.84 -
    3.85 -	    - if there is not a corresponding already-installed
    3.86 -              package, then install the upstream package
    3.87 -
    3.88 -	    - else if the upstream package is newer than the
    3.89 -              already-installed package, then update the package
    3.90 -
    3.91 -	    - else it's an error (UP_TO_DATE)
    3.92 -
    3.93 -	- else if the requested package name is the name of an
    3.94 -          already-installed package:
    3.95 -
    3.96 -	    - if there is an upstream package that obsoletes the
    3.97 -              already-installed package, then behave as though the
    3.98 -              user had requested that that package be installed
    3.99 -              instead.
   3.100 -
   3.101 -	    - else it's an error (UP_TO_DATE or INSTALL_UNAVAILABLE?)
   3.102 -
   3.103 -	- else it's an error (INSTALL_UNAVAILABLE)
   3.104 -
   3.105 -    2. Every requested removal in the initial package set must be
   3.106 -       satisfied as a removal. If any requested package name is not
   3.107 -       the name of an installed package, it's an error
   3.108 -       (REMOVE_NOT_INSTALLED)
   3.109 -
   3.110 -    REQUIRES processing:
   3.111 -
   3.112 -    3. If a package being installed or updated-to REQUIRES a property
   3.113 -       that is not provided by any installed or to-be-installed
   3.114 -       package, we need to find an installable package that provides
   3.115 -       that property. If we find one, install/update it. If not, it's
   3.116 -       an error (UNSATISFIABLE). (If we find an upstream package
   3.117 -       providing the property that corresponds to a system package
   3.118 -       that's being removed, then it's a CONTRADICTION.)
   3.119 -
   3.120 -    4. If an already-installed package REQUIRES a property which is
   3.121 -       only provided by a package that is being removed, then that
   3.122 -       package needs to be removed as well.
   3.123 -
   3.124 -    5. If an already-installed package REQUIRES a property which is
   3.125 -       only provided by a package that is being upgraded or obsoleted
   3.126 -       (to a new package which does not provide that property), then:
   3.127 -
   3.128 -	- if there is an update for the installed package, then update
   3.129 -          the installed package
   3.130 -
   3.131 -	- else if there is another installable package that provides
   3.132 -          the required property, then install that.
   3.133 -
   3.134 -	- else it's an error (UNSATISFIABLE?)
   3.135 -
   3.136 -    CONFLICTS processing
   3.137 -
   3.138 -    6. If a package being installed or updated-to CONFLICTS with a
   3.139 -       property provided by an installed package:
   3.140 -
   3.141 -	- if there is an update for the installed package, which the
   3.142 -          new package does not conflict with, then update the
   3.143 -          installed package.
   3.144 -
   3.145 -	- else it's an error (NEW_CONFLICT)
   3.146 -
   3.147 -    7. If an already-installed package CONFLICTS with a property
   3.148 -       provided by a to-be-installed package:
   3.149 -
   3.150 -	- if there is an update for the installed package, which does
   3.151 -          not conflict with the new package, then update the installed
   3.152 -          package.
   3.153 -
   3.154 -	- else it's an error (NEW_CONFLICT)
   3.155 -
   3.156 -    8. If a package being installed or updated-to CONFLICTS with a
   3.157 -       property provided by a to-be-installed package, then it's an
   3.158 -       error (CONTRADICTION).
   3.159 -
   3.160 -    OBSOLETES processing. NOTE: OBSOLETES are only matched against
   3.161 -    package names, not against arbitrary provided properties
   3.162 -
   3.163 -    9. If a package being installed or updated-to OBSOLETES an
   3.164 -       installed package, then obsolete that package. (ie, remove it,
   3.165 -       but treat it as updated for purposes of dangling REQUIRES).
   3.166 -
   3.167 -   10. If an already-installed package OBSOLETES a to-be-installed
   3.168 -       package, then it's an error. (ALREADY_OBSOLETE)
   3.169 -
   3.170 -   11. If a package being installed or updated-to OBSOLETES another
   3.171 -       package being installed or updated-to, then it's an error
   3.172 -       (CONTRADICTION).
   3.173 -
   3.174 -
   3.175 -
   3.176 -THE DEPSOLVER
   3.177 --------------
   3.178 -
   3.179 -We start with two razor_sets, system and upstream, and a list of
   3.180 -requested installations and removals.
   3.181 -
   3.182 -    FIXME: what about multiple upstream repos? Having to deal with
   3.183 -    arbitrary numbers of razor_sets is possible, but will probably be
   3.184 -    messy... It might be easier to either store all upstream repo data
   3.185 -    in a single .repo file, or else merge all upstream .repo files
   3.186 -    together into a single razor_set at startup. (Or some combination
   3.187 -    of those.)
   3.188 -
   3.189 -We create a bit array of the packages in each set, indicating which
   3.190 -ones are installed; the system bitarray starts out all 1s, and the
   3.191 -upstream bitarray all 0s. Each bit is only allowed to change state
   3.192 -once during the transaction; an installed package can be removed, or
   3.193 -an uninstalled package installed, but trying to reinstall a removed
   3.194 -package, or uninstall a newly-installed package is an error. This
   3.195 -means the packages break down into four categories:
   3.196 -
   3.197 -    - installed       (1 bit in the system bit array)
   3.198 -    - to-be-removed   (0 bit in the system bit array)
   3.199 -    - to-be-installed (1 bit in the upstream bit array)
   3.200 -    - installable     (0 bit in the upstream bit array)
   3.201 -
   3.202 -
   3.203 -Depsolver algorithm:
   3.204 -
   3.205 -    - Create new razor_transaction_packages ("rtp"s) for each
   3.206 -      requested install or remove. These will be "unresolved", because
   3.207 -      we haven't yet found the razor_packages that correspond to them.
   3.208 -
   3.209 -    - while there are new rtps:
   3.210 -
   3.211 -	- sort the new rtps
   3.212 -
   3.213 -	- Walk the system property list, upstream property list, and
   3.214 -          new rtp list in parallel, and:
   3.215 -
   3.216 -	    - For each uninstalled PROVIDES:
   3.217 -
   3.218 -		- If the property is a valid package name (that is,
   3.219 -                  either it's a package providing its own name, or it
   3.220 -                  has a matching OBSOLETES), and it matches the name
   3.221 -                  of a new rtp of type INSTALL or FORCED_UPDATE with
   3.222 -                  an unresolved new_package:
   3.223 -
   3.224 -		    - If the upstream package has the same version as
   3.225 -		      the system package, we have an UP_TO_DATE error
   3.226 -		      (FIXME: not quite right. This doesn't deal with
   3.227 -		      the case where we try to update an application
   3.228 -		      because of a library update, and it turns out
   3.229 -		      there's no new version of the application, but
   3.230 -		      there IS a compat package containing the old
   3.231 -		      version of the library.)
   3.232 -
   3.233 -		    - Otherwise, set the rtp's new_package to point to
   3.234 -		      the package providing this property and set the
   3.235 -		      appropriate bit in the upstream bit array.
   3.236 -
   3.237 -	    - For each to-be-installed non-file REQUIRES:
   3.238 -
   3.239 -		- See if there's an installed or to-be-installed
   3.240 -		  package that PROVIDES that property.
   3.241 -
   3.242 -		- If not, see if there's an installable package that
   3.243 -		  PROVIDES that property, and create a new INSTALL rtp
   3.244 -		  for it if so.
   3.245 -
   3.246 -		- If not, see if there's a to-be-removed package that
   3.247 -		  PROVIDES that property. (If we find such a package,
   3.248 -		  we have a CONTRADICTION error.)
   3.249 -
   3.250 -		- If none of the above, then we have an UNSATISFIABLE
   3.251 -                  error
   3.252 -
   3.253 -	    - For each to-be-installed file REQUIRES:
   3.254 -
   3.255 -		- (We create fake file PROVIDES to match file REQUIRES
   3.256 -                  when importing/merging razor sets, so if there is
   3.257 -                  already another installed package that REQUIRES this
   3.258 -                  file, there will be a PROVIDES listed for it as well.)
   3.259 -
   3.260 -		- See if there's an installed package that PROVIDES
   3.261 -                  that file.
   3.262 -
   3.263 -		- If not, do a binary search of the system file tree
   3.264 -                  looking to see if some installed package provides
   3.265 -                  that file but does not have a PROVIDES for it.
   3.266 -
   3.267 -		- If not, see if there's an installable package that
   3.268 -		  PROVIDES that property, and create a new INSTALL rtp
   3.269 -		  for it if so.
   3.270 -
   3.271 -		- (If we actually work with multiple upstream
   3.272 -                  razor_sets, then we will need to search the upstream
   3.273 -                  file trees at this point, because it's possible that
   3.274 -                  a package in one upstream repo would require a file
   3.275 -                  in another upstream repo. But if we merge the
   3.276 -                  multiple upstream repos into a single razor_set at
   3.277 -                  some point, then we would not need to do that,
   3.278 -                  because it would be guaranteed that we would have
   3.279 -                  already created a fake PROVIDES if any package
   3.280 -                  provides the file.)
   3.281 -
   3.282 -		- If no installed or installable package provides the
   3.283 -		  file, see if there's a to-be-removed package that
   3.284 -		  provides the file. (If we find such a package, we
   3.285 -		  have a CONTRADICTION error.)
   3.286 -
   3.287 -		- If none of the above, then we have an UNSATISFIABLE
   3.288 -                  error
   3.289 -
   3.290 -	    - For each to-be-installed PROVIDES:
   3.291 -
   3.292 -		- Check if the new PROVIDES conflicts with an
   3.293 -		  installed CONFLICTS. If so, create a new
   3.294 -		  FORCED_UPDATE rtp for the installed package, so we
   3.295 -		  can try to upgrade it to a non-conflicting version.
   3.296 -		  (If we can't, we'll have an OLD_CONFLICT error.)
   3.297 -
   3.298 -		- Check if the new PROVIDES conflicts with an
   3.299 -                  installed OBSOLETES *and* the PROVIDES property
   3.300 -                  corresponds to the name of its package. (That is,
   3.301 -                  OBSOLETES are only matched against package names,
   3.302 -                  not arbitrary provided properties.) If so, we have
   3.303 -                  an ALREADY_OBSOLETE error.
   3.304 -
   3.305 -		- Check if the new PROVIDES conflicts with a
   3.306 -		  to-be-installed CONFLICTS. If so, we have a
   3.307 -		  CONTRADICTION error.
   3.308 -
   3.309 -	    - For each to-be-installed CONFLICTS:
   3.310 -
   3.311 -		- Basically the reverse of the previous case: check if
   3.312 -		  the new CONFLICTS conflicts with an installed
   3.313 -		  PROVIDES. If so, create a new FORCED_UPDATE rtp for
   3.314 -		  the installed package, so we can try to upgrade it
   3.315 -		  to a non-conflicting version. (If we can't, we'll
   3.316 -		  have an NEW_CONFLICT error.)
   3.317 -
   3.318 -		- Check if the new CONFLICTS conflicts with a
   3.319 -		  to-be-installed PROVIDES. If so, we have a
   3.320 -		  CONTRADICTION error.
   3.321 -
   3.322 -	    - For each to-be-installed OBSOLETES:
   3.323 -
   3.324 -		- Check if there's an installed package that PROVIDES
   3.325 -		  that property. If so, create an OBSOLETED rtp for
   3.326 -		  the installed package.
   3.327 -
   3.328 -		- If not, check if there's a to-be-installed package
   3.329 -		  that PROVIDES that property. If so, we have a
   3.330 -		  CONTRADICTION error.
   3.331 -
   3.332 -
   3.333 -	    - For each installed PROVIDES:
   3.334 -
   3.335 -		- If the property is a valid package name (that is,
   3.336 -                  it's a package providing its own name), and it
   3.337 -                  matches the name of a new rtp with an unresolved
   3.338 -                  old_package, then set the rtp's old_package to point
   3.339 -                  to the package providing this property and clear the
   3.340 -                  appropriate bit in the system bit array.
   3.341 -
   3.342 -	    - For each to-be-removed PROVIDES:
   3.343 -
   3.344 -		- If there's also an identical to-be-installed
   3.345 -		  PROVIDES, we're ok and can skip this
   3.346 -
   3.347 -		- Otherwise, for each installed REQUIRES of this
   3.348 -                  property:
   3.349 -
   3.350 -		    - Look for some other installed or to-be-installed
   3.351 -		      property that satisfies the REQUIRES.
   3.352 -
   3.353 -		    - If there isn't one, then for each installed
   3.354 -		      package in this REQUIRES's package list:
   3.355 -
   3.356 -			- If the PROVIDES was lost because the old
   3.357 -			  package was REMOVEd (not FORCED_UPDATE or
   3.358 -			  OBSOLETED), then create a new REMOVE rtp for
   3.359 -			  this package.
   3.360 -
   3.361 -			- Otherwise, create a new FORCED_UPDATE rtp
   3.362 -                          for this package.
   3.363 -
   3.364 -		- (We don't need to look at to-be-installed REQUIRES
   3.365 -		  of this property, because if there are any, they
   3.366 -		  will cause a CONTRADICTION error when we try to
   3.367 -		  re-satisfy them the next time through.)
     4.1 --- a/Makefile	Sun Jun 15 23:15:59 2008 -0400
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,27 +0,0 @@
     4.4 -CFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes -g
     4.5 -LDLIBS = librazor.a -lexpat -lz -g -lrpm -lcurl
     4.6 -
     4.7 -all : razor test-driver rpm-razor
     4.8 -
     4.9 -librazor_objs = razor.o yum.o rpm.o types.o util.o razor-root.o
    4.10 -librazor.a : $(librazor_objs)
    4.11 -	ar cr $@ $(librazor_objs)
    4.12 -
    4.13 -razor : main.o librazor.a
    4.14 -
    4.15 -*.o : razor.h razor-internal.h
    4.16 -razor.o : types.h
    4.17 -
    4.18 -test-driver : librazor.a test-driver.o
    4.19 -
    4.20 -rpm-razor : librazor.a rpm-razor.o
    4.21 -
    4.22 -test : test-driver
    4.23 -	./test-driver test.xml
    4.24 -
    4.25 -reset : ./razor
    4.26 -	sudo rm -rf install
    4.27 -	./razor init
    4.28 -
    4.29 -clean :
    4.30 -	rm -f *.o razor librazor.a
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/Makefile.am	Mon Jun 16 15:40:30 2008 -0400
     5.3 @@ -0,0 +1,38 @@
     5.4 +## Process this file with automake to produce Makefile.in
     5.5 +
     5.6 +SUBDIRS = data docs librazor src po
     5.7 +
     5.8 +# Creating ChangeLog from git log (taken from cairo/Makefile.am):
     5.9 +ChangeLog: $(srcdir)/ChangeLog
    5.10 +
    5.11 +$(srcdir)/ChangeLog:
    5.12 +	@if test -d "$(srcdir)/.git"; then \
    5.13 +	  (cd "$(srcdir)" && \
    5.14 +	  ./missing --run git-log --stat) | fmt --split-only > $@.tmp \
    5.15 +	  && mv -f $@.tmp $@ \
    5.16 +	  || ($(RM) $@.tmp; \
    5.17 +	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
    5.18 +	      (test -f $@ || echo git-log is required to generate this file >> $@)); \
    5.19 +	else \
    5.20 +	  test -f $@ || \
    5.21 +	  (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
    5.22 +	  echo A git checkout and git-log is required to generate this file >> $@); \
    5.23 +	fi
    5.24 +
    5.25 +.PHONY: ChangeLog $(srcdir)/ChangeLog
    5.26 +
    5.27 +EXTRA_DIST = 			\
    5.28 +	TODO	 		\
    5.29 +	ChangeLog 		\
    5.30 +	intltool-extract.in 	\
    5.31 +	intltool-merge.in 	\
    5.32 +	intltool-update.in
    5.33 +
    5.34 +DISTCLEANFILES = \
    5.35 +	intltool-extract	\
    5.36 +	intltool-merge		\
    5.37 +	intltool-update
    5.38 +
    5.39 +clean-local :
    5.40 +	rm -f *~
    5.41 +
     6.1 --- a/REPO.txt	Sun Jun 15 23:15:59 2008 -0400
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,172 +0,0 @@
     6.4 -The repo file format / razor_set data structure
     6.5 ------------------------------------------------
     6.6 -
     6.7 -The repo starts with a header, containing some number of sections,
     6.8 -terminated by a section with type 0:
     6.9 -
    6.10 -	struct razor_set_header {
    6.11 -		uint32_t magic;
    6.12 -		uint32_t version;
    6.13 -		struct razor_set_section sections[0];
    6.14 -	};
    6.15 -
    6.16 -	struct razor_set_section {
    6.17 -		uint32_t type;
    6.18 -		uint32_t offset;
    6.19 -		uint32_t size;
    6.20 -	};
    6.21 -
    6.22 -razor_set_open() mmaps the repo file, and creates a struct razor_set:
    6.23 -
    6.24 -	struct razor_set {
    6.25 -		struct array string_pool;
    6.26 -	 	struct array packages;
    6.27 -	 	struct array properties;
    6.28 -	 	struct array files;
    6.29 -		struct array package_pool;
    6.30 -	 	struct array property_pool;
    6.31 -	 	struct array file_pool;
    6.32 -		struct razor_set_header *header;
    6.33 -	};
    6.34 -
    6.35 -by finding the sections with those IDs and creating "struct array"s
    6.36 -pointing to the right places in the mmapped data. (This is the only
    6.37 -processing needed when reading in the file; everything else is used
    6.38 -exactly as-is.)
    6.39 -
    6.40 -
    6.41 -The sections
    6.42 -------------
    6.43 -
    6.44 -RAZOR_STRING_POOL
    6.45 -
    6.46 -	Stores one copy of each string that appears in the repo. (At
    6.47 -	the moment, this is: package names, package versions, property
    6.48 -	names, property versions, and (basenames of) filenames.) The
    6.49 -	strings are arbitrarily-sized, 0-terminated, and not in any
    6.50 -	particular order (although the empty string always ends up
    6.51 -	being at offset 0).
    6.52 -
    6.53 -RAZOR_PACKAGES
    6.54 -
    6.55 -	Array of struct razor_package; one for each package in the
    6.56 -	set, sorted by name.
    6.57 -
    6.58 -RAZOR_PROPERTIES
    6.59 -
    6.60 -	Array of struct razor_property; one for each unique property
    6.61 -	in the set, sorted by type, then name, then relation type (eg,
    6.62 -	"<" or ">="), then version. (Properties with no version have
    6.63 -	relation type RAZOR_VERSION_EQUAL, and version "".)
    6.64 -
    6.65 -RAZOR_FILES
    6.66 -
    6.67 -	Array of struct razor_entry; one for each file owned by any
    6.68 -	package in the set. The current sort order (which is subject
    6.69 -	to change) is breadth-first, sorted by basename. So eg: /, /bin,
    6.70 -	/dev, /etc, /bin/false, /bin/true, /dev/null, /etc/passwd.
    6.71 -
    6.72 -RAZOR_PACKAGE_POOL
    6.73 -
    6.74 -	Array of struct list, with each list item containing the index
    6.75 -	of a struct razor_package in the packages section. See the
    6.76 -	discussion of lists below.
    6.77 -
    6.78 -RAZOR_PROPERTY_POOL
    6.79 -
    6.80 -	Array of struct list, with each list item containing the index
    6.81 -	of a struct razor_property in the properties section. See the
    6.82 -	discussion of lists below.
    6.83 -
    6.84 -RAZOR_FILE_POOL
    6.85 -
    6.86 -	Array of struct list, with each list item containing the index
    6.87 -	of a struct razor_entry in the files section. See the
    6.88 -	discussion of lists below.
    6.89 -
    6.90 -
    6.91 -Data types
    6.92 -----------
    6.93 -Note that the exact layout of bits involves some historical accidents.
    6.94 -(Particularly the fact that the "name" field in most structs loses its
    6.95 -high bits to a flags field.)
    6.96 -
    6.97 -struct list_head
    6.98 -	uint list_ptr : 24;
    6.99 -	uint flags    : 8;
   6.100 -
   6.101 -struct list
   6.102 -	uint data  : 24;
   6.103 -	uint flags : 8;
   6.104 -
   6.105 -	Used to store lists of package, property, or file IDs. "struct
   6.106 -	list_head" stores the head of the list, which points to one or
   6.107 -	more "struct list"s in the appropriate "pool" section.
   6.108 -	("struct list" should probably be called "struct list_item".)
   6.109 -
   6.110 -	"list_first(&head, &pool)" returns a "struct list *" pointing
   6.111 -	to the first element of the list (or NULL for an empty list),
   6.112 -	and "list_next(list)" will return successive elements, until
   6.113 -	NULL is returned. Each "list->data" contains the index of a
   6.114 -	package, property, or file in the corresponding section of the
   6.115 -	set.
   6.116 -
   6.117 -	Peeking underneath the abstraction, a list_head's "flags" is
   6.118 -	0xff if the list is empty, 0x80 if it contains a single
   6.119 -	element, or 0x00 if it contains more than one element. In the
   6.120 -	single-element case, that element is actually stored in the
   6.121 -	list_head directly rather than being stored in a pool (and so
   6.122 -	list_first() just casts the list_head* to a list* and returns
   6.123 -	it). For multi-element lists, list_ptr is the index in the
   6.124 -	pool of the first element of this list; the list continues
   6.125 -	through successive elements of the pool until one with
   6.126 -	non-zero flags is reached, indicating the end of the list.
   6.127 -
   6.128 -struct razor_package
   6.129 -	uint name    : 24;
   6.130 -	uint flags   : 8;
   6.131 -	uint version : 32;
   6.132 -	struct list_head properties;
   6.133 -	struct list_head files;
   6.134 -
   6.135 -	name and version are indexes into string_pool. properties is a
   6.136 -	list of all of the package's properties, and files is a list
   6.137 -	of its files. flags is currently only used during razor_set
   6.138 -	merging, to keep track of which set a package came from.
   6.139 -
   6.140 -struct razor_property
   6.141 -	uint name     : 24;
   6.142 -	uint flags    : 6;
   6.143 -	uint type     : 2;
   6.144 -	uint relation : 32;
   6.145 -	uint version  : 32;
   6.146 -	struct list_head packages;
   6.147 -
   6.148 -	name and version are indexes into string_pool. type is an enum
   6.149 -	razor_property_type (eg, RAZOR_PROPERTY_REQUIRES), and
   6.150 -	relation is an enum razor_version_relation (eg,
   6.151 -	RAZOR_VERSION_GREATER_OR_EQUAL). packages is a list of the
   6.152 -	packages that have this property. flags is currently unused.
   6.153 -
   6.154 -struct razor_entry
   6.155 -	uint name  : 24;
   6.156 -	uint flags : 8;
   6.157 -	uint start : 32;
   6.158 -	struct list_head packages;
   6.159 -
   6.160 -	name is an index into string_pool, giving the basename of the
   6.161 -	file. start is either 0, or an index pointing to another
   6.162 -	razor_entry that is the first child of this entry (for a
   6.163 -	non-empty directory). (Entry 0 is always the root of the tree,
   6.164 -	so no entry could have entry 0 as a child.) flags is 0x80
   6.165 -	(RAZOR_ENTRY_LAST) if an entry is the last entry in its
   6.166 -	directory. Otherwise it is 0.
   6.167 -
   6.168 -	Note that given a pointer to a struct_razor_entry (eg, from a
   6.169 -	package's "files" list), there is no way to reconstruct its
   6.170 -	full name without walking the entire files array up to that
   6.171 -	point. Because of this and other problems (fix_file_map()), it
   6.172 -	seems like razor_entry should be modified to include a pointer
   6.173 -	to its parent. (Storing full paths instead of just basenames
   6.174 -	would also fix this problem, but that would use much more
   6.175 -	memory.)
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/autogen.sh	Mon Jun 16 15:40:30 2008 -0400
     7.3 @@ -0,0 +1,95 @@
     7.4 +#!/bin/sh
     7.5 +# Run this to generate all the initial makefiles, etc.
     7.6 +
     7.7 +srcdir=`dirname $0`
     7.8 +test -z "$srcdir" && srcdir=.
     7.9 +
    7.10 +DIE=0
    7.11 +
    7.12 +(test -f $srcdir/configure.ac) || {
    7.13 +    echo -n "**Error**: Directory $srcdir does not look like the"
    7.14 +    echo " top-level package directory"
    7.15 +    exit 1
    7.16 +}
    7.17 +
    7.18 +(autoconf --version) < /dev/null > /dev/null 2>&1 || {
    7.19 +  echo
    7.20 +  echo "**Error**: You must have autoconf installed."
    7.21 +  echo "Download the appropriate package for your distribution,"
    7.22 +  echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
    7.23 +  DIE=1
    7.24 +}
    7.25 +
    7.26 +(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
    7.27 +  (libtool --version) < /dev/null > /dev/null 2>&1 || {
    7.28 +    echo
    7.29 +    echo "**Error**: You must have libtool installed."
    7.30 +    echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
    7.31 +    DIE=1
    7.32 +  }
    7.33 +}
    7.34 +
    7.35 +(automake --version) < /dev/null > /dev/null 2>&1 || {
    7.36 +  echo
    7.37 +  echo "**Error**: You must have automake installed."
    7.38 +  echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
    7.39 +  DIE=1
    7.40 +  NO_AUTOMAKE=yes
    7.41 +}
    7.42 +
    7.43 +
    7.44 +# if no automake, don't bother testing for aclocal
    7.45 +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
    7.46 +  echo
    7.47 +  echo "**Error**: Missing aclocal.  The version of automake"
    7.48 +  echo "installed doesn't appear recent enough."
    7.49 +  echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
    7.50 +  DIE=1
    7.51 +}
    7.52 +
    7.53 +if test "$DIE" -eq 1; then
    7.54 +  exit 1
    7.55 +fi
    7.56 +
    7.57 +if test -z "$*"; then
    7.58 +  echo "**Warning**: I am going to run configure with no arguments."
    7.59 +  echo "If you wish to pass any to it, please specify them on the"
    7.60 +  echo $0 " command line."
    7.61 +  echo
    7.62 +fi
    7.63 +
    7.64 +case $CC in
    7.65 +xlc )
    7.66 +  am_opt=--include-deps;;
    7.67 +esac
    7.68 +
    7.69 +      aclocalinclude="$ACLOCAL_FLAGS"
    7.70 +
    7.71 +      if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then
    7.72 +	if test -z "$NO_LIBTOOLIZE" ; then 
    7.73 +	  echo "Running libtoolize..."
    7.74 +	  libtoolize --force --copy
    7.75 +	fi
    7.76 +      fi
    7.77 +      echo "Running aclocal $aclocalinclude ..."
    7.78 +      aclocal $aclocalinclude
    7.79 +      if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then
    7.80 +	echo "Running autoheader..."
    7.81 +	autoheader
    7.82 +      fi
    7.83 +      echo "Running automake --gnu -Wno-portability $am_opt ..."
    7.84 +      automake --add-missing --gnu -Wno-portability $am_opt
    7.85 +      echo "Running autoconf ..."
    7.86 +      autoconf
    7.87 +
    7.88 +intltoolize --copy --force --automake                  || exit 1
    7.89 +
    7.90 +conf_flags="--enable-maintainer-mode"
    7.91 +
    7.92 +if test x$NOCONFIGURE = x; then
    7.93 +  echo "Running $srcdir/configure $conf_flags $@ ..."
    7.94 +  $srcdir/configure $conf_flags "$@" \
    7.95 +  && echo "Now type make to compile." || exit 1
    7.96 +else
    7.97 +  echo "Skipping configure process."
    7.98 +fi
     8.1 --- a/bash-completion.sh	Sun Jun 15 23:15:59 2008 -0400
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,47 +0,0 @@
     8.4 -__razor_commands () {
     8.5 -    local IFS=$'\n'
     8.6 -    COMPREPLY=($(IFS=: compgen -S' ' -W "list-requires:list-provides:list-files:list-file-packages:list-package-files:what-requires:what-provides:import-yum:import-rpmdb:validate:update:diff:install:init:download" -- $1))
     8.7 -}
     8.8 -
     8.9 -__razor_packages () {
    8.10 -    local IFS=$'\n'
    8.11 -
    8.12 -    COMPREPLY=($(./razor list --only-names "$1*" | while read p; do echo "$p "; done))
    8.13 -}
    8.14 -
    8.15 -__razor_upstream_packages () {
    8.16 -    local IFS=$'\n'
    8.17 -
    8.18 -    COMPREPLY=($(RAZOR_REPO=rawhide.repo ./razor list --only-names "$1*" | while read p; do echo "$p "; done))
    8.19 -}
    8.20 -
    8.21 -__razor_files() {
    8.22 -    COMPREPLY=($(./razor list-files "$1*"))
    8.23 -}
    8.24 -
    8.25 -__razor_requires() {
    8.26 -    COMPREPLY=($(compgen -W "$(./razor list-requires)" -- $1))
    8.27 -}
    8.28 -
    8.29 -__razor_provides() {
    8.30 -    COMPREPLY=($(compgen -W "$(./razor list-provides)" -- $1))
    8.31 -}
    8.32 -
    8.33 -__razor() {
    8.34 -    local cur="${COMP_WORDS[COMP_CWORD]}"
    8.35 -
    8.36 -    if [ $COMP_CWORD = 1 ]; then
    8.37 -	__razor_commands $cur
    8.38 -    else
    8.39 -	case "${COMP_WORDS[1]}" in
    8.40 -	    list-requires|list-provides|list-package-files)
    8.41 -		__razor_packages $cur ;;
    8.42 -	    list-files|list-file-packages) __razor_files $cur ;;
    8.43 -	    what-requires) __razor_requires $cur ;;
    8.44 -	    what-provides) __razor_provides $cur ;;
    8.45 -	    install|download) __razor_upstream_packages $cur ;;
    8.46 -	esac
    8.47 -    fi
    8.48 -}
    8.49 -
    8.50 -complete -o nospace -F __razor razor
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/configure.ac	Mon Jun 16 15:40:30 2008 -0400
     9.3 @@ -0,0 +1,201 @@
     9.4 +dnl Process this file with autoconf to produce a configure script.
     9.5 +
     9.6 +AC_PREREQ(2.59c)
     9.7 +AC_INIT(razor, 0.8, krh@redhat.com)
     9.8 +AM_INIT_AUTOMAKE(razor, 0.1)
     9.9 +AM_CONFIG_HEADER(config.h)
    9.10 +AM_MAINTAINER_MODE
    9.11 +
    9.12 +# libtool versioning - this applies to all libraries in this package
    9.13 +#
    9.14 +# See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
    9.15 +#
    9.16 +LT_CURRENT=1
    9.17 +LT_REVISION=0
    9.18 +LT_AGE=0
    9.19 +AC_SUBST(LT_CURRENT)
    9.20 +AC_SUBST(LT_REVISION)
    9.21 +AC_SUBST(LT_AGE)
    9.22 +
    9.23 +AC_ISC_POSIX
    9.24 +AC_PROG_CC
    9.25 +AM_PROG_CC_STDC
    9.26 +AC_HEADER_STDC
    9.27 +AM_PROG_LIBTOOL
    9.28 +AC_PROG_MAKE_SET
    9.29 +AC_PROG_LN_S
    9.30 +AC_SYS_LARGEFILE
    9.31 +AM_PROG_CC_C_O
    9.32 +
    9.33 +# Taken from dbus
    9.34 +AC_ARG_ENABLE(ansi,             [  --enable-ansi           enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
    9.35 +AC_ARG_ENABLE(verbose-mode,     [  --enable-verbose-mode   support verbose debug mode],enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
    9.36 +
    9.37 +if test "${enable_verbose_mode}" != no; then
    9.38 +    # To get -rdynamic you pass -export-dynamic to libtool.
    9.39 +    AC_DEFINE(BUILT_R_DYNAMIC,1,[whether -export-dynamic was passed to libtool])
    9.40 +    R_DYNAMIC_LDFLAG=-export-dynamic
    9.41 +else
    9.42 +    R_DYNAMIC_LDFLAG=
    9.43 +fi
    9.44 +AC_SUBST(R_DYNAMIC_LDFLAG)
    9.45 +
    9.46 +#### gcc warning flags
    9.47 +
    9.48 +if test "x$GCC" = "xyes"; then
    9.49 +  changequote(,)dnl
    9.50 +  case " $CFLAGS " in
    9.51 +  *[\ \	]-Wall[\ \	]*) ;;
    9.52 +  *) CFLAGS="$CFLAGS -Wall" ;;
    9.53 +  esac
    9.54 +
    9.55 +  case " $CFLAGS " in
    9.56 +  *[\ \	]-Wchar-subscripts[\ \	]*) ;;
    9.57 +  *) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
    9.58 +  esac
    9.59 +
    9.60 +  case " $CFLAGS " in
    9.61 +  *[\ \	]-Wmissing-declarations[\ \	]*) ;;
    9.62 +  *) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
    9.63 +  esac
    9.64 +
    9.65 +  case " $CFLAGS " in
    9.66 +  *[\ \	]-Wnested-externs[\ \	]*) ;;
    9.67 +  *) CFLAGS="$CFLAGS -Wnested-externs" ;;
    9.68 +  esac
    9.69 +
    9.70 +  case " $CFLAGS " in
    9.71 +  *[\ \	]-Wcast-align[\ \	]*) ;;
    9.72 +  *) CFLAGS="$CFLAGS -Wcast-align" ;;
    9.73 +  esac
    9.74 +
    9.75 +  case " $CFLAGS " in
    9.76 +  *[\ \	]-Wformat[\ \	]*) ;;
    9.77 +  *) CFLAGS="$CFLAGS -Wformat" ;;
    9.78 +  esac
    9.79 +
    9.80 +  case " $CFLAGS " in
    9.81 +  *[\ \	]-Wformat-security[\ \	]*) ;;
    9.82 +  *) CFLAGS="$CFLAGS -Wformat-security" ;;
    9.83 +  esac
    9.84 +
    9.85 +  if test "x$enable_ansi" = "xyes"; then
    9.86 +    case " $CFLAGS " in
    9.87 +    *[\ \	]-ansi[\ \	]*) ;;
    9.88 +    *) CFLAGS="$CFLAGS -ansi" ;;
    9.89 +    esac
    9.90 +
    9.91 +    case " $CFLAGS " in
    9.92 +    *[\ \	]-D_POSIX_C_SOURCE*) ;;
    9.93 +    *) CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199309L" ;;
    9.94 +    esac
    9.95 +
    9.96 +    case " $CFLAGS " in
    9.97 +    *[\ \	]-D_BSD_SOURCE[\ \	]*) ;;
    9.98 +    *) CFLAGS="$CFLAGS -D_BSD_SOURCE" ;;
    9.99 +    esac
   9.100 +
   9.101 +    case " $CFLAGS " in
   9.102 +    *[\ \	]-pedantic[\ \	]*) ;;
   9.103 +    *) CFLAGS="$CFLAGS -pedantic" ;;
   9.104 +    esac
   9.105 +  fi
   9.106 +  changequote([,])dnl
   9.107 +fi
   9.108 +
   9.109 +PKG_CHECK_MODULES(CURL, [libcurl])
   9.110 +AC_SUBST(CURL_CFLAGS)
   9.111 +AC_SUBST(CURL_LIBS)
   9.112 +
   9.113 +ZLIB_LIBS=""
   9.114 +AC_ARG_WITH(zlib, [  --with-zlib=<dir>       Use zlib from here],
   9.115 +                      [
   9.116 +                      zlib=$withval
   9.117 +                      CPPFLAGS="$CPPFLAGS -I$withval/include"
   9.118 +                      LDFLAGS="$LDFLAGS -L$withval/lib"
   9.119 +                      ]
   9.120 +                      )
   9.121 +AC_CHECK_HEADERS(zlib.h, [AC_DEFINE(HAVE_ZLIB_H)],
   9.122 +                 [AC_MSG_ERROR([Can't find zlib.h. Please install zlib.])])
   9.123 +AC_CHECK_LIB(z, inflate, [ZLIB_LIBS="-lz"],
   9.124 +	     [AC_MSG_ERROR([Can't find zlib library. Please install zlib.])])
   9.125 +AC_SUBST(ZLIB_LIBS)
   9.126 +
   9.127 +EXPAT_LIB=""
   9.128 +AC_ARG_WITH(expat, [  --with-expat=<dir>      Use expat from here],
   9.129 +                      [
   9.130 +                      expat=$withval
   9.131 +                      CPPFLAGS="$CPPFLAGS -I$withval/include"
   9.132 +                      LDFLAGS="$LDFLAGS -L$withval/lib"
   9.133 +                      ]
   9.134 +                      )
   9.135 +AC_CHECK_HEADERS(expat.h, [AC_DEFINE(HAVE_EXPAT_H)], 
   9.136 +		 [AC_MSG_ERROR([Can't find expat.h. Please install expat.])])
   9.137 +AC_CHECK_LIB(expat, XML_ParserCreate, [EXPAT_LIBS="-lexpat"],
   9.138 +	     [AC_MSG_ERROR([Can't find expat library. Please install expat.])])
   9.139 +AC_SUBST(EXPAT_LIBS)
   9.140 +
   9.141 +RPM_LIB=""
   9.142 +AC_ARG_WITH(rpm, [  --with-rpm=<dir>      Use rpm from here],
   9.143 +                      [
   9.144 +                      rpm=$withval
   9.145 +                      CPPFLAGS="$CPPFLAGS -I$withval/include"
   9.146 +                      LDFLAGS="$LDFLAGS -L$withval/lib"
   9.147 +                      ]
   9.148 +                      )
   9.149 +AC_CHECK_HEADERS(rpm/rpmlib.h, [], 
   9.150 +		 [AC_MSG_ERROR([Can't find rpm/rpmlib.h. Please install rpm-devel.])])
   9.151 +AC_CHECK_LIB(rpm,rpmdbOpen,[RPM_LIBS="-lrpm"],
   9.152 +	     [AC_MSG_ERROR([Can't find rpm library. Please install rpm-devel.])])
   9.153 +AC_SUBST(RPM_LIBS)
   9.154 +
   9.155 +if test "x$GCC" = "xyes"; then
   9.156 +  LDFLAGS="-Wl,--as-needed $LDFLAGS"
   9.157 +fi
   9.158 +
   9.159 +# *****************************
   9.160 +# Make available to Makefile.am
   9.161 +# *****************************
   9.162 +AC_SUBST(SYSCONFDIR, $sysconfdir)
   9.163 +
   9.164 +# ********************
   9.165 +# Internationalisation
   9.166 +# ********************
   9.167 +
   9.168 +IT_PROG_INTLTOOL([0.36.0])
   9.169 +GETTEXT_PACKAGE=razor
   9.170 +AC_SUBST([GETTEXT_PACKAGE])
   9.171 +AM_GLIB_GNU_GETTEXT
   9.172 +AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[gettext domain])
   9.173 +
   9.174 +AC_OUTPUT([
   9.175 +Makefile
   9.176 +data/razor.pc
   9.177 +data/Makefile
   9.178 +librazor/Makefile
   9.179 +src/Makefile
   9.180 +docs/Makefile
   9.181 +po/Makefile.in
   9.182 +])
   9.183 +
   9.184 +dnl ==========================================================================
   9.185 +echo "
   9.186 +                  razor $VERSION
   9.187 +                =================
   9.188 +
   9.189 +        prefix:                     ${prefix}
   9.190 +        libdir:                     ${libdir}
   9.191 +        libexecdir:                 ${libexecdir}
   9.192 +        bindir:                     ${bindir}
   9.193 +        sbindir:                    ${sbindir}
   9.194 +        datadir:                    ${datadir}
   9.195 +        sysconfdir:                 ${sysconfdir}
   9.196 +        localstatedir:              ${localstatedir}
   9.197 +        docdir:                     ${docdir}
   9.198 +
   9.199 +        compiler:                   ${CC}
   9.200 +        cflags:                     ${CFLAGS}
   9.201 +        Maintainer mode:            ${USE_MAINTAINER_MODE}
   9.202 +        Building verbose mode:      ${enable_verbose_mode}
   9.203 +"
   9.204 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/data/.gitignore	Mon Jun 16 15:40:30 2008 -0400
    10.3 @@ -0,0 +1,2 @@
    10.4 +razor.pc
    10.5 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/data/Makefile.am	Mon Jun 16 15:40:30 2008 -0400
    11.3 @@ -0,0 +1,11 @@
    11.4 +## Process this file with automake to produce Makefile.in
    11.5 +
    11.6 +pkgconfigdir = $(libdir)/pkgconfig
    11.7 +pkgconfig_DATA = razor.pc
    11.8 +
    11.9 +bashcompletiondir = ${SYSCONFDIR}/bash_completion.d
   11.10 +dist_bashcompletion_DATA = bash-completion.sh
   11.11 +
   11.12 +clean-local :
   11.13 +	rm -f *~
   11.14 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/data/bash-completion.sh	Mon Jun 16 15:40:30 2008 -0400
    12.3 @@ -0,0 +1,47 @@
    12.4 +__razor_commands () {
    12.5 +    local IFS=$'\n'
    12.6 +    COMPREPLY=($(IFS=: compgen -S' ' -W "list-requires:list-provides:list-files:list-file-packages:list-package-files:what-requires:what-provides:import-yum:import-rpmdb:validate:update:diff:install:init:download" -- $1))
    12.7 +}
    12.8 +
    12.9 +__razor_packages () {
   12.10 +    local IFS=$'\n'
   12.11 +
   12.12 +    COMPREPLY=($(./razor list --only-names "$1*" | while read p; do echo "$p "; done))
   12.13 +}
   12.14 +
   12.15 +__razor_upstream_packages () {
   12.16 +    local IFS=$'\n'
   12.17 +
   12.18 +    COMPREPLY=($(RAZOR_REPO=rawhide.repo ./razor list --only-names "$1*" | while read p; do echo "$p "; done))
   12.19 +}
   12.20 +
   12.21 +__razor_files() {
   12.22 +    COMPREPLY=($(./razor list-files "$1*"))
   12.23 +}
   12.24 +
   12.25 +__razor_requires() {
   12.26 +    COMPREPLY=($(compgen -W "$(./razor list-requires)" -- $1))
   12.27 +}
   12.28 +
   12.29 +__razor_provides() {
   12.30 +    COMPREPLY=($(compgen -W "$(./razor list-provides)" -- $1))
   12.31 +}
   12.32 +
   12.33 +__razor() {
   12.34 +    local cur="${COMP_WORDS[COMP_CWORD]}"
   12.35 +
   12.36 +    if [ $COMP_CWORD = 1 ]; then
   12.37 +	__razor_commands $cur
   12.38 +    else
   12.39 +	case "${COMP_WORDS[1]}" in
   12.40 +	    list-requires|list-provides|list-package-files)
   12.41 +		__razor_packages $cur ;;
   12.42 +	    list-files|list-file-packages) __razor_files $cur ;;
   12.43 +	    what-requires) __razor_requires $cur ;;
   12.44 +	    what-provides) __razor_provides $cur ;;
   12.45 +	    install|download) __razor_upstream_packages $cur ;;
   12.46 +	esac
   12.47 +    fi
   12.48 +}
   12.49 +
   12.50 +complete -o nospace -F __razor razor
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/data/razor.pc.in	Mon Jun 16 15:40:30 2008 -0400
    13.3 @@ -0,0 +1,12 @@
    13.4 +prefix=@prefix@
    13.5 +exec_prefix=@exec_prefix@
    13.6 +libdir=@libdir@
    13.7 +includedir=@includedir@
    13.8 +
    13.9 +Name: razor
   13.10 +Description: library for depsolving, installing and removing packages
   13.11 +Version: @VERSION@
   13.12 +Requires: expat curl
   13.13 +Libs: -L${libdir} -lexpat -lz -lcurl
   13.14 +Cflags: -I${includedir}/razor
   13.15 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/docs/DEPSOLVE.txt	Mon Jun 16 15:40:30 2008 -0400
    14.3 @@ -0,0 +1,364 @@
    14.4 +YUM vs RAZOR
    14.5 +------------
    14.6 +
    14.7 +At a very high level, yum's depsolver does something roughly
    14.8 +equivalent to:
    14.9 +
   14.10 +    - For each package being installed or removed
   14.11 +
   14.12 +	- For each relevant property (provides, requires, conflicts,
   14.13 +          obsoletes):
   14.14 +
   14.15 +	    - Figure out what additional packages need to be added to
   14.16 +	      or removed from the system to satisfy this property
   14.17 +
   14.18 +which ends up being roughly O(N^2 * M) where N is the total number of
   14.19 +properties and M is the number of packages being acted on.
   14.20 +
   14.21 +(I just figured that out off the top of my head, and I'm not totally
   14.22 +familiar with the yum code, so it may be wrong.)
   14.23 +
   14.24 +Razor's depsolver is something like:
   14.25 +
   14.26 +    - do {
   14.27 +
   14.28 +	- For each property to be added to or removed from the system:
   14.29 +
   14.30 +	    - Figure out what packages need to be added to or removed
   14.31 +	      from the system to satisfy this property
   14.32 +
   14.33 +    - } until we stop adding/remove more packages
   14.34 +
   14.35 +with the key being that it's very easy to find the PROVIDES
   14.36 +corresponding to a REQUIRES and vice versa, because the property
   14.37 +arrays are sorted, and so all properties with the same "name" will be
   14.38 +adjacent to one another in the array, allowing many dependencies to be
   14.39 +satisified in essentially constant time. (Actually... we've been
   14.40 +calling it constant, but it's really O(log N) for heavily-depended-on
   14.41 +packages, because the more packages you have, the more variations on
   14.42 +"requires foo", "requires foo = 1.1", "requires foo > 1.0", etc you're
   14.43 +going to have to scan through.)
   14.44 +
   14.45 +Ideally though, each iteration of the inner loop body happens in
   14.46 +constant time, and thus the inner loop as a whole is O(N), and thus
   14.47 +the depsolver as a whole is O(N * M) (or at least, less than
   14.48 +O(N * M * log N).
   14.49 +
   14.50 +
   14.51 +FILE DEPENDENCIES
   14.52 +-----------------
   14.53 +
   14.54 +Whenever we add a package with a file REQUIRES to a razor_set, we also
   14.55 +add a PROVIDES for that file to the package or packages which provide
   14.56 +that file. This means that if we later add another package that
   14.57 +requires the same file (eg, /bin/sh or /usr/bin/perl), we can resolve
   14.58 +its file requirement exactly like we would resolve a property
   14.59 +requirement, in nearly constant time.
   14.60 +
   14.61 +When adding a *new* file requirement (ie, a requirement on a file that
   14.62 +no existing package depends on), we still have to scan through the
   14.63 +file tree, which is O(log N) in the number of files.
   14.64 +
   14.65 +(AFAICT, there's no reason yum couldn't do the same optimization.
   14.66 +Also, AFAICT, yum currently sticks property dependencies and file
   14.67 +dependencies into the same hash table, so that if any package in the
   14.68 +transaction has a file dependency, it causes *property* dependencies
   14.69 +to become slower to resolve as well...)
   14.70 +
   14.71 +
   14.72 +THE RULES
   14.73 +---------
   14.74 +
   14.75 +This is what we have figured out for transaction-solving rules;
   14.76 +neither yum nor rpm's algorithm seems to be explained in full
   14.77 +anywhere...
   14.78 +
   14.79 +    1. Every requested install in the initial package set must be
   14.80 +       satisfied as either a new install or an update:
   14.81 +
   14.82 +	- if the requested package name is the name of an upstream
   14.83 +          package:
   14.84 +
   14.85 +	    - if there is not a corresponding already-installed
   14.86 +              package, then install the upstream package
   14.87 +
   14.88 +	    - else if the upstream package is newer than the
   14.89 +              already-installed package, then update the package
   14.90 +
   14.91 +	    - else it's an error (UP_TO_DATE)
   14.92 +
   14.93 +	- else if the requested package name is the name of an
   14.94 +          already-installed package:
   14.95 +
   14.96 +	    - if there is an upstream package that obsoletes the
   14.97 +              already-installed package, then behave as though the
   14.98 +              user had requested that that package be installed
   14.99 +              instead.
  14.100 +
  14.101 +	    - else it's an error (UP_TO_DATE or INSTALL_UNAVAILABLE?)
  14.102 +
  14.103 +	- else it's an error (INSTALL_UNAVAILABLE)
  14.104 +
  14.105 +    2. Every requested removal in the initial package set must be
  14.106 +       satisfied as a removal. If any requested package name is not
  14.107 +       the name of an installed package, it's an error
  14.108 +       (REMOVE_NOT_INSTALLED)
  14.109 +
  14.110 +    REQUIRES processing:
  14.111 +
  14.112 +    3. If a package being installed or updated-to REQUIRES a property
  14.113 +       that is not provided by any installed or to-be-installed
  14.114 +       package, we need to find an installable package that provides
  14.115 +       that property. If we find one, install/update it. If not, it's
  14.116 +       an error (UNSATISFIABLE). (If we find an upstream package
  14.117 +       providing the property that corresponds to a system package
  14.118 +       that's being removed, then it's a CONTRADICTION.)
  14.119 +
  14.120 +    4. If an already-installed package REQUIRES a property which is
  14.121 +       only provided by a package that is being removed, then that
  14.122 +       package needs to be removed as well.
  14.123 +
  14.124 +    5. If an already-installed package REQUIRES a property which is
  14.125 +       only provided by a package that is being upgraded or obsoleted
  14.126 +       (to a new package which does not provide that property), then:
  14.127 +
  14.128 +	- if there is an update for the installed package, then update
  14.129 +          the installed package
  14.130 +
  14.131 +	- else if there is another installable package that provides
  14.132 +          the required property, then install that.
  14.133 +
  14.134 +	- else it's an error (UNSATISFIABLE?)
  14.135 +
  14.136 +    CONFLICTS processing
  14.137 +
  14.138 +    6. If a package being installed or updated-to CONFLICTS with a
  14.139 +       property provided by an installed package:
  14.140 +
  14.141 +	- if there is an update for the installed package, which the
  14.142 +          new package does not conflict with, then update the
  14.143 +          installed package.
  14.144 +
  14.145 +	- else it's an error (NEW_CONFLICT)
  14.146 +
  14.147 +    7. If an already-installed package CONFLICTS with a property
  14.148 +       provided by a to-be-installed package:
  14.149 +
  14.150 +	- if there is an update for the installed package, which does
  14.151 +          not conflict with the new package, then update the installed
  14.152 +          package.
  14.153 +
  14.154 +	- else it's an error (NEW_CONFLICT)
  14.155 +
  14.156 +    8. If a package being installed or updated-to CONFLICTS with a
  14.157 +       property provided by a to-be-installed package, then it's an
  14.158 +       error (CONTRADICTION).
  14.159 +
  14.160 +    OBSOLETES processing. NOTE: OBSOLETES are only matched against
  14.161 +    package names, not against arbitrary provided properties
  14.162 +
  14.163 +    9. If a package being installed or updated-to OBSOLETES an
  14.164 +       installed package, then obsolete that package. (ie, remove it,
  14.165 +       but treat it as updated for purposes of dangling REQUIRES).
  14.166 +
  14.167 +   10. If an already-installed package OBSOLETES a to-be-installed
  14.168 +       package, then it's an error. (ALREADY_OBSOLETE)
  14.169 +
  14.170 +   11. If a package being installed or updated-to OBSOLETES another
  14.171 +       package being installed or updated-to, then it's an error
  14.172 +       (CONTRADICTION).
  14.173 +
  14.174 +
  14.175 +
  14.176 +THE DEPSOLVER
  14.177 +-------------
  14.178 +
  14.179 +We start with two razor_sets, system and upstream, and a list of
  14.180 +requested installations and removals.
  14.181 +
  14.182 +    FIXME: what about multiple upstream repos? Having to deal with
  14.183 +    arbitrary numbers of razor_sets is possible, but will probably be
  14.184 +    messy... It might be easier to either store all upstream repo data
  14.185 +    in a single .repo file, or else merge all upstream .repo files
  14.186 +    together into a single razor_set at startup. (Or some combination
  14.187 +    of those.)
  14.188 +
  14.189 +We create a bit array of the packages in each set, indicating which
  14.190 +ones are installed; the system bitarray starts out all 1s, and the
  14.191 +upstream bitarray all 0s. Each bit is only allowed to change state
  14.192 +once during the transaction; an installed package can be removed, or
  14.193 +an uninstalled package installed, but trying to reinstall a removed
  14.194 +package, or uninstall a newly-installed package is an error. This
  14.195 +means the packages break down into four categories:
  14.196 +
  14.197 +    - installed       (1 bit in the system bit array)
  14.198 +    - to-be-removed   (0 bit in the system bit array)
  14.199 +    - to-be-installed (1 bit in the upstream bit array)
  14.200 +    - installable     (0 bit in the upstream bit array)
  14.201 +
  14.202 +
  14.203 +Depsolver algorithm:
  14.204 +
  14.205 +    - Create new razor_transaction_packages ("rtp"s) for each
  14.206 +      requested install or remove. These will be "unresolved", because
  14.207 +      we haven't yet found the razor_packages that correspond to them.
  14.208 +
  14.209 +    - while there are new rtps:
  14.210 +
  14.211 +	- sort the new rtps
  14.212 +
  14.213 +	- Walk the system property list, upstream property list, and
  14.214 +          new rtp list in parallel, and:
  14.215 +
  14.216 +	    - For each uninstalled PROVIDES:
  14.217 +
  14.218 +		- If the property is a valid package name (that is,
  14.219 +                  either it's a package providing its own name, or it
  14.220 +                  has a matching OBSOLETES), and it matches the name
  14.221 +                  of a new rtp of type INSTALL or FORCED_UPDATE with
  14.222 +                  an unresolved new_package:
  14.223 +
  14.224 +		    - If the upstream package has the same version as
  14.225 +		      the system package, we have an UP_TO_DATE error
  14.226 +		      (FIXME: not quite right. This doesn't deal with
  14.227 +		      the case where we try to update an application
  14.228 +		      because of a library update, and it turns out
  14.229 +		      there's no new version of the application, but
  14.230 +		      there IS a compat package containing the old
  14.231 +		      version of the library.)
  14.232 +
  14.233 +		    - Otherwise, set the rtp's new_package to point to
  14.234 +		      the package providing this property and set the
  14.235 +		      appropriate bit in the upstream bit array.
  14.236 +
  14.237 +	    - For each to-be-installed non-file REQUIRES:
  14.238 +
  14.239 +		- See if there's an installed or to-be-installed
  14.240 +		  package that PROVIDES that property.
  14.241 +
  14.242 +		- If not, see if there's an installable package that
  14.243 +		  PROVIDES that property, and create a new INSTALL rtp
  14.244 +		  for it if so.
  14.245 +
  14.246 +		- If not, see if there's a to-be-removed package that
  14.247 +		  PROVIDES that property. (If we find such a package,
  14.248 +		  we have a CONTRADICTION error.)
  14.249 +
  14.250 +		- If none of the above, then we have an UNSATISFIABLE
  14.251 +                  error
  14.252 +
  14.253 +	    - For each to-be-installed file REQUIRES:
  14.254 +
  14.255 +		- (We create fake file PROVIDES to match file REQUIRES
  14.256 +                  when importing/merging razor sets, so if there is
  14.257 +                  already another installed package that REQUIRES this
  14.258 +                  file, there will be a PROVIDES listed for it as well.)
  14.259 +
  14.260 +		- See if there's an installed package that PROVIDES
  14.261 +                  that file.
  14.262 +
  14.263 +		- If not, do a binary search of the system file tree
  14.264 +                  looking to see if some installed package provides
  14.265 +                  that file but does not have a PROVIDES for it.
  14.266 +
  14.267 +		- If not, see if there's an installable package that
  14.268 +		  PROVIDES that property, and create a new INSTALL rtp
  14.269 +		  for it if so.
  14.270 +
  14.271 +		- (If we actually work with multiple upstream
  14.272 +                  razor_sets, then we will need to search the upstream
  14.273 +                  file trees at this point, because it's possible that
  14.274 +                  a package in one upstream repo would require a file
  14.275 +                  in another upstream repo. But if we merge the
  14.276 +                  multiple upstream repos into a single razor_set at
  14.277 +                  some point, then we would not need to do that,
  14.278 +                  because it would be guaranteed that we would have
  14.279 +                  already created a fake PROVIDES if any package
  14.280 +                  provides the file.)
  14.281 +
  14.282 +		- If no installed or installable package provides the
  14.283 +		  file, see if there's a to-be-removed package that
  14.284 +		  provides the file. (If we find such a package, we
  14.285 +		  have a CONTRADICTION error.)
  14.286 +
  14.287 +		- If none of the above, then we have an UNSATISFIABLE
  14.288 +                  error
  14.289 +
  14.290 +	    - For each to-be-installed PROVIDES:
  14.291 +
  14.292 +		- Check if the new PROVIDES conflicts with an
  14.293 +		  installed CONFLICTS. If so, create a new
  14.294 +		  FORCED_UPDATE rtp for the installed package, so we
  14.295 +		  can try to upgrade it to a non-conflicting version.
  14.296 +		  (If we can't, we'll have an OLD_CONFLICT error.)
  14.297 +
  14.298 +		- Check if the new PROVIDES conflicts with an
  14.299 +                  installed OBSOLETES *and* the PROVIDES property
  14.300 +                  corresponds to the name of its package. (That is,
  14.301 +                  OBSOLETES are only matched against package names,
  14.302 +                  not arbitrary provided properties.) If so, we have
  14.303 +                  an ALREADY_OBSOLETE error.
  14.304 +
  14.305 +		- Check if the new PROVIDES conflicts with a
  14.306 +		  to-be-installed CONFLICTS. If so, we have a
  14.307 +		  CONTRADICTION error.
  14.308 +
  14.309 +	    - For each to-be-installed CONFLICTS:
  14.310 +
  14.311 +		- Basically the reverse of the previous case: check if
  14.312 +		  the new CONFLICTS conflicts with an installed
  14.313 +		  PROVIDES. If so, create a new FORCED_UPDATE rtp for
  14.314 +		  the installed package, so we can try to upgrade it
  14.315 +		  to a non-conflicting version. (If we can't, we'll
  14.316 +		  have an NEW_CONFLICT error.)
  14.317 +
  14.318 +		- Check if the new CONFLICTS conflicts with a
  14.319 +		  to-be-installed PROVIDES. If so, we have a
  14.320 +		  CONTRADICTION error.
  14.321 +
  14.322 +	    - For each to-be-installed OBSOLETES:
  14.323 +
  14.324 +		- Check if there's an installed package that PROVIDES
  14.325 +		  that property. If so, create an OBSOLETED rtp for
  14.326 +		  the installed package.
  14.327 +
  14.328 +		- If not, check if there's a to-be-installed package
  14.329 +		  that PROVIDES that property. If so, we have a
  14.330 +		  CONTRADICTION error.
  14.331 +
  14.332 +
  14.333 +	    - For each installed PROVIDES:
  14.334 +
  14.335 +		- If the property is a valid package name (that is,
  14.336 +                  it's a package providing its own name), and it
  14.337 +                  matches the name of a new rtp with an unresolved
  14.338 +                  old_package, then set the rtp's old_package to point
  14.339 +                  to the package providing this property and clear the
  14.340 +                  appropriate bit in the system bit array.
  14.341 +
  14.342 +	    - For each to-be-removed PROVIDES:
  14.343 +
  14.344 +		- If there's also an identical to-be-installed
  14.345 +		  PROVIDES, we're ok and can skip this
  14.346 +
  14.347 +		- Otherwise, for each installed REQUIRES of this
  14.348 +                  property:
  14.349 +
  14.350 +		    - Look for some other installed or to-be-installed
  14.351 +		      property that satisfies the REQUIRES.
  14.352 +
  14.353 +		    - If there isn't one, then for each installed
  14.354 +		      package in this REQUIRES's package list:
  14.355 +
  14.356 +			- If the PROVIDES was lost because the old
  14.357 +			  package was REMOVEd (not FORCED_UPDATE or
  14.358 +			  OBSOLETED), then create a new REMOVE rtp for
  14.359 +			  this package.
  14.360 +
  14.361 +			- Otherwise, create a new FORCED_UPDATE rtp
  14.362 +                          for this package.
  14.363 +
  14.364 +		- (We don't need to look at to-be-installed REQUIRES
  14.365 +		  of this property, because if there are any, they
  14.366 +		  will cause a CONTRADICTION error when we try to
  14.367 +		  re-satisfy them the next time through.)
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/docs/Makefile.am	Mon Jun 16 15:40:30 2008 -0400
    15.3 @@ -0,0 +1,5 @@
    15.4 +
    15.5 +EXTRA_DIST = 			\
    15.6 +	DEPSOLVE.txt 		\
    15.7 +	REPO.txt
    15.8 +
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/docs/REPO.txt	Mon Jun 16 15:40:30 2008 -0400
    16.3 @@ -0,0 +1,172 @@
    16.4 +The repo file format / razor_set data structure
    16.5 +-----------------------------------------------
    16.6 +
    16.7 +The repo starts with a header, containing some number of sections,
    16.8 +terminated by a section with type 0:
    16.9 +
   16.10 +	struct razor_set_header {
   16.11 +		uint32_t magic;
   16.12 +		uint32_t version;
   16.13 +		struct razor_set_section sections[0];
   16.14 +	};
   16.15 +
   16.16 +	struct razor_set_section {
   16.17 +		uint32_t type;
   16.18 +		uint32_t offset;
   16.19 +		uint32_t size;
   16.20 +	};
   16.21 +
   16.22 +razor_set_open() mmaps the repo file, and creates a struct razor_set:
   16.23 +
   16.24 +	struct razor_set {
   16.25 +		struct array string_pool;
   16.26 +	 	struct array packages;
   16.27 +	 	struct array properties;
   16.28 +	 	struct array files;
   16.29 +		struct array package_pool;
   16.30 +	 	struct array property_pool;
   16.31 +	 	struct array file_pool;
   16.32 +		struct razor_set_header *header;
   16.33 +	};
   16.34 +
   16.35 +by finding the sections with those IDs and creating "struct array"s
   16.36 +pointing to the right places in the mmapped data. (This is the only
   16.37 +processing needed when reading in the file; everything else is used
   16.38 +exactly as-is.)
   16.39 +
   16.40 +
   16.41 +The sections
   16.42 +------------
   16.43 +
   16.44 +RAZOR_STRING_POOL
   16.45 +
   16.46 +	Stores one copy of each string that appears in the repo. (At
   16.47 +	the moment, this is: package names, package versions, property
   16.48 +	names, property versions, and (basenames of) filenames.) The
   16.49 +	strings are arbitrarily-sized, 0-terminated, and not in any
   16.50 +	particular order (although the empty string always ends up
   16.51 +	being at offset 0).
   16.52 +
   16.53 +RAZOR_PACKAGES
   16.54 +
   16.55 +	Array of struct razor_package; one for each package in the
   16.56 +	set, sorted by name.
   16.57 +
   16.58 +RAZOR_PROPERTIES
   16.59 +
   16.60 +	Array of struct razor_property; one for each unique property
   16.61 +	in the set, sorted by type, then name, then relation type (eg,
   16.62 +	"<" or ">="), then version. (Properties with no version have
   16.63 +	relation type RAZOR_VERSION_EQUAL, and version "".)
   16.64 +
   16.65 +RAZOR_FILES
   16.66 +
   16.67 +	Array of struct razor_entry; one for each file owned by any
   16.68 +	package in the set. The current sort order (which is subject
   16.69 +	to change) is breadth-first, sorted by basename. So eg: /, /bin,
   16.70 +	/dev, /etc, /bin/false, /bin/true, /dev/null, /etc/passwd.
   16.71 +
   16.72 +RAZOR_PACKAGE_POOL
   16.73 +
   16.74 +	Array of struct list, with each list item containing the index
   16.75 +	of a struct razor_package in the packages section. See the
   16.76 +	discussion of lists below.
   16.77 +
   16.78 +RAZOR_PROPERTY_POOL
   16.79 +
   16.80 +	Array of struct list, with each list item containing the index
   16.81 +	of a struct razor_property in the properties section. See the
   16.82 +	discussion of lists below.
   16.83 +
   16.84 +RAZOR_FILE_POOL
   16.85 +
   16.86 +	Array of struct list, with each list item containing the index
   16.87 +	of a struct razor_entry in the files section. See the
   16.88 +	discussion of lists below.
   16.89 +
   16.90 +
   16.91 +Data types
   16.92 +----------
   16.93 +Note that the exact layout of bits involves some historical accidents.
   16.94 +(Particularly the fact that the "name" field in most structs loses its
   16.95 +high bits to a flags field.)
   16.96 +
   16.97 +struct list_head
   16.98 +	uint list_ptr : 24;
   16.99 +	uint flags    : 8;
  16.100 +
  16.101 +struct list
  16.102 +	uint data  : 24;
  16.103 +	uint flags : 8;
  16.104 +
  16.105 +	Used to store lists of package, property, or file IDs. "struct
  16.106 +	list_head" stores the head of the list, which points to one or
  16.107 +	more "struct list"s in the appropriate "pool" section.
  16.108 +	("struct list" should probably be called "struct list_item".)
  16.109 +
  16.110 +	"list_first(&head, &pool)" returns a "struct list *" pointing
  16.111 +	to the first element of the list (or NULL for an empty list),
  16.112 +	and "list_next(list)" will return successive elements, until
  16.113 +	NULL is returned. Each "list->data" contains the index of a
  16.114 +	package, property, or file in the corresponding section of the
  16.115 +	set.
  16.116 +
  16.117 +	Peeking underneath the abstraction, a list_head's "flags" is
  16.118 +	0xff if the list is empty, 0x80 if it contains a single
  16.119 +	element, or 0x00 if it contains more than one element. In the
  16.120 +	single-element case, that element is actually stored in the
  16.121 +	list_head directly rather than being stored in a pool (and so
  16.122 +	list_first() just casts the list_head* to a list* and returns
  16.123 +	it). For multi-element lists, list_ptr is the index in the
  16.124 +	pool of the first element of this list; the list continues
  16.125 +	through successive elements of the pool until one with
  16.126 +	non-zero flags is reached, indicating the end of the list.
  16.127 +
  16.128 +struct razor_package
  16.129 +	uint name    : 24;
  16.130 +	uint flags   : 8;
  16.131 +	uint version : 32;
  16.132 +	struct list_head properties;
  16.133 +	struct list_head files;
  16.134 +
  16.135 +	name and version are indexes into string_pool. properties is a
  16.136 +	list of all of the package's properties, and files is a list
  16.137 +	of its files. flags is currently only used during razor_set
  16.138 +	merging, to keep track of which set a package came from.
  16.139 +
  16.140 +struct razor_property
  16.141 +	uint name     : 24;
  16.142 +	uint flags    : 6;
  16.143 +	uint type     : 2;
  16.144 +	uint relation : 32;
  16.145 +	uint version  : 32;
  16.146 +	struct list_head packages;
  16.147 +
  16.148 +	name and version are indexes into string_pool. type is an enum
  16.149 +	razor_property_type (eg, RAZOR_PROPERTY_REQUIRES), and
  16.150 +	relation is an enum razor_version_relation (eg,
  16.151 +	RAZOR_VERSION_GREATER_OR_EQUAL). packages is a list of the
  16.152 +	packages that have this property. flags is currently unused.
  16.153 +
  16.154 +struct razor_entry
  16.155 +	uint name  : 24;
  16.156 +	uint flags : 8;
  16.157 +	uint start : 32;
  16.158 +	struct list_head packages;
  16.159 +
  16.160 +	name is an index into string_pool, giving the basename of the
  16.161 +	file. start is either 0, or an index pointing to another
  16.162 +	razor_entry that is the first child of this entry (for a
  16.163 +	non-empty directory). (Entry 0 is always the root of the tree,
  16.164 +	so no entry could have entry 0 as a child.) flags is 0x80
  16.165 +	(RAZOR_ENTRY_LAST) if an entry is the last entry in its
  16.166 +	directory. Otherwise it is 0.
  16.167 +
  16.168 +	Note that given a pointer to a struct_razor_entry (eg, from a
  16.169 +	package's "files" list), there is no way to reconstruct its
  16.170 +	full name without walking the entire files array up to that
  16.171 +	point. Because of this and other problems (fix_file_map()), it
  16.172 +	seems like razor_entry should be modified to include a pointer
  16.173 +	to its parent. (Storing full paths instead of just basenames
  16.174 +	would also fix this problem, but that would use much more
  16.175 +	memory.)
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/librazor/.gitignore	Mon Jun 16 15:40:30 2008 -0400
    17.3 @@ -0,0 +1,5 @@
    17.4 +.deps
    17.5 +.libs
    17.6 +*.lo
    17.7 +*.la
    17.8 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/librazor/Makefile.am	Mon Jun 16 15:40:30 2008 -0400
    18.3 @@ -0,0 +1,34 @@
    18.4 +## Process this file with automake to produce Makefile.in
    18.5 +
    18.6 +INCLUDES = \
    18.7 +	-I$(top_builddir)/src -I$(top_srcdir)/src \
    18.8 +	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
    18.9 +	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
   18.10 +	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
   18.11 +	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
   18.12 +	-DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \
   18.13 +	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
   18.14 +	-DPACKAGE_LIB_DIR=\""$(libdir)"\"
   18.15 +
   18.16 +lib_LTLIBRARIES = librazor.la
   18.17 +
   18.18 +librazorincludedir = $(includedir)/razor
   18.19 +
   18.20 +librazorinclude_HEADERS =              			\
   18.21 +	razor.h
   18.22 +
   18.23 +librazor_la_SOURCES =                                	\
   18.24 +	razor-internal.h				\
   18.25 +	razor.h						\
   18.26 +	razor.c						\
   18.27 +	razor-root.c					\
   18.28 +	types.h						\
   18.29 +	types.c						\
   18.30 +	util.c						\
   18.31 +	rpm.c
   18.32 +
   18.33 +librazor_la_LIBADD = $(ZLIB_LIBS)
   18.34 +
   18.35 +clean-local :
   18.36 +	rm -f *~
   18.37 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/librazor/razor-internal.h	Mon Jun 16 15:40:30 2008 -0400
    19.3 @@ -0,0 +1,19 @@
    19.4 +#ifndef _RAZOR_INTERNAL_H_
    19.5 +#define _RAZOR_INTERNAL_H_
    19.6 +
    19.7 +#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
    19.8 +
    19.9 +/* Utility functions */
   19.10 +
   19.11 +int razor_create_dir(const char *root, const char *path);
   19.12 +int razor_write(int fd, const void *data, size_t size);
   19.13 +
   19.14 +
   19.15 +typedef int (*razor_compare_with_data_func_t)(const void *p1,
   19.16 +					      const void *p,
   19.17 +					      void *data);
   19.18 +uint32_t *
   19.19 +razor_qsort_with_data(void *base, size_t nelem, size_t size,
   19.20 +		      razor_compare_with_data_func_t compare, void *data);
   19.21 +
   19.22 +#endif /* _RAZOR_INTERNAL_H_ */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/librazor/razor-root.c	Mon Jun 16 15:40:30 2008 -0400
    20.3 @@ -0,0 +1,168 @@
    20.4 +#include <stdlib.h>
    20.5 +#include <stdint.h>
    20.6 +#include <stdio.h>
    20.7 +#include <sys/stat.h>
    20.8 +#include <dirent.h>
    20.9 +#include <unistd.h>
   20.10 +#include <fcntl.h>
   20.11 +#include "razor.h"
   20.12 +#include "razor-internal.h"
   20.13 +
   20.14 +static const char system_repo_filename[] = "system.repo";
   20.15 +static const char next_repo_filename[] = "system-next.repo";
   20.16 +static const char razor_root_path[] = "/var/lib/razor";
   20.17 +
   20.18 +struct razor_root {
   20.19 +	struct razor_set *system;
   20.20 +	struct razor_set *next;
   20.21 +	int fd;
   20.22 +	char path[PATH_MAX];
   20.23 +	char new_path[PATH_MAX];
   20.24 +};
   20.25 +
   20.26 +int
   20.27 +razor_root_create(const char *root)
   20.28 +{
   20.29 +	struct stat buf;
   20.30 +	struct razor_set *set;
   20.31 +	char path[PATH_MAX];
   20.32 +
   20.33 +	if (stat(root, &buf) < 0) {
   20.34 +		if (mkdir(root, 0777) < 0) {
   20.35 +			fprintf(stderr,
   20.36 +				"could not create install root \"%s\"\n",
   20.37 +				root);
   20.38 +			return -1;
   20.39 +		}
   20.40 +		fprintf(stderr, "created install root \"%s\"\n", root);
   20.41 +	} else if (!S_ISDIR(buf.st_mode)) {
   20.42 +		fprintf(stderr,
   20.43 +			"install root \"%s\" exists, but is not a directory\n",
   20.44 +			root);
   20.45 +		return -1;
   20.46 +	}
   20.47 +
   20.48 +	snprintf(path, sizeof path, "%s/%s",
   20.49 +		 razor_root_path, system_repo_filename);
   20.50 +	if (razor_create_dir(root, path) < 0) {
   20.51 +		fprintf(stderr, "could not create %s%s\n",
   20.52 +			root, razor_root_path);
   20.53 +		return -1;
   20.54 +	}
   20.55 +
   20.56 +	set = razor_set_create();
   20.57 +	snprintf(path, sizeof path, "%s%s/%s",
   20.58 +		 root, razor_root_path, system_repo_filename);
   20.59 +	if (stat(path, &buf) == 0) {
   20.60 +		fprintf(stderr,
   20.61 +			"a razor install root is already initialized\n");
   20.62 +		return -1;
   20.63 +	}
   20.64 +	if (razor_set_write(set, path) < 0) {
   20.65 +		fprintf(stderr, "could not write initial package set\n");
   20.66 +		return -1;
   20.67 +	}
   20.68 +	razor_set_destroy(set);
   20.69 +
   20.70 +	return 0;
   20.71 +}
   20.72 +
   20.73 +struct razor_root *
   20.74 +razor_root_open(const char *root, int flags)
   20.75 +{
   20.76 +	struct razor_root *image;
   20.77 +
   20.78 +	image = malloc(sizeof *image);
   20.79 +	if (image == NULL)
   20.80 +		return NULL;
   20.81 +
   20.82 +	/* Create the new next repo file up front to ensure exclusive
   20.83 +	 * access. */
   20.84 +	snprintf(image->new_path, sizeof image->new_path,
   20.85 +		 "%s%s/%s", root, root, next_repo_filename);
   20.86 +	image->fd = open(image->new_path,
   20.87 +			 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
   20.88 +	if (image->fd < 0) {
   20.89 +		fprintf(stderr, "failed to get lock file, "
   20.90 +			"maybe previous operation crashed?\n");
   20.91 +
   20.92 +		/* FIXME: Use fcntl advisory locking on the system
   20.93 +		 * package set file to figure out whether previous
   20.94 +		 * operation crashed or is still in progress. */
   20.95 +
   20.96 +		free(image);
   20.97 +		return NULL;
   20.98 +	}
   20.99 +
  20.100 +	snprintf(image->path, sizeof image->path,
  20.101 +		 "%s%s/%s", root, razor_root_path, system_repo_filename);
  20.102 +	image->system = razor_set_open(image->path);
  20.103 +	if (image->system == NULL) {
  20.104 +		unlink(image->new_path);
  20.105 +		close(image->fd);
  20.106 +		free(image);
  20.107 +		return NULL;
  20.108 +	}
  20.109 +
  20.110 +	return image;
  20.111 +}
  20.112 +
  20.113 +struct razor_set *
  20.114 +razor_root_open_read_only(const char *root)
  20.115 +{
  20.116 +	char path[PATH_MAX];
  20.117 +
  20.118 +	snprintf(path, sizeof path, "%s%s/%s",
  20.119 +		 root, razor_root_path, system_repo_filename);
  20.120 +
  20.121 +	return razor_set_open(path);
  20.122 +}
  20.123 +
  20.124 +struct razor_transaction *
  20.125 +razor_root_create_transaction(struct razor_root *image,
  20.126 +			      struct razor_set *upstream)
  20.127 +{
  20.128 +	/* FIXME: This should take a number of upstream repos. */
  20.129 +	return razor_transaction_create(image->system, upstream);
  20.130 +}
  20.131 +
  20.132 +int
  20.133 +razor_root_close(struct razor_root *image)
  20.134 +{
  20.135 +	unlink(image->new_path);
  20.136 +	close(image->fd);
  20.137 +	free(image);
  20.138 +
  20.139 +	return 0;
  20.140 +}
  20.141 +
  20.142 +void
  20.143 +razor_root_update(struct razor_root *root, struct razor_set *next)
  20.144 +{
  20.145 +	razor_set_write_to_fd(next, root->fd);
  20.146 +	root->next = next;
  20.147 +
  20.148 +	/* Sync the new repo file so the new package set is on disk
  20.149 +	 * before we start upgrading. */
  20.150 +	fsync(root->fd);
  20.151 +	printf("wrote %s\n", root->new_path);
  20.152 +}
  20.153 +
  20.154 +int
  20.155 +razor_root_commit(struct razor_root *image)
  20.156 +{
  20.157 +	/* Make it so. */
  20.158 +	rename(image->new_path, image->path);
  20.159 +	printf("renamed %s to %s\n", image->new_path, image->path);
  20.160 +	close(image->fd);
  20.161 +	free(image);
  20.162 +
  20.163 +	return 0;
  20.164 +}
  20.165 +
  20.166 +void
  20.167 +razor_root_diff(struct razor_root *root,
  20.168 +		razor_package_callback_t callback, void *data)
  20.169 +{
  20.170 +	return razor_set_diff(root->system, root->next, callback, data);
  20.171 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/librazor/razor.c	Mon Jun 16 15:40:30 2008 -0400
    21.3 @@ -0,0 +1,2611 @@
    21.4 +/*
    21.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    21.6 + * Copyright (C) 2008  Red Hat, Inc
    21.7 + *
    21.8 + * This program is free software; you can redistribute it and/or modify
    21.9 + * it under the terms of the GNU General Public License as published by
   21.10 + * the Free Software Foundation; either version 2 of the License, or
   21.11 + * (at your option) any later version.
   21.12 + *
   21.13 + * This program is distributed in the hope that it will be useful,
   21.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.16 + * GNU General Public License for more details.
   21.17 + *
   21.18 + * You should have received a copy of the GNU General Public License along
   21.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   21.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   21.21 + */
   21.22 +
   21.23 +#define _GNU_SOURCE
   21.24 +
   21.25 +#include <stdlib.h>
   21.26 +#include <stddef.h>
   21.27 +#include <stdint.h>
   21.28 +#include <stdio.h>
   21.29 +#include <string.h>
   21.30 +#include <sys/types.h>
   21.31 +#include <sys/stat.h>
   21.32 +#include <sys/mman.h>
   21.33 +#include <unistd.h>
   21.34 +#include <fcntl.h>
   21.35 +#include <errno.h>
   21.36 +#include <ctype.h>
   21.37 +#include <fnmatch.h>
   21.38 +
   21.39 +#include "razor.h"
   21.40 +#include "razor-internal.h"
   21.41 +#include "types.h"
   21.42 +
   21.43 +struct razor_set_section {
   21.44 +	uint32_t type;
   21.45 +	uint32_t offset;
   21.46 +	uint32_t size;
   21.47 +};
   21.48 +
   21.49 +struct razor_set_header {
   21.50 +	uint32_t magic;
   21.51 +	uint32_t version;
   21.52 +	struct razor_set_section sections[0];
   21.53 +};
   21.54 +
   21.55 +#define RAZOR_MAGIC 0x7a7a7a7a
   21.56 +#define RAZOR_VERSION 1
   21.57 +
   21.58 +#define RAZOR_STRING_POOL	0
   21.59 +#define RAZOR_PACKAGES		1
   21.60 +#define RAZOR_PROPERTIES	2
   21.61 +#define RAZOR_FILES		3
   21.62 +#define RAZOR_PACKAGE_POOL	4
   21.63 +#define RAZOR_PROPERTY_POOL	5
   21.64 +#define RAZOR_FILE_POOL		6
   21.65 +
   21.66 +struct razor_package {
   21.67 +	uint name  : 24;
   21.68 +	uint flags : 8;
   21.69 +	uint32_t version;
   21.70 +	uint32_t arch;
   21.71 +	struct list_head properties;
   21.72 +	struct list_head files;
   21.73 +};
   21.74 +
   21.75 +struct razor_property {
   21.76 +	uint name  : 24;
   21.77 +	uint flags : 6;
   21.78 +	enum razor_property_type type : 2;
   21.79 +	enum razor_version_relation relation : 32;
   21.80 +	uint32_t version;
   21.81 +	struct list_head packages;
   21.82 +};
   21.83 +
   21.84 +struct razor_entry {
   21.85 +	uint name  : 24;
   21.86 +	uint flags : 8;
   21.87 +	uint32_t start;
   21.88 +	struct list_head packages;
   21.89 +};
   21.90 +
   21.91 +#define RAZOR_ENTRY_LAST	0x80
   21.92 +
   21.93 +struct razor_set {
   21.94 +	struct array string_pool;
   21.95 + 	struct array packages;
   21.96 + 	struct array properties;
   21.97 + 	struct array files;
   21.98 +	struct array package_pool;
   21.99 + 	struct array property_pool;
  21.100 + 	struct array file_pool;
  21.101 +	struct razor_set_header *header;
  21.102 +};
  21.103 +
  21.104 +struct import_entry {
  21.105 +	uint32_t package;
  21.106 +	char *name;
  21.107 +};
  21.108 +
  21.109 +struct import_directory {
  21.110 +	uint32_t name, count;
  21.111 +	struct array files;
  21.112 +	struct array packages;
  21.113 +	struct import_directory *last;
  21.114 +};
  21.115 +
  21.116 +struct razor_importer {
  21.117 +	struct razor_set *set;
  21.118 +	struct hashtable table;
  21.119 +	struct razor_package *package;
  21.120 +	struct array properties;
  21.121 +	struct array files;
  21.122 +	struct array file_requires;
  21.123 +};
  21.124 +
  21.125 +static void *
  21.126 +zalloc(size_t size)
  21.127 +{
  21.128 +	void *p;
  21.129 +
  21.130 +	p = malloc(size);
  21.131 +	memset(p, 0, size);
  21.132 +
  21.133 +	return p;
  21.134 +}
  21.135 +
  21.136 +struct razor_set_section razor_sections[] = {
  21.137 +	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
  21.138 +	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
  21.139 +	{ RAZOR_PROPERTIES,	offsetof(struct razor_set, properties) },
  21.140 +	{ RAZOR_FILES,		offsetof(struct razor_set, files) },
  21.141 +	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
  21.142 +	{ RAZOR_PROPERTY_POOL,	offsetof(struct razor_set, property_pool) },
  21.143 +	{ RAZOR_FILE_POOL,	offsetof(struct razor_set, file_pool) },
  21.144 +};
  21.145 +
  21.146 +struct razor_set *
  21.147 +razor_set_create(void)
  21.148 +{
  21.149 +	struct razor_set *set;
  21.150 +	struct razor_entry *e;
  21.151 +	char *empty;
  21.152 +
  21.153 +	set = zalloc(sizeof *set);
  21.154 +
  21.155 +	e = array_add(&set->files, sizeof *e);
  21.156 +	empty = array_add(&set->string_pool, 1);
  21.157 +	*empty = '\0';
  21.158 +	e->name = 0;
  21.159 +	e->flags = RAZOR_ENTRY_LAST;
  21.160 +	e->start = 0;
  21.161 +	list_set_empty(&e->packages);
  21.162 +
  21.163 +	return set;
  21.164 +}
  21.165 +
  21.166 +struct razor_set *
  21.167 +razor_set_open(const char *filename)
  21.168 +{
  21.169 +	struct razor_set *set;
  21.170 +	struct razor_set_section *s;
  21.171 +	struct stat stat;
  21.172 +	struct array *array;
  21.173 +	int fd;
  21.174 +
  21.175 +	set = zalloc(sizeof *set);
  21.176 +	fd = open(filename, O_RDONLY);
  21.177 +	if (fstat(fd, &stat) < 0)
  21.178 +		return NULL;
  21.179 +	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  21.180 +	if (set->header == MAP_FAILED) {
  21.181 +		free(set);
  21.182 +		return NULL;
  21.183 +	}
  21.184 +
  21.185 +	for (s = set->header->sections; ~s->type; s++) {
  21.186 +		if (s->type >= ARRAY_SIZE(razor_sections))
  21.187 +			continue;
  21.188 +		if (s->type != razor_sections[s->type].type)
  21.189 +			continue;
  21.190 +		array = (void *) set + razor_sections[s->type].offset;
  21.191 +		array->data = (void *) set->header + s->offset;
  21.192 +		array->size = s->size;
  21.193 +		array->alloc = s->size;
  21.194 +	}
  21.195 +	close(fd);
  21.196 +
  21.197 +	return set;
  21.198 +}
  21.199 +
  21.200 +void
  21.201 +razor_set_destroy(struct razor_set *set)
  21.202 +{
  21.203 +	unsigned int size;
  21.204 +	struct array *a;
  21.205 +	int i;
  21.206 +
  21.207 +	if (set->header) {
  21.208 +		for (i = 0; set->header->sections[i].type; i++)
  21.209 +			;
  21.210 +		size = set->header->sections[i].type;
  21.211 +		munmap(set->header, size);
  21.212 +	} else {
  21.213 +		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  21.214 +			a = (void *) set + razor_sections[i].offset;
  21.215 +			free(a->data);
  21.216 +		}
  21.217 +	}
  21.218 +
  21.219 +	free(set);
  21.220 +}
  21.221 +
  21.222 +int
  21.223 +razor_set_write_to_fd(struct razor_set *set, int fd)
  21.224 +{
  21.225 +	char data[4096];
  21.226 +	struct razor_set_header *header = (struct razor_set_header *) data;
  21.227 +	struct array *a;
  21.228 +	uint32_t offset;
  21.229 +	int i;
  21.230 +
  21.231 +	memset(data, 0, sizeof data);
  21.232 +	header->magic = RAZOR_MAGIC;
  21.233 +	header->version = RAZOR_VERSION;
  21.234 +	offset = sizeof data;
  21.235 +
  21.236 +	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  21.237 +		if (razor_sections[i].type != i)
  21.238 +			continue;
  21.239 +		a = (void *) set + razor_sections[i].offset;
  21.240 +		header->sections[i].type = i;
  21.241 +		header->sections[i].offset = offset;
  21.242 +		header->sections[i].size = a->size;
  21.243 +		offset += ALIGN(a->size, 4096);
  21.244 +	}
  21.245 +
  21.246 +	header->sections[i].type = ~0;
  21.247 +	header->sections[i].offset = 0;
  21.248 +	header->sections[i].size = 0;
  21.249 +
  21.250 +	razor_write(fd, data, sizeof data);
  21.251 +	memset(data, 0, sizeof data);
  21.252 +	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  21.253 +		if (razor_sections[i].type != i)
  21.254 +			continue;
  21.255 +		a = (void *) set + razor_sections[i].offset;
  21.256 +		razor_write(fd, a->data, a->size);
  21.257 +		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
  21.258 +	}
  21.259 +
  21.260 +	return 0;
  21.261 +}
  21.262 +
  21.263 +int
  21.264 +razor_set_write(struct razor_set *set, const char *filename)
  21.265 +{
  21.266 +	int fd, status;
  21.267 +
  21.268 +	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
  21.269 +	if (fd < 0)
  21.270 +		return -1;
  21.271 +
  21.272 +	status = razor_set_write_to_fd(set, fd);
  21.273 +	if (status) {
  21.274 +	    close(fd);
  21.275 +	    return status;
  21.276 +	}
  21.277 +
  21.278 +	return close(fd);
  21.279 +}
  21.280 +
  21.281 +void
  21.282 +razor_build_evr(char *evr_buf, int size, const char *epoch,
  21.283 +		const char *version, const char *release)
  21.284 +{
  21.285 +	int len;
  21.286 +
  21.287 +	if (!version || !*version) {
  21.288 +		*evr_buf = '\0';
  21.289 +		return;
  21.290 +	}
  21.291 +
  21.292 +	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
  21.293 +		len = snprintf(evr_buf, size, "%s:", epoch);
  21.294 +		evr_buf += len;
  21.295 +		size -= len;
  21.296 +	}
  21.297 +	len = snprintf(evr_buf, size, "%s", version);
  21.298 +	evr_buf += len;
  21.299 +	size -= len;
  21.300 +	if (release && *release)
  21.301 +		snprintf(evr_buf, size, "-%s", release);
  21.302 +}
  21.303 +
  21.304 +void
  21.305 +razor_importer_begin_package(struct razor_importer *importer,
  21.306 +			     const char *name,
  21.307 +			     const char *version,
  21.308 +			     const char *arch)
  21.309 +{
  21.310 +	struct razor_package *p;
  21.311 +
  21.312 +	p = array_add(&importer->set->packages, sizeof *p);
  21.313 +	p->name = hashtable_tokenize(&importer->table, name);
  21.314 +	p->flags = 0;
  21.315 +	p->version = hashtable_tokenize(&importer->table, version);
  21.316 +	p->arch = hashtable_tokenize(&importer->table, arch);
  21.317 +
  21.318 +	importer->package = p;
  21.319 +	array_init(&importer->properties);
  21.320 +}
  21.321 +
  21.322 +void
  21.323 +razor_importer_finish_package(struct razor_importer *importer)
  21.324 +{
  21.325 +	list_set_array(&importer->package->properties,
  21.326 +		       &importer->set->property_pool,
  21.327 +		       &importer->properties,
  21.328 +		       1);
  21.329 +
  21.330 +	array_release(&importer->properties);
  21.331 +}
  21.332 +
  21.333 +void
  21.334 +razor_importer_add_property(struct razor_importer *importer,
  21.335 +			    const char *name,
  21.336 +			    enum razor_version_relation relation,
  21.337 +			    const char *version,
  21.338 +			    enum razor_property_type type)
  21.339 +{
  21.340 +	struct razor_property *p;
  21.341 +	uint32_t *r;
  21.342 +
  21.343 +	p = array_add(&importer->set->properties, sizeof *p);
  21.344 +	p->name = hashtable_tokenize(&importer->table, name);
  21.345 +	p->flags = 0;
  21.346 +	p->type = type;
  21.347 +	p->relation = relation;
  21.348 +	p->version = hashtable_tokenize(&importer->table, version);
  21.349 +	list_set_ptr(&p->packages, importer->package -
  21.350 +		     (struct razor_package *) importer->set->packages.data);
  21.351 +
  21.352 +	r = array_add(&importer->properties, sizeof *r);
  21.353 +	*r = p - (struct razor_property *) importer->set->properties.data;
  21.354 +
  21.355 +	if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
  21.356 +		r = array_add(&importer->file_requires, sizeof *r);
  21.357 +		*r = p->name;
  21.358 +	}
  21.359 +}
  21.360 +
  21.361 +void
  21.362 +razor_importer_add_file(struct razor_importer *importer, const char *name)
  21.363 +{
  21.364 +	struct import_entry *e;
  21.365 +
  21.366 +	e = array_add(&importer->files, sizeof *e);
  21.367 +
  21.368 +	e->package = importer->package -
  21.369 +		(struct razor_package *) importer->set->packages.data;
  21.370 +	e->name = strdup(name);
  21.371 +}
  21.372 +
  21.373 +struct razor_importer *
  21.374 +razor_importer_new(void)
  21.375 +{
  21.376 +	struct razor_importer *importer;
  21.377 +
  21.378 +	importer = zalloc(sizeof *importer);
  21.379 +	importer->set = razor_set_create();
  21.380 +	hashtable_init(&importer->table, &importer->set->string_pool);
  21.381 +
  21.382 +	return importer;
  21.383 +}
  21.384 +
  21.385 +/* Destroy an importer without creating the set. */
  21.386 +void
  21.387 +razor_importer_destroy(struct razor_importer *importer)
  21.388 +{
  21.389 +	/* FIXME: write this */
  21.390 +}
  21.391 +
  21.392 +static int
  21.393 +versioncmp(const char *s1, const char *s2)
  21.394 +{
  21.395 +	const char *p1, *p2;
  21.396 +	long n1, n2;
  21.397 +	int res;
  21.398 +
  21.399 +	n1 = strtol(s1, (char **) &p1, 10);
  21.400 +	n2 = strtol(s2, (char **) &p2, 10);
  21.401 +
  21.402 +	/* Epoch; if one but not the other has an epoch set, default
  21.403 +	 * the epoch-less version to 0. */
  21.404 +	res = (*p1 == ':') - (*p2 == ':');
  21.405 +	if (res < 0) {
  21.406 +		n1 = 0;
  21.407 +		p1 = s1;
  21.408 +		p2++;
  21.409 +	} else if (res > 0) {
  21.410 +		p1++;
  21.411 +		n2 = 0;
  21.412 +		p2 = s2;
  21.413 +	}
  21.414 +
  21.415 +	if (n1 != n2)
  21.416 +		return n1 - n2;
  21.417 +	while (*p1 && *p2) {
  21.418 +		if (*p1 != *p2)
  21.419 +			return *p1 - *p2;
  21.420 +		p1++;
  21.421 +		p2++;
  21.422 +		if (isdigit(*p1) && isdigit(*p2))
  21.423 +			return versioncmp(p1, p2);
  21.424 +	}
  21.425 +
  21.426 +	return *p1 - *p2;
  21.427 +}
  21.428 +
  21.429 +static int
  21.430 +compare_packages(const void *p1, const void *p2, void *data)
  21.431 +{
  21.432 +	const struct razor_package *pkg1 = p1, *pkg2 = p2;
  21.433 +	struct razor_set *set = data;
  21.434 +	char *pool = set->string_pool.data;
  21.435 +
  21.436 +	/* FIXME: what if the flags are different? */
  21.437 +	if (pkg1->name == pkg2->name)
  21.438 +		return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
  21.439 +	else
  21.440 +		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
  21.441 +}
  21.442 +
  21.443 +static int
  21.444 +compare_properties(const void *p1, const void *p2, void *data)
  21.445 +{
  21.446 +	const struct razor_property *prop1 = p1, *prop2 = p2;
  21.447 +	struct razor_set *set = data;
  21.448 +	char *pool = set->string_pool.data;
  21.449 +
  21.450 +	if (prop1->name != prop2->name)
  21.451 +		return strcmp(&pool[prop1->name], &pool[prop2->name]);
  21.452 +	else if (prop1->type != prop2->type)
  21.453 +		return prop1->type - prop2->type;
  21.454 +	else if (prop1->relation != prop2->relation)
  21.455 +		return prop1->relation - prop2->relation;
  21.456 +	else
  21.457 +		return versioncmp(&pool[prop1->version], &pool[prop2->version]);
  21.458 +}
  21.459 +
  21.460 +static uint32_t *
  21.461 +uniqueify_properties(struct razor_set *set)
  21.462 +{
  21.463 +	struct razor_property *rp, *up, *rp_end;
  21.464 +	struct array *pkgs, *p;
  21.465 +	struct list_head *r;
  21.466 +	uint32_t *map, *rmap;
  21.467 +	int i, count, unique;
  21.468 +
  21.469 +	count = set->properties.size / sizeof(struct razor_property);
  21.470 +	map = razor_qsort_with_data(set->properties.data,
  21.471 +				    count,
  21.472 +				    sizeof(struct razor_property),
  21.473 +				    compare_properties,
  21.474 +				    set);
  21.475 +
  21.476 +	rp_end = set->properties.data + set->properties.size;
  21.477 +	rmap = malloc(count * sizeof *map);
  21.478 +	pkgs = zalloc(count * sizeof *pkgs);
  21.479 +	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
  21.480 +		if (rp->name != up->name || rp->type != up->type ||
  21.481 +		    rp->relation != up->relation || rp->version != up->version) {
  21.482 +			up++;
  21.483 +			up->name = rp->name;
  21.484 +			up->flags = 0;
  21.485 +			up->type = rp->type;
  21.486 +			up->relation = rp->relation;
  21.487 +			up->version = rp->version;
  21.488 +		}
  21.489 +
  21.490 +		unique = up - (struct razor_property *) set->properties.data;
  21.491 +		rmap[map[i]] = unique;
  21.492 +		r = array_add(&pkgs[unique], sizeof *r);
  21.493 +		*r = rp->packages;
  21.494 +	}
  21.495 +	free(map);
  21.496 +
  21.497 +	if (up != rp)
  21.498 +		up++;
  21.499 +	set->properties.size = (void *) up - set->properties.data;
  21.500 +	rp_end = up;
  21.501 +	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
  21.502 +		list_set_array(&rp->packages, &set->package_pool, p, 0);
  21.503 +		array_release(p);
  21.504 +	}
  21.505 +
  21.506 +	free(pkgs);
  21.507 +
  21.508 +	return rmap;
  21.509 +}
  21.510 +
  21.511 +static int
  21.512 +compare_filenames(const void *p1, const void *p2, void *data)
  21.513 +{
  21.514 +	const struct import_entry *e1 = p1;
  21.515 +	const struct import_entry *e2 = p2;
  21.516 +	const char *n1 = e1->name;
  21.517 +	const char *n2 = e2->name;
  21.518 +
  21.519 +	/* Need to make sure that the contents of a directory
  21.520 +	 * are sorted immediately after it. So "foo/bar" has to
  21.521 +	 * sort before "foo.conf"
  21.522 +	 *
  21.523 +	 * FIXME: this is about 60% slower than strcmp
  21.524 +	 */
  21.525 +	while (*n1 && *n2) {
  21.526 +		if (*n1 < *n2)
  21.527 +			return *n2 == '/' ? 1 : -1;
  21.528 +		else if (*n1 > *n2)
  21.529 +			return *n1 == '/' ? -1 : 1;
  21.530 +		n1++;
  21.531 +		n2++;
  21.532 +	}
  21.533 +	if (*n1)
  21.534 +		return 1;
  21.535 +	else if (*n2)
  21.536 +		return -1;
  21.537 +	else
  21.538 +		return 0;
  21.539 +}
  21.540 +
  21.541 +static void
  21.542 +count_entries(struct import_directory *d)
  21.543 +{
  21.544 +	struct import_directory *p, *end;
  21.545 +
  21.546 +	p = d->files.data;
  21.547 +	end = d->files.data + d->files.size;
  21.548 +	d->count = 0;
  21.549 +	while (p < end) {
  21.550 +		count_entries(p);
  21.551 +		d->count += p->count + 1;
  21.552 +		p++;
  21.553 +	}
  21.554 +}
  21.555 +
  21.556 +static void
  21.557 +serialize_files(struct razor_set *set,
  21.558 +		struct import_directory *d, struct array *array)
  21.559 +{
  21.560 +	struct import_directory *p, *end;
  21.561 +	struct razor_entry *e = NULL;
  21.562 +	uint32_t s;
  21.563 +
  21.564 +	p = d->files.data;
  21.565 +	end = d->files.data + d->files.size;
  21.566 +	s = array->size / sizeof *e + d->files.size / sizeof *p;
  21.567 +	while (p < end) {
  21.568 +		e = array_add(array, sizeof *e);
  21.569 +		e->name = p->name;
  21.570 +		e->flags = 0;
  21.571 +		e->start = p->count > 0 ? s : 0;
  21.572 +		s += p->count;
  21.573 +
  21.574 +		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
  21.575 +		array_release(&p->packages);
  21.576 +		p++;
  21.577 +	}
  21.578 +	if (e != NULL)
  21.579 +		e->flags |= RAZOR_ENTRY_LAST;
  21.580 +
  21.581 +	p = d->files.data;
  21.582 +	end = d->files.data + d->files.size;
  21.583 +	while (p < end) {
  21.584 +		serialize_files(set, p, array);
  21.585 +		p++;
  21.586 +	}
  21.587 +}
  21.588 +
  21.589 +static void
  21.590 +remap_property_package_links(struct array *properties, uint32_t *rmap)
  21.591 +{
  21.592 +	struct razor_property *p, *end;
  21.593 +
  21.594 +	end = properties->data + properties->size;
  21.595 +	for (p = properties->data; p < end; p++)
  21.596 +		list_remap_head(&p->packages, rmap);
  21.597 +}
  21.598 +
  21.599 +static void
  21.600 +build_file_tree(struct razor_importer *importer)
  21.601 +{
  21.602 +	int count, i, length;
  21.603 +	struct import_entry *filenames;
  21.604 +	char *f, *end;
  21.605 +	uint32_t name, *r;
  21.606 +	char dirname[256];
  21.607 +	struct import_directory *d, root;
  21.608 +	struct razor_entry *e;
  21.609 +
  21.610 +	count = importer->files.size / sizeof (struct import_entry);
  21.611 +	razor_qsort_with_data(importer->files.data,
  21.612 +			      count,
  21.613 +			      sizeof (struct import_entry),
  21.614 +			      compare_filenames,
  21.615 +			      NULL);
  21.616 +
  21.617 +	root.name = hashtable_tokenize(&importer->table, "");
  21.618 +	array_init(&root.files);
  21.619 +	array_init(&root.packages);
  21.620 +	root.last = NULL;
  21.621 +
  21.622 +	filenames = importer->files.data;
  21.623 +	for (i = 0; i < count; i++) {
  21.624 +		f = filenames[i].name;
  21.625 +		if (*f != '/')
  21.626 +			continue;
  21.627 +		f++;
  21.628 +
  21.629 +		d = &root;
  21.630 +		while (*f) {
  21.631 +			end = strchr(f, '/');
  21.632 +			if (end == NULL)
  21.633 +				end = f + strlen(f);
  21.634 +			length = end - f;
  21.635 +			memcpy(dirname, f, length);
  21.636 +			dirname[length] ='\0';
  21.637 +			name = hashtable_tokenize(&importer->table, dirname);
  21.638 +			if (d->last == NULL || d->last->name != name) {
  21.639 +				d->last = array_add(&d->files, sizeof *d);
  21.640 +				d->last->name = name;
  21.641 +				d->last->last = NULL;
  21.642 +				array_init(&d->last->files);
  21.643 +				array_init(&d->last->packages);
  21.644 +			}
  21.645 +			d = d->last;
  21.646 +			f = end + 1;
  21.647 +			if (*end == '\0')
  21.648 +				break;
  21.649 +		}
  21.650 +
  21.651 +		r = array_add(&d->packages, sizeof *r);
  21.652 +		*r = filenames[i].package;
  21.653 +		free(filenames[i].name);
  21.654 +	}
  21.655 +
  21.656 +	count_entries(&root);
  21.657 +	e = importer->set->files.data;
  21.658 +	e->name = root.name;
  21.659 +	e->flags = RAZOR_ENTRY_LAST;
  21.660 +	e->start = importer->files.size ? 1 : 0;
  21.661 +	list_set_empty(&e->packages);
  21.662 +
  21.663 +	serialize_files(importer->set, &root, &importer->set->files);
  21.664 +
  21.665 +	array_release(&importer->files);
  21.666 +}
  21.667 +
  21.668 +static struct razor_entry *
  21.669 +find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
  21.670 +
  21.671 +static void
  21.672 +list_to_array(struct list *list, struct array *array)
  21.673 +{
  21.674 +	uint32_t *item;
  21.675 +
  21.676 +	while (list) {
  21.677 +		 item = array_add(array, sizeof *item);
  21.678 +		 *item = list->data;
  21.679 +		 list = list_next(list);
  21.680 +	}
  21.681 +}
  21.682 +
  21.683 +static int
  21.684 +compare_file_requires(const void *p1, const void *p2, void *data)
  21.685 +{
  21.686 +	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
  21.687 +	const char *pool = data;
  21.688 +
  21.689 +	return strcmp(&pool[*f1], &pool[*f2]);
  21.690 +}
  21.691 +
  21.692 +static void
  21.693 +find_file_provides(struct razor_importer *importer)
  21.694 +{
  21.695 +	struct razor_property *prop;
  21.696 +	struct razor_entry *top, *entry;
  21.697 +	struct razor_package *packages;
  21.698 +	struct array pkgprops;
  21.699 +	struct list *pkg;
  21.700 +	uint32_t *req, *req_start, *req_end;
  21.701 +	uint32_t *map, *newprop;
  21.702 +	char *pool;
  21.703 +
  21.704 +	pool = importer->set->string_pool.data;
  21.705 +	packages = importer->set->packages.data;
  21.706 +	top = importer->set->files.data;
  21.707 +
  21.708 +	req = req_start = importer->file_requires.data;
  21.709 +	req_end = importer->file_requires.data + importer->file_requires.size;
  21.710 +	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
  21.711 +				    compare_file_requires, pool);
  21.712 +	free(map);
  21.713 +
  21.714 +	for (req = req_start; req < req_end; req++) {
  21.715 +		if (req > req_start && req[0] == req[-1])
  21.716 +			continue;
  21.717 +		entry = find_entry(importer->set, top, &pool[*req]);
  21.718 +		if (!entry)
  21.719 +			continue;
  21.720 +
  21.721 +		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
  21.722 +			prop = array_add(&importer->set->properties, sizeof *prop);
  21.723 +			prop->name = *req;
  21.724 +			prop->type = RAZOR_PROPERTY_PROVIDES;
  21.725 +			prop->relation = RAZOR_VERSION_EQUAL;
  21.726 +			prop->version = hashtable_tokenize(&importer->table, "");
  21.727 +			list_set_ptr(&prop->packages, pkg->data);
  21.728 +
  21.729 +			/* Update property list of pkg */
  21.730 +			array_init(&pkgprops);
  21.731 +			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
  21.732 +			newprop = array_add(&pkgprops, sizeof *newprop);
  21.733 +			*newprop = prop - (struct razor_property *)importer->set->properties.data;
  21.734 +			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
  21.735 +			array_release(&pkgprops);
  21.736 +		}
  21.737 +	}
  21.738 +
  21.739 +	array_release(&importer->file_requires);
  21.740 +}
  21.741 +
  21.742 +static void
  21.743 +build_package_file_lists(struct razor_set *set, uint32_t *rmap)
  21.744 +{
  21.745 +	struct razor_package *p, *packages;
  21.746 +	struct array *pkgs;
  21.747 +	struct razor_entry *e, *end;
  21.748 +	struct list *r;
  21.749 +	uint32_t *q;
  21.750 +	int i, count;
  21.751 +
  21.752 +	count = set->packages.size / sizeof *p;
  21.753 +	pkgs = zalloc(count * sizeof *pkgs);
  21.754 +
  21.755 +	end = set->files.data + set->files.size;
  21.756 +	for (e = set->files.data; e < end; e++) {
  21.757 +		list_remap_head(&e->packages, rmap);
  21.758 +		r = list_first(&e->packages, &set->package_pool);
  21.759 +		while (r) {
  21.760 +			q = array_add(&pkgs[r->data], sizeof *q);
  21.761 +			*q = e - (struct razor_entry *) set->files.data;
  21.762 +			r = list_next(r);
  21.763 +		}
  21.764 +	}
  21.765 +
  21.766 +	packages = set->packages.data;
  21.767 +	for (i = 0; i < count; i++) {
  21.768 +		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
  21.769 +		array_release(&pkgs[i]);
  21.770 +	}
  21.771 +	free(pkgs);
  21.772 +}
  21.773 +
  21.774 +struct razor_set *
  21.775 +razor_importer_finish(struct razor_importer *importer)
  21.776 +{
  21.777 +	struct razor_set *set;
  21.778 +	uint32_t *map, *rmap;
  21.779 +	int i, count;
  21.780 +
  21.781 +	build_file_tree(importer);
  21.782 +	find_file_provides(importer);
  21.783 +
  21.784 +	map = uniqueify_properties(importer->set);
  21.785 +	list_remap_pool(&importer->set->property_pool, map);
  21.786 +	free(map);
  21.787 +
  21.788 +	count = importer->set->packages.size / sizeof(struct razor_package);
  21.789 +	map = razor_qsort_with_data(importer->set->packages.data,
  21.790 +				    count,
  21.791 +				    sizeof(struct razor_package),
  21.792 +				    compare_packages,
  21.793 +				    importer->set);
  21.794 +
  21.795 +	rmap = malloc(count * sizeof *rmap);
  21.796 +	for (i = 0; i < count; i++)
  21.797 +		rmap[map[i]] = i;
  21.798 +	free(map);
  21.799 +
  21.800 +	list_remap_pool(&importer->set->package_pool, rmap);
  21.801 +	build_package_file_lists(importer->set, rmap);
  21.802 +	remap_property_package_links(&importer->set->properties, rmap);
  21.803 +	free(rmap);
  21.804 +
  21.805 +	set = importer->set;
  21.806 +	hashtable_release(&importer->table);
  21.807 +	free(importer);
  21.808 +
  21.809 +	return set;
  21.810 +}
  21.811 +
  21.812 +struct razor_package_iterator {
  21.813 +	struct razor_set *set;
  21.814 +	struct razor_package *package, *end;
  21.815 +	struct list *index;
  21.816 +	int free_index;
  21.817 +};
  21.818 +
  21.819 +static struct razor_package_iterator *
  21.820 +razor_package_iterator_create_with_index(struct razor_set *set,
  21.821 +					 struct list *index)
  21.822 +{
  21.823 +	struct razor_package_iterator *pi;
  21.824 +
  21.825 +	pi = zalloc(sizeof *pi);
  21.826 +	pi->set = set;
  21.827 +	pi->index = index;
  21.828 +
  21.829 +	return pi;
  21.830 +}
  21.831 +
  21.832 +struct razor_package_iterator *
  21.833 +razor_package_iterator_create(struct razor_set *set)
  21.834 +{
  21.835 +	struct razor_package_iterator *pi;
  21.836 +
  21.837 +	pi = zalloc(sizeof *pi);
  21.838 +	pi->set = set;
  21.839 +	pi->end = set->packages.data + set->packages.size;
  21.840 +	pi->package = set->packages.data;
  21.841 +
  21.842 +	return pi;
  21.843 +}
  21.844 +
  21.845 +static void
  21.846 +razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
  21.847 +					 struct razor_set *set,
  21.848 +					 struct razor_property *property)
  21.849 +{
  21.850 +	memset(pi, 0, sizeof *pi);
  21.851 +	pi->set = set;
  21.852 +	pi->index = list_first(&property->packages, &set->package_pool);
  21.853 +}
  21.854 +
  21.855 +struct razor_package_iterator *
  21.856 +razor_package_iterator_create_for_property(struct razor_set *set,
  21.857 +					   struct razor_property *property)
  21.858 +{
  21.859 +	struct list *index;
  21.860 +
  21.861 +	index = list_first(&property->packages, &set->package_pool);
  21.862 +	return razor_package_iterator_create_with_index(set, index);
  21.863 +}
  21.864 +
  21.865 +int
  21.866 +razor_package_iterator_next(struct razor_package_iterator *pi,
  21.867 +			    struct razor_package **package,
  21.868 +			    const char **name,
  21.869 +			    const char **version,
  21.870 +			    const char **arch)
  21.871 +{
  21.872 +	char *pool;
  21.873 +	int valid;
  21.874 +	struct razor_package *p, *packages;
  21.875 +
  21.876 +	if (pi->package) {
  21.877 +		p = pi->package++;
  21.878 +		valid = p < pi->end;
  21.879 +	} else if (pi->index) {
  21.880 +		packages = pi->set->packages.data;
  21.881 +		p = &packages[pi->index->data];
  21.882 +		pi->index = list_next(pi->index);
  21.883 +		valid = 1;
  21.884 +	} else
  21.885 +		valid = 0;
  21.886 +
  21.887 +	if (valid) {
  21.888 +		pool = pi->set->string_pool.data;
  21.889 +		*package = p;
  21.890 +		*name = &pool[p->name];
  21.891 +		*version = &pool[p->version];
  21.892 +		*arch = &pool[p->arch];
  21.893 +	} else {
  21.894 +		*package = NULL;
  21.895 +	}
  21.896 +
  21.897 +	return valid;
  21.898 +}
  21.899 +
  21.900 +void
  21.901 +razor_package_iterator_destroy(struct razor_package_iterator *pi)
  21.902 +{
  21.903 +	if (pi->free_index)
  21.904 +		free(pi->index);
  21.905 +
  21.906 +	free(pi);
  21.907 +}
  21.908 +
  21.909 +struct razor_package *
  21.910 +razor_set_get_package(struct razor_set *set, const char *package)
  21.911 +{
  21.912 +	struct razor_package_iterator *pi;
  21.913 +	struct razor_package *p;
  21.914 +	const char *name, *version, *arch;
  21.915 +
  21.916 +	pi = razor_package_iterator_create(set);
  21.917 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  21.918 +		if (strcmp(package, name) == 0)
  21.919 +			break;
  21.920 +	}
  21.921 +	razor_package_iterator_destroy(pi);
  21.922 +
  21.923 +	return p;
  21.924 +}
  21.925 +
  21.926 +struct razor_property_iterator {
  21.927 +	struct razor_set *set;
  21.928 +	struct razor_property *property, *end;
  21.929 +	struct list *index;
  21.930 +};
  21.931 +
  21.932 +struct razor_property_iterator *
  21.933 +razor_property_iterator_create(struct razor_set *set,
  21.934 +			       struct razor_package *package)
  21.935 +{
  21.936 +	struct razor_property_iterator *pi;
  21.937 +
  21.938 +	pi = zalloc(sizeof *pi);
  21.939 +	pi->set = set;
  21.940 +
  21.941 +	if (package) {
  21.942 +		pi->index = list_first(&package->properties,
  21.943 +				       &set->property_pool);
  21.944 +	} else {
  21.945 +		pi->property = set->properties.data;
  21.946 +		pi->end = set->properties.data + set->properties.size;
  21.947 +	}
  21.948 +
  21.949 +	return pi;
  21.950 +}
  21.951 +
  21.952 +int
  21.953 +razor_property_iterator_next(struct razor_property_iterator *pi,
  21.954 +			     struct razor_property **property,
  21.955 +			     const char **name,
  21.956 +			     enum razor_version_relation *relation,
  21.957 +			     const char **version,
  21.958 +			     enum razor_property_type *type)
  21.959 +{
  21.960 +	char *pool;
  21.961 +	int valid;
  21.962 +	struct razor_property *p, *properties;
  21.963 +
  21.964 +	if (pi->property) {
  21.965 +		p = pi->property++;
  21.966 +		valid = p < pi->end;
  21.967 +	} else if (pi->index) {
  21.968 +		properties = pi->set->properties.data;
  21.969 +		p = &properties[pi->index->data];
  21.970 +		pi->index = list_next(pi->index);
  21.971 +		valid = 1;
  21.972 +	} else
  21.973 +		valid = 0;
  21.974 +
  21.975 +	if (valid) {
  21.976 +		pool = pi->set->string_pool.data;
  21.977 +		*property = p;
  21.978 +		*name = &pool[p->name];
  21.979 +		*relation = p->relation;
  21.980 +		*version = &pool[p->version];
  21.981 +		*type = p->type;
  21.982 +	} else {
  21.983 +		*property = NULL;
  21.984 +	}
  21.985 +
  21.986 +	return valid;
  21.987 +}
  21.988 +
  21.989 +void
  21.990 +razor_property_iterator_destroy(struct razor_property_iterator *pi)
  21.991 +{
  21.992 +	free(pi);
  21.993 +}
  21.994 +
  21.995 +static struct razor_entry *
  21.996 +find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
  21.997 +{
  21.998 +	struct razor_entry *e;
  21.999 +	const char *n, *pool = set->string_pool.data;
 21.1000 +	int len;
 21.1001 +
 21.1002 +	e = (struct razor_entry *) set->files.data + dir->start;
 21.1003 +	do {
 21.1004 +		n = pool + e->name;
 21.1005 +		if (strcmp(pattern + 1, n) == 0)
 21.1006 +			return e;
 21.1007 +		len = strlen(n);
 21.1008 +		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
 21.1009 +		    pattern[len + 1] == '/') {
 21.1010 +			return find_entry(set, e, pattern + len + 1);
 21.1011 +		}
 21.1012 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 21.1013 +
 21.1014 +	return NULL;
 21.1015 +}
 21.1016 +
 21.1017 +static void
 21.1018 +list_dir(struct razor_set *set, struct razor_entry *dir,
 21.1019 +	 char *prefix, const char *pattern)
 21.1020 +{
 21.1021 +	struct razor_entry *e;
 21.1022 +	const char *n, *pool = set->string_pool.data;
 21.1023 +
 21.1024 +	e = (struct razor_entry *) set->files.data + dir->start;
 21.1025 +	do {
 21.1026 +		n = pool + e->name;
 21.1027 +		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
 21.1028 +			continue;
 21.1029 +		printf("%s/%s\n", prefix, n);
 21.1030 +		if (e->start) {
 21.1031 +			char *sub = prefix + strlen (prefix);
 21.1032 +			*sub = '/';
 21.1033 +			strcpy (sub + 1, n);
 21.1034 +			list_dir(set, e, prefix, pattern);
 21.1035 +			*sub = '\0';
 21.1036 +		}
 21.1037 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 21.1038 +}
 21.1039 +
 21.1040 +void
 21.1041 +razor_set_list_files(struct razor_set *set, const char *pattern)
 21.1042 +{
 21.1043 +	struct razor_entry *e;
 21.1044 +	char buffer[512], *p, *base;
 21.1045 +
 21.1046 +	if (pattern == NULL || !strcmp (pattern, "/")) {
 21.1047 +		buffer[0] = '\0';
 21.1048 +		list_dir(set, set->files.data, buffer, NULL);
 21.1049 +		return;
 21.1050 +	}
 21.1051 +
 21.1052 +	strcpy(buffer, pattern);
 21.1053 +	e = find_entry(set, set->files.data, buffer);
 21.1054 +	if (e && e->start > 0) {
 21.1055 +		base = NULL;
 21.1056 +	} else {
 21.1057 +		p = strrchr(buffer, '/');
 21.1058 +		if (p) {
 21.1059 +			*p = '\0';
 21.1060 +			base = p + 1;
 21.1061 +		} else {
 21.1062 +			base = NULL;
 21.1063 +		}
 21.1064 +	}
 21.1065 +	e = find_entry(set, set->files.data, buffer);
 21.1066 +	if (e->start != 0)
 21.1067 +		list_dir(set, e, buffer, base);
 21.1068 +}
 21.1069 +
 21.1070 +struct razor_package_iterator *
 21.1071 +razor_package_iterator_create_for_file(struct razor_set *set,
 21.1072 +				       const char *filename)
 21.1073 +{
 21.1074 +	struct razor_entry *entry;
 21.1075 +	struct list *index;
 21.1076 +
 21.1077 +	entry = find_entry(set, set->files.data, filename);
 21.1078 +	if (entry == NULL)
 21.1079 +		return NULL;
 21.1080 +
 21.1081 +	index = list_first(&entry->packages, &set->package_pool);
 21.1082 +	return razor_package_iterator_create_with_index(set, index);
 21.1083 +}
 21.1084 +
 21.1085 +static struct list *
 21.1086 +list_package_files(struct razor_set *set, struct list *r,
 21.1087 +		   struct razor_entry *dir, uint32_t end,
 21.1088 +		   char *prefix)
 21.1089 +{
 21.1090 +	struct razor_entry *e, *f, *entries;
 21.1091 +	uint32_t next, file;
 21.1092 +	char *pool;
 21.1093 +	int len;
 21.1094 +
 21.1095 +	entries = (struct razor_entry *) set->files.data;
 21.1096 +	pool = set->string_pool.data;
 21.1097 +
 21.1098 +	e = entries + dir->start;
 21.1099 +	do {
 21.1100 +		if (entries + r->data == e) {
 21.1101 +			printf("%s/%s\n", prefix, pool + e->name);
 21.1102 +			r = list_next(r);
 21.1103 +			if (!r)
 21.1104 +				return NULL;
 21.1105 +			if (r->data >= end)
 21.1106 +				return r;
 21.1107 +		}
 21.1108 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 21.1109 +
 21.1110 +	e = entries + dir->start;
 21.1111 +	do {
 21.1112 +		if (e->start == 0)
 21.1113 +			continue;
 21.1114 +
 21.1115 +		if (e->flags & RAZOR_ENTRY_LAST)
 21.1116 +			next = end;
 21.1117 +		else {
 21.1118 +			f = e + 1;
 21.1119 +			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
 21.1120 +				f++;
 21.1121 +			if (f->start == 0)
 21.1122 +				next = end;
 21.1123 +			else
 21.1124 +				next = f->start;
 21.1125 +		}
 21.1126 +
 21.1127 +		file = r->data;
 21.1128 +		if (e->start <= file && file < next) {
 21.1129 +			len = strlen(prefix);
 21.1130 +			prefix[len] = '/';
 21.1131 +			strcpy(prefix + len + 1, pool + e->name);
 21.1132 +			r = list_package_files(set, r, e, next, prefix);
 21.1133 +			prefix[len] = '\0';
 21.1134 +		}
 21.1135 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
 21.1136 +
 21.1137 +	return r;
 21.1138 +}
 21.1139 +
 21.1140 +void
 21.1141 +razor_set_list_package_files(struct razor_set *set, const char *name)
 21.1142 +{
 21.1143 +	struct razor_package *package;
 21.1144 +	struct list *r;
 21.1145 +	uint32_t end;
 21.1146 +	char buffer[512];
 21.1147 +
 21.1148 +	package = razor_set_get_package(set, name);
 21.1149 +
 21.1150 +	r = list_first(&package->files, &set->file_pool);
 21.1151 +	end = set->files.size / sizeof (struct razor_entry);
 21.1152 +	buffer[0] = '\0';
 21.1153 +	list_package_files(set, r, set->files.data, end, buffer);
 21.1154 +}
 21.1155 +
 21.1156 +#define UPSTREAM_SOURCE 0x80
 21.1157 +
 21.1158 +struct source {
 21.1159 +	struct razor_set *set;
 21.1160 +	uint32_t *property_map;
 21.1161 +	uint32_t *file_map;
 21.1162 +};
 21.1163 +
 21.1164 +struct razor_merger {
 21.1165 +	struct razor_set *set;
 21.1166 +	struct hashtable table;
 21.1167 +	struct source source1;
 21.1168 +	struct source source2;
 21.1169 +};
 21.1170 +
 21.1171 +static struct razor_merger *
 21.1172 +razor_merger_create(struct razor_set *set1, struct razor_set *set2)
 21.1173 +{
 21.1174 +	struct razor_merger *merger;
 21.1175 +	int count;
 21.1176 +	size_t size;
 21.1177 +
 21.1178 +	merger = zalloc(sizeof *merger);
 21.1179 +	merger->set = razor_set_create();
 21.1180 +	hashtable_init(&merger->table, &merger->set->string_pool);
 21.1181 +
 21.1182 +	merger->source1.set = set1;
 21.1183 +	count = set1->properties.size / sizeof (struct razor_property);
 21.1184 +	size = count * sizeof merger->source1.property_map[0];
 21.1185 +	merger->source1.property_map = zalloc(size);
 21.1186 +	count = set1->files.size / sizeof (struct razor_entry);
 21.1187 +	size = count * sizeof merger->source1.file_map[0];
 21.1188 +	merger->source1.file_map = zalloc(size);
 21.1189 +
 21.1190 +	merger->source2.set = set2;
 21.1191 +	count = set2->properties.size / sizeof (struct razor_property);
 21.1192 +	size = count * sizeof merger->source2.property_map[0];
 21.1193 +	merger->source2.property_map = zalloc(size);
 21.1194 +	count = set2->files.size / sizeof (struct razor_entry);
 21.1195 +	size = count * sizeof merger->source2.file_map[0];
 21.1196 +	merger->source2.file_map = zalloc(size);
 21.1197 +
 21.1198 +	return merger;
 21.1199 +}
 21.1200 +
 21.1201 +static void
 21.1202 +razor_merger_add_package(struct razor_merger *merger,
 21.1203 +			 struct razor_package *package)
 21.1204 +{
 21.1205 +	char *pool;
 21.1206 +	struct list *r;
 21.1207 +	struct razor_package *p;
 21.1208 +	struct razor_set *set1;
 21.1209 +	struct source *source;
 21.1210 +	uint32_t flags;
 21.1211 +
 21.1212 +	set1 = merger->source1.set;
 21.1213 +	if (set1->packages.data <= (void *) package &&
 21.1214 +	    (void *) package < set1->packages.data + set1->packages.size) {
 21.1215 +		source = &merger->source1;
 21.1216 +		flags = 0;
 21.1217 +	} else {
 21.1218 +		source = &merger->source2;
 21.1219 +		flags = UPSTREAM_SOURCE;
 21.1220 +	}
 21.1221 +
 21.1222 +	pool = source->set->string_pool.data;
 21.1223 +	p = array_add(&merger->set->packages, sizeof *p);
 21.1224 +	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
 21.1225 +	p->flags = flags;
 21.1226 +	p->version = hashtable_tokenize(&merger->table,
 21.1227 +					&pool[package->version]);
 21.1228 +	p->arch = hashtable_tokenize(&merger->table,
 21.1229 +				     &pool[package->arch]);
 21.1230 +
 21.1231 +	p->properties = package->properties;
 21.1232 +	r = list_first(&package->properties, &source->set->property_pool);
 21.1233 +	while (r) {
 21.1234 +		source->property_map[r->data] = 1;
 21.1235 +		r = list_next(r);
 21.1236 +	}
 21.1237 +
 21.1238 +	p->files = package->files;
 21.1239 +	r = list_first(&package->files, &source->set->file_pool);
 21.1240 +	while (r) {
 21.1241 +		source->file_map[r->data] = 1;
 21.1242 +		r = list_next(r);
 21.1243 +	}
 21.1244 +}
 21.1245 +
 21.1246 +static uint32_t
 21.1247 +add_property(struct razor_merger *merger,
 21.1248 +	     const char *name, enum razor_version_relation relation,
 21.1249 +	     const char *version, int type)
 21.1250 +{
 21.1251 +	struct razor_property *p;
 21.1252 +
 21.1253 +	p = array_add(&merger->set->properties, sizeof *p);
 21.1254 +	p->name = hashtable_tokenize(&merger->table, name);
 21.1255 +	p->flags = 0;
 21.1256 +	p->type = type;
 21.1257 +	p->relation = relation;
 21.1258 +	p->version = hashtable_tokenize(&merger->table, version);
 21.1259 +
 21.1260 +	return p - (struct razor_property *) merger->set->properties.data;
 21.1261 +}
 21.1262 +
 21.1263 +static void
 21.1264 +merge_properties(struct razor_merger *merger)
 21.1265 +{
 21.1266 +	struct razor_property *p1, *p2;
 21.1267 +	struct razor_set *set1, *set2;
 21.1268 +	uint32_t *map1, *map2;
 21.1269 +	int i, j, cmp, count1, count2;
 21.1270 +	char *pool1, *pool2;
 21.1271 +
 21.1272 +	set1 = merger->source1.set;
 21.1273 +	set2 = merger->source2.set;
 21.1274 +	map1 = merger->source1.property_map;
 21.1275 +	map2 = merger->source2.property_map;
 21.1276 +
 21.1277 +	i = 0;
 21.1278 +	j = 0;
 21.1279 +	pool1 = set1->string_pool.data;
 21.1280 +	pool2 = set2->string_pool.data;
 21.1281 +
 21.1282 +	count1 = set1->properties.size / sizeof *p1;
 21.1283 +	count2 = set2->properties.size / sizeof *p2;
 21.1284 +	while (i < count1 || j < count2) {
 21.1285 +		if (i < count1 && map1[i] == 0) {
 21.1286 +			i++;
 21.1287 +			continue;
 21.1288 +		}
 21.1289 +		if (j < count2 && map2[j] == 0) {
 21.1290 +			j++;
 21.1291 +			continue;
 21.1292 +		}
 21.1293 +		p1 = (struct razor_property *) set1->properties.data + i;
 21.1294 +		p2 = (struct razor_property *) set2->properties.data + j;
 21.1295 +		if (i < count1 && j < count2)
 21.1296 +			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
 21.1297 +		else if (i < count1)
 21.1298 +			cmp = -1;
 21.1299 +		else
 21.1300 +			cmp = 1;
 21.1301 +		if (cmp == 0)
 21.1302 +			cmp = p1->type - p2->type;
 21.1303 +		if (cmp == 0)
 21.1304 +			cmp = p1->relation - p2->relation;
 21.1305 +		if (cmp == 0)
 21.1306 +			cmp = versioncmp(&pool1[p1->version],
 21.1307 +					 &pool2[p2->version]);
 21.1308 +		if (cmp < 0) {
 21.1309 +			map1[i++] = add_property(merger,
 21.1310 +						 &pool1[p1->name],
 21.1311 +						 p1->relation,
 21.1312 +						 &pool1[p1->version],
 21.1313 +						 p1->type);
 21.1314 +		} else if (cmp > 0) {
 21.1315 +			map2[j++] = add_property(merger,
 21.1316 +						 &pool2[p2->name],
 21.1317 +						 p2->relation,
 21.1318 +						 &pool2[p2->version],
 21.1319 +						 p2->type);
 21.1320 +		} else  {
 21.1321 +			map1[i++] = map2[j++] = add_property(merger,
 21.1322 +							     &pool1[p1->name],
 21.1323 +							     p1->relation,
 21.1324 +							     &pool1[p1->version],
 21.1325 +							     p1->type);
 21.1326 +		}
 21.1327 +	}
 21.1328 +}
 21.1329 +
 21.1330 +static void
 21.1331 +emit_properties(struct list_head *properties, struct array *source_pool,
 21.1332 +		uint32_t *map, struct array *pool)
 21.1333 +{
 21.1334 +	uint32_t r;
 21.1335 +	struct list *p, *q;
 21.1336 +
 21.1337 +	r = pool->size / sizeof *q;
 21.1338 +	p = list_first(properties, source_pool);
 21.1339 +	while (p) {
 21.1340 +		q = array_add(pool, sizeof *q);
 21.1341 +		q->data = map[p->data];
 21.1342 +		q->flags = p->flags;
 21.1343 +		p = list_next(p);
 21.1344 +	}
 21.1345 +
 21.1346 +	list_set_ptr(properties, r);
 21.1347 +}
 21.1348 +
 21.1349 +static uint32_t
 21.1350 +add_file(struct razor_merger *merger, const char *name)
 21.1351 +{
 21.1352 +	struct razor_entry *e;
 21.1353 +
 21.1354 +	e = array_add(&merger->set->files, sizeof *e);
 21.1355 +	e->name = hashtable_tokenize(&merger->table, name);
 21.1356 +	e->flags = 0;
 21.1357 +	e->start = 0;
 21.1358 +
 21.1359 +	return e - (struct razor_entry *)merger->set->files.data;
 21.1360 +}
 21.1361 +
 21.1362 +/* FIXME. Blah */
 21.1363 +static int
 21.1364 +fix_file_map(uint32_t *map,
 21.1365 +	     struct razor_entry *files,
 21.1366 +	     struct razor_entry *top)
 21.1367 +{
 21.1368 +	uint32_t e;
 21.1369 +	int found_file = 0;
 21.1370 +
 21.1371 +	e = top->start;
 21.1372 +	do {
 21.1373 +		if (files[e].start)
 21.1374 +			fix_file_map(map, files, &files[e]);
 21.1375 +		if (map[e])
 21.1376 +			found_file = 1;
 21.1377 +	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
 21.1378 +
 21.1379 +	if (found_file)
 21.1380 +		map[top - files] = 1;
 21.1381 +	return found_file;
 21.1382 +}
 21.1383 +
 21.1384 +struct merge_directory {
 21.1385 +	uint32_t merged, dir1, dir2;
 21.1386 +};
 21.1387 +
 21.1388 +static void
 21.1389 +merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
 21.1390 +{
 21.1391 +	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
 21.1392 +	struct razor_set *set1, *set2;
 21.1393 +	struct array merge_stack;
 21.1394 +	struct merge_directory *child_md, *end_md;
 21.1395 +	uint32_t *map1, *map2, start, last;
 21.1396 +	int cmp;
 21.1397 +	char *pool1, *pool2;
 21.1398 +
 21.1399 +	set1 = merger->source1.set;
 21.1400 +	set2 = merger->source2.set;
 21.1401 +	map1 = merger->source1.file_map;
 21.1402 +	map2 = merger->source2.file_map;
 21.1403 +	pool1 = set1->string_pool.data;
 21.1404 +	pool2 = set2->string_pool.data;
 21.1405 +	root1 = (struct razor_entry *) set1->files.data;
 21.1406 +	root2 = (struct razor_entry *) set2->files.data;
 21.1407 +
 21.1408 +	array_init(&merge_stack);
 21.1409 +
 21.1410 +	start = merger->set->files.size / sizeof (struct razor_entry);
 21.1411 +	last = 0;
 21.1412 +	e1 = md->dir1 ? root1 + md->dir1 : NULL;
 21.1413 +	e2 = md->dir2 ? root2 + md->dir2 : NULL;
 21.1414 +	while (e1 || e2) {
 21.1415 +		if (!e2 && !map1[e1 - root1]) {
 21.1416 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 21.1417 +				e1 = NULL;
 21.1418 +			continue;
 21.1419 +		}
 21.1420 +		if (!e1 && !map2[e2 - root2]) {
 21.1421 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 21.1422 +				e2 = NULL;
 21.1423 +			continue;
 21.1424 +		}
 21.1425 +		if (e1 && !map1[e1 - root1] &&
 21.1426 +		    e2 && !map1[e2 - root2]) {
 21.1427 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 21.1428 +				e1 = NULL;
 21.1429 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 21.1430 +				e2 = NULL;
 21.1431 +			continue;
 21.1432 +		}
 21.1433 +
 21.1434 +		if (!e1)
 21.1435 +			cmp = 1;
 21.1436 +		else if (!e2)
 21.1437 +			cmp = -1;
 21.1438 +		else {
 21.1439 +			cmp = strcmp (&pool1[e1->name],
 21.1440 +				      &pool2[e2->name]);
 21.1441 +		}
 21.1442 +
 21.1443 +		if (cmp < 0) {
 21.1444 +			if (map1[e1 - root1]) {
 21.1445 +				map1[e1 - root1] = last =
 21.1446 +					add_file(merger, &pool1[e1->name]);
 21.1447 +				if (e1->start) {
 21.1448 +					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 21.1449 +					child_md->merged = last;
 21.1450 +					child_md->dir1 = e1->start;
 21.1451 +					child_md->dir2 = 0;
 21.1452 +				}
 21.1453 +			}
 21.1454 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 21.1455 +				e1 = NULL;
 21.1456 +		} else if (cmp > 0) {
 21.1457 +			if (map2[e2 - root2]) {
 21.1458 +				map2[e2 - root2] = last =
 21.1459 +					add_file(merger, &pool2[e2->name]);
 21.1460 +				if (e2->start) {
 21.1461 +					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 21.1462 +					child_md->merged = last;
 21.1463 +					child_md->dir1 = 0;
 21.1464 +					child_md->dir2 = e2->start;
 21.1465 +				}
 21.1466 +			}
 21.1467 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 21.1468 +				e2 = NULL;
 21.1469 +		} else {
 21.1470 +			map1[e1 - root1] = map2[e2- root2] = last =
 21.1471 +				add_file(merger, &pool1[e1->name]);
 21.1472 +			if (e1->start || e2->start) {
 21.1473 +				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 21.1474 +				child_md->merged = last;
 21.1475 +				child_md->dir1 = e1->start;
 21.1476 +				child_md->dir2 = e2->start;
 21.1477 +			}
 21.1478 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 21.1479 +				e1 = NULL;
 21.1480 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 21.1481 +				e2 = NULL;
 21.1482 +		}
 21.1483 +	}
 21.1484 +
 21.1485 +	mroot = (struct razor_entry *)merger->set->files.data;
 21.1486 +	if (last) {
 21.1487 +		mroot[last].flags = RAZOR_ENTRY_LAST;
 21.1488 +		mroot[md->merged].start = start;
 21.1489 +	} else
 21.1490 +		mroot[md->merged].start = 0;
 21.1491 +
 21.1492 +	end_md = merge_stack.data + merge_stack.size;
 21.1493 +	for (child_md = merge_stack.data; child_md < end_md; child_md++)
 21.1494 +		merge_one_directory(merger, child_md);
 21.1495 +	array_release(&merge_stack);
 21.1496 +}
 21.1497 +
 21.1498 +static void
 21.1499 +merge_files(struct razor_merger *merger)
 21.1500 +{
 21.1501 +	struct razor_entry *root;
 21.1502 +	struct merge_directory md;
 21.1503 +	uint32_t *map1, *map2;
 21.1504 +
 21.1505 +	map1 = merger->source1.file_map;
 21.1506 +	map2 = merger->source2.file_map;
 21.1507 +
 21.1508 +	md.merged = 0;
 21.1509 +
 21.1510 +	if (merger->source1.set->files.size) {
 21.1511 +		root = (struct razor_entry *) merger->source1.set->files.data;
 21.1512 +		if (root->start)
 21.1513 +			fix_file_map(map1, root, root);
 21.1514 +		md.dir1 = root->start;
 21.1515 +	} else
 21.1516 +		md.dir1 = 0;
 21.1517 +
 21.1518 +	if (merger->source2.set->files.size) {
 21.1519 +		root = (struct razor_entry *) merger->source2.set->files.data;
 21.1520 +		if (root->start)
 21.1521 +			fix_file_map(map2, root, root);
 21.1522 +		md.dir2 = root->start;
 21.1523 +	} else
 21.1524 +		md.dir2 = 0;
 21.1525 +
 21.1526 +	merge_one_directory(merger, &md);
 21.1527 +}
 21.1528 +
 21.1529 +static void
 21.1530 +emit_files(struct list_head *files, struct array *source_pool,
 21.1531 +	   uint32_t *map, struct array *pool)
 21.1532 +{
 21.1533 +	uint32_t r;
 21.1534 +	struct list *p, *q;
 21.1535 +
 21.1536 +	r = pool->size / sizeof *q;
 21.1537 +	p = list_first(files, source_pool);
 21.1538 +	while (p) {
 21.1539 +		q = array_add(pool, sizeof *q);
 21.1540 +		q->data = map[p->data];
 21.1541 +		q->flags = p->flags;
 21.1542 +		p = list_next(p);
 21.1543 +	}
 21.1544 +
 21.1545 +	list_set_ptr(files, r);
 21.1546 +}
 21.1547 +
 21.1548 +/* Rebuild property->packages maps.  We can't just remap these, as a
 21.1549 + * property may have lost or gained a number of packages.  Allocate an
 21.1550 + * array per property and loop through the packages and add them to
 21.1551 + * the arrays for their properties. */
 21.1552 +static void
 21.1553 +rebuild_property_package_lists(struct razor_set *set)
 21.1554 +{
 21.1555 +	struct array *pkgs, *a;
 21.1556 +	struct razor_package *pkg, *pkg_end;
 21.1557 +	struct razor_property *prop, *prop_end;
 21.1558 +	struct list *r;
 21.1559 +	uint32_t *q;
 21.1560 +	int count;
 21.1561 +
 21.1562 +	count = set->properties.size / sizeof (struct razor_property);
 21.1563 +	pkgs = zalloc(count * sizeof *pkgs);
 21.1564 +	pkg_end = set->packages.data + set->packages.size;
 21.1565 +
 21.1566 +	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
 21.1567 +		r = list_first(&pkg->properties, &set->property_pool);
 21.1568 +		while (r) {
 21.1569 +			q = array_add(&pkgs[r->data], sizeof *q);
 21.1570 +			*q = pkg - (struct razor_package *) set->packages.data;
 21.1571 +			r = list_next(r);
 21.1572 +		}
 21.1573 +	}
 21.1574 +
 21.1575 +	prop_end = set->properties.data + set->properties.size;
 21.1576 +	a = pkgs;
 21.1577 +	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
 21.1578 +		list_set_array(&prop->packages, &set->package_pool, a, 0);
 21.1579 +		array_release(a);
 21.1580 +	}
 21.1581 +	free(pkgs);
 21.1582 +}
 21.1583 +
 21.1584 +static void
 21.1585 +rebuild_file_package_lists(struct razor_set *set)
 21.1586 +{
 21.1587 +	struct array *pkgs, *a;
 21.1588 +	struct razor_package *pkg, *pkg_end;
 21.1589 +	struct razor_entry *entry, *entry_end;
 21.1590 +	struct list *r;
 21.1591 +	uint32_t *q;
 21.1592 +	int count;
 21.1593 +
 21.1594 +	count = set->files.size / sizeof (struct razor_entry);
 21.1595 +	pkgs = zalloc(count * sizeof *pkgs);
 21.1596 +	pkg_end = set->packages.data + set->packages.size;
 21.1597 +
 21.1598 +	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
 21.1599 +		r = list_first(&pkg->files, &set->file_pool);
 21.1600 +		while (r) {
 21.1601 +			q = array_add(&pkgs[r->data], sizeof *q);
 21.1602 +			*q = pkg - (struct razor_package *) set->packages.data;
 21.1603 +			r = list_next(r);
 21.1604 +		}
 21.1605 +	}
 21.1606 +
 21.1607 +	entry_end = set->files.data + set->files.size;
 21.1608 +	a = pkgs;
 21.1609 +	for (entry = set->files.data; entry < entry_end; entry++, a++) {
 21.1610 +		list_set_array(&entry->packages, &set->package_pool, a, 0);
 21.1611 +		array_release(a);
 21.1612 +	}
 21.1613 +	free(pkgs);
 21.1614 +}
 21.1615 +
 21.1616 +static struct razor_set *
 21.1617 +razor_merger_finish(struct razor_merger *merger)
 21.1618 +{
 21.1619 +	struct razor_set *result;
 21.1620 +	struct razor_package *p, *pend;
 21.1621 +
 21.1622 +	/* As we built the package list, we filled out a bitvector of
 21.1623 +	 * the properties that are referenced by the packages in the
 21.1624 +	 * new set.  Now we do a parallel loop through the properties
 21.1625 +	 * and emit those marked in the bit vector to the new set.  In
 21.1626 +	 * the process, we update the bit vector to actually map from
 21.1627 +	 * indices in the old property list to indices in the new
 21.1628 +	 * property list for both sets. */
 21.1629 +
 21.1630 +	merge_properties(merger);
 21.1631 +	merge_files(merger);
 21.1632 +
 21.1633 +	/* Now we loop through the packages again and emit the
 21.1634 +	 * property lists, remapped to point to the new properties. */
 21.1635 +
 21.1636 +	pend = merger->set->packages.data + merger->set->packages.size;
 21.1637 +	for (p = merger->set->packages.data; p < pend; p++) {
 21.1638 +		struct source *src;
 21.1639 +
 21.1640 +		if (p->flags & UPSTREAM_SOURCE)
 21.1641 +			src = &merger->source2;
 21.1642 +		else
 21.1643 +			src = &merger->source1;
 21.1644 +
 21.1645 +		emit_properties(&p->properties,
 21.1646 +				&src->set->property_pool,
 21.1647 +				src->property_map,
 21.1648 +				&merger->set->property_pool);
 21.1649 +		emit_files(&p->files,
 21.1650 +			   &src->set->file_pool,
 21.1651 +			   src->file_map,
 21.1652 +			   &merger->set->file_pool);
 21.1653 +		p->flags &= ~UPSTREAM_SOURCE;
 21.1654 +	}
 21.1655 +
 21.1656 +	rebuild_property_package_lists(merger->set);
 21.1657 +	rebuild_file_package_lists(merger->set);
 21.1658 +
 21.1659 +	result = merger->set;
 21.1660 +	hashtable_release(&merger->table);
 21.1661 +	free(merger);
 21.1662 +
 21.1663 +	return result;
 21.1664 +}
 21.1665 +
 21.1666 +/* The diff order matters.  We should sort the packages so that a
 21.1667 + * REMOVE of a package comes before the INSTALL, and so that all
 21.1668 + * requires for a package have been installed before the package.
 21.1669 + **/
 21.1670 +
 21.1671 +void
 21.1672 +razor_set_diff(struct razor_set *set, struct razor_set *upstream,
 21.1673 +	       razor_package_callback_t callback, void *data)
 21.1674 +{
 21.1675 + 	struct razor_package_iterator *pi1, *pi2;
 21.1676 + 	struct razor_package *p1, *p2;
 21.1677 +	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
 21.1678 +	int res;
 21.1679 +
 21.1680 +	pi1 = razor_package_iterator_create(set);
 21.1681 +	pi2 = razor_package_iterator_create(upstream);
 21.1682 +
 21.1683 +	razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
 21.1684 +	razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
 21.1685 +
 21.1686 +	while (p1 || p2) {
 21.1687 +		if (p1 && p2) {
 21.1688 +			res = strcmp(name1, name2);
 21.1689 +			if (res == 0)
 21.1690 +				res = versioncmp(version1, version2);
 21.1691 +		} else {
 21.1692 +			res = 0;
 21.1693 +		}
 21.1694 +
 21.1695 +		if (p2 == NULL || res < 0)
 21.1696 +			callback(name1, version1, NULL, arch1, data);
 21.1697 +		else if (p1 == NULL || res > 0)
 21.1698 +			callback(name2, NULL, version2, arch2, data);
 21.1699 +
 21.1700 +		if (p1 != NULL && res <= 0)
 21.1701 +			razor_package_iterator_next(pi1, &p1,
 21.1702 +						    &name1, &version1, &arch1);
 21.1703 +		if (p2 != NULL && res >= 0)
 21.1704 +			razor_package_iterator_next(pi2, &p2,
 21.1705 +						    &name2, &version2, &arch2);
 21.1706 +	}
 21.1707 +
 21.1708 +	razor_package_iterator_destroy(pi1);
 21.1709 +	razor_package_iterator_destroy(pi2);
 21.1710 +}
 21.1711 +
 21.1712 +static int
 21.1713 +provider_satisfies_requirement(struct razor_property *provider,
 21.1714 +			       const char *provider_strings,
 21.1715 +			       enum razor_version_relation relation,
 21.1716 +			       const char *required)
 21.1717 +{
 21.1718 +	int cmp, len;
 21.1719 +	const char *provided = &provider_strings[provider->version];
 21.1720 +
 21.1721 +	if (!*required)
 21.1722 +		return 1;
 21.1723 +	if (!*provided) {
 21.1724 +		if (relation >= RAZOR_VERSION_EQUAL)
 21.1725 +			return 1;
 21.1726 +		else
 21.1727 +			return 0;
 21.1728 +	}
 21.1729 +
 21.1730 +	cmp = versioncmp(provided, required);
 21.1731 +
 21.1732 +	switch (relation) {
 21.1733 +	case RAZOR_VERSION_LESS:
 21.1734 +		return cmp < 0;
 21.1735 +
 21.1736 +	case RAZOR_VERSION_LESS_OR_EQUAL:
 21.1737 +		if (cmp <= 0)
 21.1738 +			return 1;
 21.1739 +		/* fall through: FIXME, make sure this is correct */
 21.1740 +
 21.1741 +	case RAZOR_VERSION_EQUAL:
 21.1742 +		if (cmp == 0)
 21.1743 +			return 1;
 21.1744 +
 21.1745 +		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
 21.1746 +		len = strlen(required);
 21.1747 +		if (!strncmp(required, provided, len) && provided[len] == '-')
 21.1748 +			return 1;
 21.1749 +		return 0;
 21.1750 +
 21.1751 +	case RAZOR_VERSION_GREATER_OR_EQUAL:
 21.1752 +		return cmp >= 0;
 21.1753 +
 21.1754 +	case RAZOR_VERSION_GREATER:
 21.1755 +		return cmp > 0;
 21.1756 +	}
 21.1757 +
 21.1758 +	/* shouldn't happen */
 21.1759 +	return 0;
 21.1760 +}
 21.1761 +
 21.1762 +#define TRANS_PACKAGE_PRESENT		1
 21.1763 +#define TRANS_PACKAGE_UPDATE		2
 21.1764 +#define TRANS_PROPERTY_SATISFIED	0x80000000
 21.1765 +
 21.1766 +struct transaction_set {
 21.1767 +	struct razor_set *set;
 21.1768 +	uint32_t *packages;
 21.1769 +	uint32_t *properties;
 21.1770 +};
 21.1771 +
 21.1772 +struct razor_transaction {
 21.1773 +	int package_count, errors;
 21.1774 +	struct transaction_set system, upstream;
 21.1775 +	int changes;
 21.1776 +};
 21.1777 +
 21.1778 +static void
 21.1779 +transaction_set_init(struct transaction_set *ts, struct razor_set *set)
 21.1780 +{
 21.1781 +	int count;
 21.1782 +
 21.1783 +	ts->set = set;
 21.1784 +	count = set->packages.size / sizeof (struct razor_package);
 21.1785 +	ts->packages = zalloc(count * sizeof *ts->packages);
 21.1786 +	count = set->properties.size / sizeof (struct razor_property);
 21.1787 +	ts->properties = zalloc(count * sizeof *ts->properties);
 21.1788 +}
 21.1789 +
 21.1790 +static void
 21.1791 +transaction_set_release(struct transaction_set *ts)
 21.1792 +{
 21.1793 +	free(ts->packages);
 21.1794 +	free(ts->properties);
 21.1795 +}
 21.1796 +
 21.1797 +static void
 21.1798 +transaction_set_install_package(struct transaction_set *ts,
 21.1799 +				struct razor_package *package)
 21.1800 +{
 21.1801 +	struct razor_package *pkgs;
 21.1802 +	struct list *prop;
 21.1803 +	int i;
 21.1804 +
 21.1805 +	pkgs = ts->set->packages.data;
 21.1806 +	i = package - pkgs;
 21.1807 +	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
 21.1808 +		return;
 21.1809 +
 21.1810 +	ts->packages[i] = TRANS_PACKAGE_PRESENT;
 21.1811 +
 21.1812 +	prop = list_first(&package->properties, &ts->set->property_pool);
 21.1813 +	while (prop) {
 21.1814 +		ts->properties[prop->data]++;
 21.1815 +		prop = list_next(prop);
 21.1816 +	}
 21.1817 +}
 21.1818 +
 21.1819 +static void
 21.1820 +transaction_set_remove_package(struct transaction_set *ts,
 21.1821 +			       struct razor_package *package)
 21.1822 +{
 21.1823 +	struct razor_package *pkgs;
 21.1824 +	struct list *prop;
 21.1825 +	int i;
 21.1826 +
 21.1827 +	pkgs = ts->set->packages.data;
 21.1828 +	i = package - pkgs;
 21.1829 +	if (ts->packages[i] == 0)
 21.1830 +		return;
 21.1831 +
 21.1832 +	ts->packages[i] = 0;
 21.1833 +
 21.1834 +	prop = list_first(&package->properties, &ts->set->property_pool);
 21.1835 +	while (prop) {
 21.1836 +		ts->properties[prop->data]--;
 21.1837 +		prop = list_next(prop);
 21.1838 +	}
 21.1839 +}
 21.1840 +
 21.1841 +struct razor_transaction *
 21.1842 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
 21.1843 +{
 21.1844 +	struct razor_transaction *trans;
 21.1845 +	struct razor_package *p, *spkgs, *pend;
 21.1846 +
 21.1847 +	trans = zalloc(sizeof *trans);
 21.1848 +	transaction_set_init(&trans->system, system);
 21.1849 +	transaction_set_init(&trans->upstream, upstream);
 21.1850 +
 21.1851 +	spkgs = trans->system.set->packages.data;
 21.1852 +	pend = trans->system.set->packages.data +
 21.1853 +		trans->system.set->packages.size;
 21.1854 +	for (p = spkgs; p < pend; p++)
 21.1855 +		transaction_set_install_package(&trans->system, p);
 21.1856 +
 21.1857 +	return trans;
 21.1858 +}
 21.1859 +
 21.1860 +void
 21.1861 +razor_transaction_install_package(struct razor_transaction *trans,
 21.1862 +				  struct razor_package *package)
 21.1863 +{
 21.1864 +	transaction_set_install_package(&trans->upstream, package);
 21.1865 +	trans->changes++;
 21.1866 +}
 21.1867 +
 21.1868 +void
 21.1869 +razor_transaction_remove_package(struct razor_transaction *trans,
 21.1870 +				 struct razor_package *package)
 21.1871 +{
 21.1872 +	transaction_set_remove_package(&trans->system, package);
 21.1873 +	trans->changes++;
 21.1874 +}
 21.1875 +
 21.1876 +void
 21.1877 +razor_transaction_update_package(struct razor_transaction *trans,
 21.1878 +				  struct razor_package *package)
 21.1879 +{
 21.1880 +	struct razor_package *spkgs, *upkgs, *end;
 21.1881 +
 21.1882 +	spkgs = trans->system.set->packages.data;
 21.1883 +	upkgs = trans->upstream.set->packages.data;
 21.1884 +	end = trans->system.set->packages.data +
 21.1885 +		trans->system.set->packages.size;
 21.1886 +	if (spkgs <= package && package < end)
 21.1887 +		trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
 21.1888 +	else
 21.1889 +		trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
 21.1890 +}
 21.1891 +
 21.1892 +struct prop_iter {
 21.1893 +	struct razor_property *p, *start, *end;
 21.1894 +	const char *pool;
 21.1895 +	uint32_t *present;
 21.1896 +};
 21.1897 +
 21.1898 +static void
 21.1899 +prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
 21.1900 +{
 21.1901 +	pi->p = ts->set->properties.data;
 21.1902 +	pi->start = ts->set->properties.data;
 21.1903 +	pi->end = ts->set->properties.data + ts->set->properties.size;
 21.1904 +	pi->pool = ts->set->string_pool.data;
 21.1905 +	pi->present = ts->properties;
 21.1906 +}
 21.1907 +
 21.1908 +static int
 21.1909 +prop_iter_next(struct prop_iter *pi,
 21.1910 +	       enum razor_property_type type, struct razor_property **p)
 21.1911 +{
 21.1912 +	while (pi->p < pi->end) {
 21.1913 +		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
 21.1914 +		    pi->p->type == type) {
 21.1915 +			*p = pi->p++;
 21.1916 +			return 1;
 21.1917 +		}
 21.1918 +		pi->p++;
 21.1919 +	}
 21.1920 +
 21.1921 +	return 0;
 21.1922 +}
 21.1923 +
 21.1924 +static struct razor_property *
 21.1925 +prop_iter_seek_to(struct prop_iter *pi,
 21.1926 +		  enum razor_property_type type, const char *match)
 21.1927 +{
 21.1928 +	uint32_t name;
 21.1929 +
 21.1930 +	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
 21.1931 +		pi->p++;
 21.1932 +
 21.1933 +	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
 21.1934 +		return NULL;
 21.1935 +
 21.1936 +	name = pi->p->name;
 21.1937 +	while (pi->p < pi->end &&
 21.1938 +	       pi->p->name == name &&
 21.1939 +	       pi->p->type != type)
 21.1940 +		pi->p++;
 21.1941 +
 21.1942 +	if (pi->p == pi->end || pi->p->name != name)
 21.1943 +		return NULL;
 21.1944 +
 21.1945 +	return pi->p;
 21.1946 +}
 21.1947 +
 21.1948 +/* Remove packages from set that provide any of the matching (same
 21.1949 + * name and type) providers from ppi onwards that match the
 21.1950 + * requirement that rpi points to. */
 21.1951 +static void
 21.1952 +remove_matching_providers(struct razor_transaction *trans,
 21.1953 +			  struct prop_iter *ppi,
 21.1954 +			  enum razor_version_relation relation,
 21.1955 +			  const char *version)
 21.1956 +{
 21.1957 +	struct razor_property *p;
 21.1958 +	struct razor_package *pkg, *pkgs;
 21.1959 +	struct razor_package_iterator pkg_iter;
 21.1960 +	struct razor_set *set;
 21.1961 +	const char *n, *v, *a;
 21.1962 +
 21.1963 +	if (ppi->present == trans->system.properties)
 21.1964 +		set = trans->system.set;
 21.1965 +	else
 21.1966 +		set = trans->upstream.set;
 21.1967 +
 21.1968 +	pkgs = (struct razor_package *) set->packages.data;
 21.1969 +	for (p = ppi->p;
 21.1970 +	     p < ppi->end &&
 21.1971 +	     p->name == ppi->p->name &&
 21.1972 +	     p->type == ppi->p->type;
 21.1973 +	     p++) {
 21.1974 +		if (!ppi->present[p - ppi->start])
 21.1975 +			continue;
 21.1976 +		if (!provider_satisfies_requirement(p, ppi->pool,
 21.1977 +						    relation, version))
 21.1978 +			continue;
 21.1979 +
 21.1980 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
 21.1981 +		while (razor_package_iterator_next(&pkg_iter,
 21.1982 +						   &pkg, &n, &v, &a)) {
 21.1983 +			fprintf(stderr, "removing %s-%s\n", n, v);
 21.1984 +			razor_transaction_remove_package(trans, pkg);
 21.1985 +		}
 21.1986 +	}
 21.1987 +}
 21.1988 +
 21.1989 +static void
 21.1990 +flag_matching_providers(struct razor_transaction *trans,
 21.1991 +			struct prop_iter *ppi,
 21.1992 +			struct razor_property *r,
 21.1993 +			struct prop_iter *rpi,
 21.1994 +			unsigned int flag)
 21.1995 +{
 21.1996 +	struct razor_property *p;
 21.1997 +	struct razor_package *pkg, *pkgs;
 21.1998 +	struct razor_package_iterator pkg_iter;
 21.1999 +	struct razor_set *set;
 21.2000 +	const char *name, *version, *arch;
 21.2001 +	uint32_t *flags;
 21.2002 +
 21.2003 +	if (ppi->present == trans->system.properties) {
 21.2004 +		set = trans->system.set;
 21.2005 +		flags = trans->system.packages;
 21.2006 +	} else {
 21.2007 +		set = trans->upstream.set;
 21.2008 +		flags = trans->upstream.packages;
 21.2009 +	}
 21.2010 +
 21.2011 +	pkgs = (struct razor_package *) set->packages.data;
 21.2012 +	for (p = ppi->p;
 21.2013 +	     p < ppi->end &&
 21.2014 +		     p->name == ppi->p->name &&
 21.2015 +		     p->type == ppi->p->type;
 21.2016 +	     p++) {
 21.2017 +		if (!ppi->present[p - ppi->start])
 21.2018 +			continue;
 21.2019 +		if (!provider_satisfies_requirement(p, ppi->pool,
 21.2020 +						    r->relation,
 21.2021 +						    &rpi->pool[r->version]))
 21.2022 +			continue;
 21.2023 +
 21.2024 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
 21.2025 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
 21.2026 +						   &name, &version, &arch)) {
 21.2027 +
 21.2028 +			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
 21.2029 +				name, version,
 21.2030 +				ppi->pool + p->name,
 21.2031 +				rpi->pool + r->name,
 21.2032 +				rpi->pool + r->version);
 21.2033 +			flags[pkg - pkgs] |= flag;
 21.2034 +		}
 21.2035 +	}
 21.2036 +}
 21.2037 +
 21.2038 +static struct razor_package *
 21.2039 +pick_matching_provider(struct razor_set *set,
 21.2040 +		       struct prop_iter *ppi,
 21.2041 +		       enum razor_version_relation relation,
 21.2042 +		       const char *version)
 21.2043 +{
 21.2044 +	struct razor_property *p;
 21.2045 +	struct razor_package *pkgs;
 21.2046 +	struct list *i;
 21.2047 +
 21.2048 +	/* This is where we decide which pkgs to pull in to satisfy a
 21.2049 +	 * requirement.  There may be several different providers
 21.2050 +	 * (different versions) and each version of a provider may
 21.2051 +	 * come from a number of packages.  We pick the first package
 21.2052 +	 * from the first provider that matches. */
 21.2053 +
 21.2054 +	pkgs = set->packages.data;
 21.2055 +	for (p = ppi->p;
 21.2056 +	     p < ppi->end &&
 21.2057 +		     p->name == ppi->p->name &&
 21.2058 +		     p->type == ppi->p->type &&
 21.2059 +		     ppi->present[p - ppi->start] == 0;
 21.2060 +	     p++) {
 21.2061 +		if (!provider_satisfies_requirement(p, ppi->pool,
 21.2062 +						    relation, version))
 21.2063 +			continue;
 21.2064 +
 21.2065 +		i = list_first(&p->packages, &set->package_pool);
 21.2066 +
 21.2067 +		return &pkgs[i->data];
 21.2068 +	}
 21.2069 +
 21.2070 +	return NULL;
 21.2071 +}
 21.2072 +
 21.2073 +static void
 21.2074 +remove_obsoleted_packages(struct razor_transaction *trans)
 21.2075 +{
 21.2076 +	struct razor_property *up;
 21.2077 +	struct razor_package *spkgs;
 21.2078 +	struct prop_iter spi, upi;
 21.2079 +
 21.2080 +	spkgs = trans->system.set->packages.data;
 21.2081 +	prop_iter_init(&spi, &trans->system);
 21.2082 +	prop_iter_init(&upi, &trans->upstream);
 21.2083 +
 21.2084 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
 21.2085 +		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
 21.2086 +				       &upi.pool[up->name]))
 21.2087 +			continue;
 21.2088 +		remove_matching_providers(trans, &spi, up->relation,
 21.2089 +					  &upi.pool[up->version]);
 21.2090 +	}
 21.2091 +}
 21.2092 +
 21.2093 +static int
 21.2094 +any_provider_satisfies_requirement(struct prop_iter *ppi,
 21.2095 +				   enum razor_version_relation relation,
 21.2096 +				   const char *version)
 21.2097 +{
 21.2098 +	struct razor_property *p;
 21.2099 +
 21.2100 +	for (p = ppi->p;
 21.2101 +	     p < ppi->end &&
 21.2102 +		     p->name == ppi->p->name &&
 21.2103 +		     p->type == ppi->p->type;
 21.2104 +	     p++) {
 21.2105 +		if (ppi->present[p - ppi->start] > 0 &&
 21.2106 +		    provider_satisfies_requirement(p, ppi->pool,
 21.2107 +						   relation, version))
 21.2108 +			return 1;
 21.2109 +	}
 21.2110 +
 21.2111 +	return 0;
 21.2112 +}
 21.2113 +
 21.2114 +static void
 21.2115 +clear_requires_flags(struct transaction_set *ts)
 21.2116 +{
 21.2117 +	struct razor_property *p;
 21.2118 +	const char *pool;
 21.2119 +	int i, count;
 21.2120 +
 21.2121 +	count = ts->set->properties.size / sizeof *p;
 21.2122 +	p = ts->set->properties.data;
 21.2123 +	pool = ts->set->string_pool.data;
 21.2124 +	for (i = 0; i < count; i++) {
 21.2125 +		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
 21.2126 +		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
 21.2127 +			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
 21.2128 +	}
 21.2129 +}
 21.2130 +
 21.2131 +static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
 21.2132 +
 21.2133 +static void
 21.2134 +mark_satisfied_requires(struct razor_transaction *trans,
 21.2135 +			struct transaction_set *rts,
 21.2136 +			struct transaction_set *pts)
 21.2137 +{
 21.2138 +	struct prop_iter rpi, ppi;
 21.2139 +	struct razor_property *rp;
 21.2140 +
 21.2141 +	prop_iter_init(&rpi, rts);
 21.2142 +	prop_iter_init(&ppi, pts);
 21.2143 +
 21.2144 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 21.2145 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
 21.2146 +				       &rpi.pool[rp->name]))
 21.2147 +			continue;
 21.2148 +
 21.2149 +		if (any_provider_satisfies_requirement(&ppi, rp->relation,
 21.2150 +						       &rpi.pool[rp->version]))
 21.2151 +			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
 21.2152 +	}
 21.2153 +}
 21.2154 +
 21.2155 +static void
 21.2156 +mark_all_satisfied_requires(struct razor_transaction *trans)
 21.2157 +{
 21.2158 +	clear_requires_flags(&trans->system);
 21.2159 +	clear_requires_flags(&trans->upstream);
 21.2160 +	mark_satisfied_requires(trans, &trans->system, &trans->system);
 21.2161 +	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
 21.2162 +	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
 21.2163 +	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
 21.2164 +}
 21.2165 +
 21.2166 +static void
 21.2167 +update_unsatisfied_packages(struct razor_transaction *trans)
 21.2168 +{
 21.2169 +	struct razor_package *spkgs, *pkg;
 21.2170 +	struct razor_property *sp;
 21.2171 +	struct prop_iter spi;
 21.2172 +	struct razor_package_iterator pkg_iter;
 21.2173 +	const char *name, *version, *arch;
 21.2174 +
 21.2175 +	spkgs = trans->system.set->packages.data;
 21.2176 +	prop_iter_init(&spi, &trans->system);
 21.2177 +
 21.2178 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
 21.2179 +		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
 21.2180 +			continue;
 21.2181 +
 21.2182 +		razor_package_iterator_init_for_property(&pkg_iter,
 21.2183 +							 trans->system.set,
 21.2184 +							 sp);
 21.2185 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
 21.2186 +						   &name, &version, &arch)) {
 21.2187 +			fprintf(stderr, "updating %s because %s %s %s "
 21.2188 +				"isn't satisfied\n",
 21.2189 +				name, spi.pool + sp->name,
 21.2190 +				relation_string[sp->relation],
 21.2191 +				spi.pool + sp->version);
 21.2192 +			trans->system.packages[pkg - spkgs] |=
 21.2193 +				TRANS_PACKAGE_UPDATE;
 21.2194 +		}
 21.2195 +	}
 21.2196 +}
 21.2197 +
 21.2198 +void
 21.2199 +razor_transaction_update_all(struct razor_transaction *trans)
 21.2200 +{
 21.2201 +	struct razor_package *p;
 21.2202 +	int i, count;
 21.2203 +
 21.2204 +	count = trans->system.set->packages.size / sizeof *p;
 21.2205 +	for (i = 0; i < count; i++)
 21.2206 +		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
 21.2207 +}
 21.2208 +
 21.2209 +static void
 21.2210 +update_conflicted_packages(struct razor_transaction *trans)
 21.2211 +{
 21.2212 +	struct razor_package *pkg, *spkgs;
 21.2213 +	struct razor_property *up, *sp;
 21.2214 +	struct prop_iter spi, upi;
 21.2215 +	struct razor_package_iterator pkg_iter;
 21.2216 +	const char *name, *version, *arch;
 21.2217 +
 21.2218 +	spkgs = trans->system.set->packages.data;
 21.2219 +	prop_iter_init(&spi, &trans->system);
 21.2220 +	prop_iter_init(&upi, &trans->upstream);
 21.2221 +
 21.2222 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
 21.2223 +		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
 21.2224 +				       &spi.pool[sp->name]))
 21.2225 +			continue;
 21.2226 +
 21.2227 +		if (!any_provider_satisfies_requirement(&upi, sp->relation,
 21.2228 +							&spi.pool[sp->version]))
 21.2229 +			continue;
 21.2230 +
 21.2231 +		razor_package_iterator_init_for_property(&pkg_iter,
 21.2232 +							 trans->system.set,
 21.2233 +							 sp);
 21.2234 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
 21.2235 +						   &name, &version, &arch)) {
 21.2236 +			fprintf(stderr, "updating %s %s because it conflicts with %s",
 21.2237 +				name, version, spi.pool + sp->name);
 21.2238 +			trans->system.packages[pkg - spkgs] |=
 21.2239 +				TRANS_PACKAGE_UPDATE;
 21.2240 +		}
 21.2241 +	}
 21.2242 +
 21.2243 +	prop_iter_init(&spi, &trans->system);
 21.2244 +	prop_iter_init(&upi, &trans->upstream);
 21.2245 +
 21.2246 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
 21.2247 +		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
 21.2248 +				       &upi.pool[upi.p->name]);
 21.2249 +
 21.2250 +		if (sp)
 21.2251 +			flag_matching_providers(trans, &spi, up, &upi,
 21.2252 +						TRANS_PACKAGE_UPDATE);
 21.2253 +	}
 21.2254 +}
 21.2255 +
 21.2256 +static void
 21.2257 +pull_in_requirements(struct razor_transaction *trans,
 21.2258 +		     struct prop_iter *rpi, struct prop_iter *ppi)
 21.2259 +{
 21.2260 +	struct razor_property *rp, *pp;
 21.2261 +	struct razor_package *pkg, *upkgs;
 21.2262 +
 21.2263 +	upkgs = trans->upstream.set->packages.data;
 21.2264 +	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 21.2265 +		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
 21.2266 +			continue;
 21.2267 +
 21.2268 +		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
 21.2269 +				       &rpi->pool[rp->name]);
 21.2270 +		if (pp == NULL)
 21.2271 +			continue;
 21.2272 +		pkg = pick_matching_provider(trans->upstream.set,
 21.2273 +					     ppi, rp->relation,
 21.2274 +					     &rpi->pool[rp->version]);
 21.2275 +		if (pkg == NULL)
 21.2276 +			continue;
 21.2277 +
 21.2278 +		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
 21.2279 +
 21.2280 +		fprintf(stderr, "pulling in %s which provides %s %s %s "
 21.2281 +			"to satisfy %s %s %s\n",
 21.2282 +			ppi->pool + pkg->name,
 21.2283 +			ppi->pool + pp->name,
 21.2284 +			relation_string[pp->relation],
 21.2285 +			ppi->pool + pp->version,
 21.2286 +			&rpi->pool[rp->name],
 21.2287 +			relation_string[rp->relation],
 21.2288 +			&rpi->pool[rp->version]);
 21.2289 +
 21.2290 +		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
 21.2291 +	}
 21.2292 +}
 21.2293 +
 21.2294 +static void
 21.2295 +pull_in_all_requirements(struct razor_transaction *trans)
 21.2296 +{
 21.2297 +	struct prop_iter rpi, ppi;
 21.2298 +
 21.2299 +	prop_iter_init(&rpi, &trans->system);
 21.2300 +	prop_iter_init(&ppi, &trans->upstream);
 21.2301 +	pull_in_requirements(trans, &rpi, &ppi);
 21.2302 +
 21.2303 +	prop_iter_init(&rpi, &trans->upstream);
 21.2304 +	prop_iter_init(&ppi, &trans->upstream);
 21.2305 +	pull_in_requirements(trans, &rpi, &ppi);
 21.2306 +}
 21.2307 +
 21.2308 +static void
 21.2309 +flush_scheduled_system_updates(struct razor_transaction *trans)
 21.2310 +{
 21.2311 + 	struct razor_package_iterator *pi;
 21.2312 + 	struct razor_package *p, *pkg, *spkgs;
 21.2313 +	struct prop_iter ppi;
 21.2314 +	const char *name, *version, *arch;
 21.2315 +
 21.2316 +	spkgs = trans->system.set->packages.data;
 21.2317 +	pi = razor_package_iterator_create(trans->system.set);
 21.2318 +	prop_iter_init(&ppi, &trans->upstream);
 21.2319 +
 21.2320 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 21.2321 +		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
 21.2322 +			continue;
 21.2323 +
 21.2324 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
 21.2325 +			continue;
 21.2326 +
 21.2327 +		pkg = pick_matching_provider(trans->upstream.set, &ppi,
 21.2328 +					     RAZOR_VERSION_GREATER, version);
 21.2329 +		if (pkg == NULL)
 21.2330 +			continue;
 21.2331 +
 21.2332 +		fprintf(stderr, "updating %s-%s to %s-%s\n",
 21.2333 +			name, version,
 21.2334 +			&ppi.pool[pkg->name], &ppi.pool[pkg->version]);
 21.2335 +
 21.2336 +		razor_transaction_remove_package(trans, p);
 21.2337 +		razor_transaction_install_package(trans, pkg);
 21.2338 +	}
 21.2339 +
 21.2340 +	razor_package_iterator_destroy(pi);
 21.2341 +}
 21.2342 +
 21.2343 +static void
 21.2344 +flush_scheduled_upstream_updates(struct razor_transaction *trans)
 21.2345 +{
 21.2346 + 	struct razor_package_iterator *pi;
 21.2347 + 	struct razor_package *p, *upkgs;
 21.2348 +	struct prop_iter spi;
 21.2349 +	const char *name, *version, *arch;
 21.2350 +
 21.2351 +	upkgs = trans->upstream.set->packages.data;
 21.2352 +	pi = razor_package_iterator_create(trans->upstream.set);
 21.2353 +	prop_iter_init(&spi, &trans->system);
 21.2354 +
 21.2355 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 21.2356 +		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
 21.2357 +			continue;
 21.2358 +
 21.2359 +		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
 21.2360 +			continue;
 21.2361 +		remove_matching_providers(trans, &spi,
 21.2362 +					  RAZOR_VERSION_LESS, version);
 21.2363 +		razor_transaction_install_package(trans, p);
 21.2364 +		fprintf(stderr, "installing %s-%s\n", name, version);
 21.2365 +	}
 21.2366 +}
 21.2367 +
 21.2368 +int
 21.2369 +razor_transaction_resolve(struct razor_transaction *trans)
 21.2370 +{
 21.2371 +	int last = 0;
 21.2372 +
 21.2373 +	flush_scheduled_system_updates(trans);
 21.2374 +
 21.2375 +	while (last < trans->changes) {
 21.2376 +		last = trans->changes;
 21.2377 +		remove_obsoleted_packages(trans);
 21.2378 +		mark_all_satisfied_requires(trans);
 21.2379 +		update_unsatisfied_packages(trans);
 21.2380 +		update_conflicted_packages(trans);
 21.2381 +		pull_in_all_requirements(trans);
 21.2382 +		flush_scheduled_system_updates(trans);
 21.2383 +		flush_scheduled_upstream_updates(trans);
 21.2384 +	}
 21.2385 +
 21.2386 +	return trans->changes;
 21.2387 +}
 21.2388 +
 21.2389 +static void
 21.2390 +describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
 21.2391 +{
 21.2392 +	struct razor_package_iterator pi;
 21.2393 +	struct razor_package *pkg;
 21.2394 +	const char *name, *version, *arch, *pool;
 21.2395 +
 21.2396 +	pool = set->string_pool.data;
 21.2397 +	if (pool[rp->version] == '\0') {
 21.2398 +		razor_package_iterator_init_for_property(&pi, set, rp);
 21.2399 +		while (razor_package_iterator_next(&pi, &pkg,
 21.2400 +						   &name, &version, &arch))
 21.2401 +			fprintf(stderr, "%s is needed by %s-%s.%s\n",
 21.2402 +				&pool[rp->name],
 21.2403 +				name, version, arch);
 21.2404 +	} else {
 21.2405 +		razor_package_iterator_init_for_property(&pi, set, rp);
 21.2406 +		while (razor_package_iterator_next(&pi, &pkg,
 21.2407 +						   &name, &version, &arch))
 21.2408 +			fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
 21.2409 +				&pool[rp->name],
 21.2410 +				relation_string[rp->relation],
 21.2411 +				&pool[rp->version],
 21.2412 +				name, version, arch);
 21.2413 +	}
 21.2414 +}
 21.2415 +
 21.2416 +int
 21.2417 +razor_transaction_describe(struct razor_transaction *trans)
 21.2418 +{
 21.2419 +	struct prop_iter rpi;
 21.2420 +	struct razor_property *rp;
 21.2421 +	int unsatisfied;
 21.2422 +
 21.2423 +	flush_scheduled_system_updates(trans);
 21.2424 +	flush_scheduled_upstream_updates(trans);
 21.2425 +	mark_all_satisfied_requires(trans);
 21.2426 +
 21.2427 +	unsatisfied = 0;
 21.2428 +	prop_iter_init(&rpi, &trans->system);
 21.2429 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 21.2430 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
 21.2431 +			describe_unsatisfied(trans->system.set, rp);
 21.2432 +		        unsatisfied++;
 21.2433 +		}
 21.2434 +	}
 21.2435 +
 21.2436 +	prop_iter_init(&rpi, &trans->upstream);
 21.2437 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 21.2438 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
 21.2439 +			describe_unsatisfied(trans->upstream.set, rp);
 21.2440 +			unsatisfied++;
 21.2441 +		}
 21.2442 +	}
 21.2443 +
 21.2444 +	return unsatisfied;
 21.2445 +}
 21.2446 +
 21.2447 +int
 21.2448 +razor_transaction_unsatisfied_property(struct razor_transaction *trans,
 21.2449 +				       const char *name,
 21.2450 +				       enum razor_version_relation rel,
 21.2451 +				       const char *version,
 21.2452 +				       enum razor_property_type type)
 21.2453 +{
 21.2454 +	struct prop_iter pi;
 21.2455 +	struct razor_property *p;
 21.2456 +
 21.2457 +	prop_iter_init(&pi, &trans->system);
 21.2458 +	while (prop_iter_next(&pi, type, &p)) {
 21.2459 +		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
 21.2460 +		    p->relation == rel &&
 21.2461 +		    strcmp(&pi.pool[p->name], name) == 0 &&
 21.2462 +		    strcmp(&pi.pool[p->version], version) == 0)
 21.2463 +
 21.2464 +			return 1;
 21.2465 +	}
 21.2466 +
 21.2467 +	prop_iter_init(&pi, &trans->upstream);
 21.2468 +	while (prop_iter_next(&pi, type, &p)) {
 21.2469 +		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
 21.2470 +		    p->relation == rel &&
 21.2471 +		    strcmp(&pi.pool[p->name], name) == 0 &&
 21.2472 +		    strcmp(&pi.pool[p->version], version) == 0)
 21.2473 +
 21.2474 +			return 1;
 21.2475 +	}
 21.2476 +
 21.2477 +	return 0;
 21.2478 +}
 21.2479 +
 21.2480 +struct razor_set *
 21.2481 +razor_transaction_finish(struct razor_transaction *trans)
 21.2482 +{
 21.2483 +	struct razor_merger *merger;
 21.2484 +	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
 21.2485 +	char *upool, *spool;
 21.2486 +	int cmp;
 21.2487 +
 21.2488 +	s = trans->system.set->packages.data;
 21.2489 +	spkgs = trans->system.set->packages.data;
 21.2490 +	send = trans->system.set->packages.data +
 21.2491 +		trans->system.set->packages.size;
 21.2492 +	spool = trans->system.set->string_pool.data;
 21.2493 +
 21.2494 +	u = trans->upstream.set->packages.data;
 21.2495 +	upkgs = trans->upstream.set->packages.data;
 21.2496 +	uend = trans->upstream.set->packages.data +
 21.2497 +		trans->upstream.set->packages.size;
 21.2498 +	upool = trans->upstream.set->string_pool.data;
 21.2499 +
 21.2500 +	merger = razor_merger_create(trans->system.set, trans->upstream.set);
 21.2501 +	while (s < send || u < uend) {
 21.2502 +		if (s < send && u < uend)
 21.2503 +			cmp = strcmp(&spool[s->name], &upool[u->name]);
 21.2504 +		else if (s < send)
 21.2505 +			cmp = -1;
 21.2506 +		else
 21.2507 +			cmp = 1;
 21.2508 +
 21.2509 +		if (cmp < 0) {
 21.2510 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
 21.2511 +				razor_merger_add_package(merger, s);
 21.2512 +			s++;
 21.2513 +		} else if (cmp == 0) {
 21.2514 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
 21.2515 +				razor_merger_add_package(merger, s);
 21.2516 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
 21.2517 +				razor_merger_add_package(merger, u);
 21.2518 +
 21.2519 +			s++;
 21.2520 +			u++;
 21.2521 +		} else {
 21.2522 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
 21.2523 +				razor_merger_add_package(merger, u);
 21.2524 +			u++;
 21.2525 +		}
 21.2526 +	}
 21.2527 +
 21.2528 +	razor_transaction_destroy(trans);
 21.2529 +
 21.2530 +	return razor_merger_finish(merger);
 21.2531 +}
 21.2532 +
 21.2533 +void
 21.2534 +razor_transaction_destroy(struct razor_transaction *trans)
 21.2535 +{
 21.2536 +	transaction_set_release(&trans->system);
 21.2537 +	transaction_set_release(&trans->upstream);
 21.2538 +	free(trans);
 21.2539 +}
 21.2540 +
 21.2541 +struct razor_package_query {
 21.2542 +	struct razor_set *set;
 21.2543 +	char *vector;
 21.2544 +	int count;
 21.2545 +};
 21.2546 +
 21.2547 +struct razor_package_query *
 21.2548 +razor_package_query_create(struct razor_set *set)
 21.2549 +{
 21.2550 +	struct razor_package_query *pq;
 21.2551 +	int count;
 21.2552 +
 21.2553 +	pq = zalloc(sizeof *pq);
 21.2554 +	pq->set = set;
 21.2555 +	count = set->packages.size / sizeof(struct razor_package);
 21.2556 +	pq->vector = zalloc(count * sizeof(char));
 21.2557 +
 21.2558 +	return pq;
 21.2559 +}
 21.2560 +
 21.2561 +void
 21.2562 +razor_package_query_add_package(struct razor_package_query *pq,
 21.2563 +				struct razor_package *p)
 21.2564 +{
 21.2565 +	struct razor_package *packages;
 21.2566 +
 21.2567 +	packages = pq->set->packages.data;
 21.2568 +	pq->count += pq->vector[p - packages] ^ 1;
 21.2569 +	pq->vector[p - packages] = 1;
 21.2570 +}
 21.2571 +
 21.2572 +void
 21.2573 +razor_package_query_add_iterator(struct razor_package_query *pq,
 21.2574 +				 struct razor_package_iterator *pi)
 21.2575 +{
 21.2576 +	struct razor_package *packages, *p;
 21.2577 +	const char *name, *version, *arch;
 21.2578 +
 21.2579 +	packages = pq->set->packages.data;
 21.2580 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 21.2581 +		pq->count += pq->vector[p - packages] ^ 1;
 21.2582 +		pq->vector[p - packages] = 1;
 21.2583 +	}
 21.2584 +}
 21.2585 +
 21.2586 +struct razor_package_iterator *
 21.2587 +razor_package_query_finish(struct razor_package_query *pq)
 21.2588 +{
 21.2589 +	struct razor_package_iterator *pi;
 21.2590 +	struct razor_set *set;
 21.2591 +	struct list *index;
 21.2592 +	int i, j, count;
 21.2593 +
 21.2594 +	set = pq->set;
 21.2595 +	count = set->packages.size / sizeof(struct razor_package);
 21.2596 +	index = zalloc(pq->count * sizeof *index);
 21.2597 +
 21.2598 +	for (i = 0, j = 0; i < count; i++) {
 21.2599 +		if (!pq->vector[i])
 21.2600 +			continue;
 21.2601 +
 21.2602 +		index[j].data = i;
 21.2603 +		if (j == pq->count - 1)
 21.2604 +			index[j].flags = 0x80;
 21.2605 +		j++;
 21.2606 +	}
 21.2607 +
 21.2608 +	free(pq);
 21.2609 +
 21.2610 +	pi = razor_package_iterator_create_with_index(set, index);
 21.2611 +	pi->free_index = 1;
 21.2612 +
 21.2613 +	return pi;
 21.2614 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/librazor/razor.h	Mon Jun 16 15:40:30 2008 -0400
    22.3 @@ -0,0 +1,189 @@
    22.4 +/*
    22.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    22.6 + * Copyright (C) 2008  Red Hat, Inc
    22.7 + *
    22.8 + * This program is free software; you can redistribute it and/or modify
    22.9 + * it under the terms of the GNU General Public License as published by
   22.10 + * the Free Software Foundation; either version 2 of the License, or
   22.11 + * (at your option) any later version.
   22.12 + *
   22.13 + * This program is distributed in the hope that it will be useful,
   22.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.16 + * GNU General Public License for more details.
   22.17 + *
   22.18 + * You should have received a copy of the GNU General Public License along
   22.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   22.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   22.21 + */
   22.22 +
   22.23 +#ifndef _RAZOR_H_
   22.24 +#define _RAZOR_H_
   22.25 +
   22.26 +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
   22.27 +
   22.28 +struct razor_set;
   22.29 +struct razor_package;
   22.30 +struct razor_property;
   22.31 +
   22.32 +enum razor_property_type {
   22.33 +	RAZOR_PROPERTY_REQUIRES,
   22.34 +	RAZOR_PROPERTY_PROVIDES,
   22.35 +	RAZOR_PROPERTY_CONFLICTS,
   22.36 +	RAZOR_PROPERTY_OBSOLETES
   22.37 +};
   22.38 +
   22.39 +enum razor_version_relation {
   22.40 +	RAZOR_VERSION_LESS,
   22.41 +	RAZOR_VERSION_LESS_OR_EQUAL,
   22.42 +	RAZOR_VERSION_EQUAL,
   22.43 +	RAZOR_VERSION_GREATER_OR_EQUAL,
   22.44 +	RAZOR_VERSION_GREATER
   22.45 +};
   22.46 +extern const char * const razor_version_relations[];
   22.47 +
   22.48 +struct razor_set *razor_set_create(void);
   22.49 +struct razor_set *razor_set_open(const char *filename);
   22.50 +void razor_set_destroy(struct razor_set *set);
   22.51 +int razor_set_write_to_fd(struct razor_set *set, int fd);
   22.52 +int razor_set_write(struct razor_set *set, const char *filename);
   22.53 +
   22.54 +struct razor_package *
   22.55 +razor_set_get_package(struct razor_set *set, const char *package);
   22.56 +
   22.57 +struct razor_package_iterator;
   22.58 +struct razor_package_iterator *
   22.59 +razor_package_iterator_create(struct razor_set *set);
   22.60 +struct razor_package_iterator *
   22.61 +razor_package_iterator_create_for_property(struct razor_set *set,
   22.62 +					   struct razor_property *property);
   22.63 +struct razor_package_iterator *
   22.64 +razor_package_iterator_create_for_file(struct razor_set *set,
   22.65 +				       const char *filename);
   22.66 +
   22.67 +int razor_package_iterator_next(struct razor_package_iterator *pi,
   22.68 +				struct razor_package **package,
   22.69 +				const char **name,
   22.70 +				const char **version,
   22.71 +				const char **arch);
   22.72 +void razor_package_iterator_destroy(struct razor_package_iterator *pi);
   22.73 +
   22.74 +struct razor_package_query *
   22.75 +razor_package_query_create(struct razor_set *set);
   22.76 +void
   22.77 +razor_package_query_add_package(struct razor_package_query *pq,
   22.78 +				struct razor_package *p);
   22.79 +void
   22.80 +razor_package_query_add_iterator(struct razor_package_query *pq,
   22.81 +				 struct razor_package_iterator *pi);
   22.82 +struct razor_package_iterator *
   22.83 +razor_package_query_finish(struct razor_package_query *pq);
   22.84 +
   22.85 +struct razor_property_iterator;
   22.86 +struct razor_property_iterator *
   22.87 +razor_property_iterator_create(struct razor_set *set,
   22.88 +			       struct razor_package *package);
   22.89 +int razor_property_iterator_next(struct razor_property_iterator *pi,
   22.90 +				 struct razor_property **property,
   22.91 +				 const char **name,
   22.92 +				 enum razor_version_relation *relation,
   22.93 +				 const char **version,
   22.94 +				 enum razor_property_type *type);
   22.95 +void
   22.96 +razor_property_iterator_destroy(struct razor_property_iterator *pi);
   22.97 +
   22.98 +void razor_set_list_files(struct razor_set *set, const char *prefix);
   22.99 +void razor_set_list_package_files(struct razor_set *set, const char *name);
  22.100 +
  22.101 +void razor_set_list_unsatisfied(struct razor_set *set);
  22.102 +
  22.103 +typedef void (*razor_package_callback_t)(const char *name,
  22.104 +					 const char *old_version,
  22.105 +					 const char *new_version,
  22.106 +					 const char *arch,
  22.107 +					 void *data);
  22.108 +void
  22.109 +razor_set_diff(struct razor_set *set, struct razor_set *upstream,
  22.110 +	       razor_package_callback_t callback, void *data);
  22.111 +
  22.112 +/* Package transactions */
  22.113 +
  22.114 +struct razor_transaction *
  22.115 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream);
  22.116 +void razor_transaction_install_package(struct razor_transaction *transaction,
  22.117 +				       struct razor_package *package);
  22.118 +void razor_transaction_remove_package(struct razor_transaction *transaction,
  22.119 +				      struct razor_package *package);
  22.120 +void razor_transaction_update_package(struct razor_transaction *trans,
  22.121 +				      struct razor_package *package);
  22.122 +void razor_transaction_update_all(struct razor_transaction *transaction);
  22.123 +int razor_transaction_resolve(struct razor_transaction *trans);
  22.124 +int razor_transaction_describe(struct razor_transaction *trans);
  22.125 +struct razor_set *razor_transaction_finish(struct razor_transaction *trans);
  22.126 +void razor_transaction_destroy(struct razor_transaction *trans);
  22.127 +
  22.128 +/* Temporary helper for test suite. */
  22.129 +int razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  22.130 +					   const char *name,
  22.131 +					   enum razor_version_relation rel,
  22.132 +					   const char *version,
  22.133 +					   enum razor_property_type type);
  22.134 +
  22.135 +/* Importer interface; for building a razor set from external sources,
  22.136 + * like yum, rpmdb or razor package files. */
  22.137 +
  22.138 +struct razor_importer;
  22.139 +struct razor_rpm;
  22.140 +
  22.141 +struct razor_importer *razor_importer_new(void);
  22.142 +void razor_importer_destroy(struct razor_importer *importer);
  22.143 +void razor_importer_begin_package(struct razor_importer *importer,
  22.144 +				  const char *name,
  22.145 +				  const char *version,
  22.146 +				  const char *arch);
  22.147 +void razor_importer_add_property(struct razor_importer *importer,
  22.148 +				 const char *name,
  22.149 +				 enum razor_version_relation relation,
  22.150 +				 const char *version,
  22.151 +				 enum razor_property_type type);
  22.152 +void razor_importer_add_file(struct razor_importer *importer,
  22.153 +			     const char *name);
  22.154 +void razor_importer_finish_package(struct razor_importer *importer);
  22.155 +
  22.156 +int razor_importer_add_rpm(struct razor_importer *importer,
  22.157 +			   struct razor_rpm *rpm);
  22.158 +
  22.159 +struct razor_set *razor_importer_finish(struct razor_importer *importer);
  22.160 +
  22.161 +void razor_build_evr(char *evr_buf, int size, const char *epoch,
  22.162 +		     const char *version, const char *release);
  22.163 +
  22.164 +struct razor_set *razor_set_create_from_yum(void);
  22.165 +struct razor_set *razor_set_create_from_rpmdb(void);
  22.166 +
  22.167 +/* RPM functions */
  22.168 +
  22.169 +struct razor_rpm *razor_rpm_open(const char *filename);
  22.170 +int razor_rpm_install(struct razor_rpm *rpm, const char *root);
  22.171 +int razor_rpm_close(struct razor_rpm *rpm);
  22.172 +
  22.173 +
  22.174 +/* Razor root functions. The root data struct encapsulates filesystem
  22.175 + * conventions and the locking protocol. */
  22.176 +
  22.177 +struct razor_root;
  22.178 +#define RAZOR_ROOT_OPEN_WRITE 0x01
  22.179 +
  22.180 +int razor_root_create(const char *root);
  22.181 +struct razor_root *razor_root_open(const char *root, int flags);
  22.182 +struct razor_set *razor_root_open_read_only(const char *root);
  22.183 +struct razor_transaction *
  22.184 +razor_root_create_transaction(struct razor_root *image,
  22.185 +			      struct razor_set *upstream);
  22.186 +int razor_root_close(struct razor_root *image);
  22.187 +void razor_root_update(struct razor_root *image, struct razor_set *next);
  22.188 +int razor_root_commit(struct razor_root *image);
  22.189 +void razor_root_diff(struct razor_root *root,
  22.190 +		     razor_package_callback_t callback, void *data);
  22.191 +
  22.192 +#endif /* _RAZOR_H_ */
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/librazor/rpm.c	Mon Jun 16 15:40:30 2008 -0400
    23.3 @@ -0,0 +1,813 @@
    23.4 +/*
    23.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    23.6 + * Copyright (C) 2008  Red Hat, Inc
    23.7 + *
    23.8 + * This program is free software; you can redistribute it and/or modify
    23.9 + * it under the terms of the GNU General Public License as published by
   23.10 + * the Free Software Foundation; either version 2 of the License, or
   23.11 + * (at your option) any later version.
   23.12 + *
   23.13 + * This program is distributed in the hope that it will be useful,
   23.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.16 + * GNU General Public License for more details.
   23.17 + *
   23.18 + * You should have received a copy of the GNU General Public License along
   23.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   23.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   23.21 + */
   23.22 +
   23.23 +#include <stdio.h>
   23.24 +#include <stddef.h>
   23.25 +#include <stdlib.h>
   23.26 +#include <string.h>
   23.27 +#include <errno.h>
   23.28 +#include <sys/stat.h>
   23.29 +#include <sys/mman.h>
   23.30 +#include <sys/types.h>
   23.31 +#include <sys/wait.h>
   23.32 +#include <fcntl.h>
   23.33 +#include <dirent.h>
   23.34 +#include <unistd.h>
   23.35 +#include <arpa/inet.h>
   23.36 +#include <zlib.h>
   23.37 +
   23.38 +#include "razor.h"
   23.39 +#include "razor-internal.h"
   23.40 +
   23.41 +#define	RPM_LEAD_SIZE 96
   23.42 +
   23.43 +enum {
   23.44 +    PIPE	=  1,	/*!< pipe/fifo */
   23.45 +    CDEV	=  2,	/*!< character device */
   23.46 +    XDIR	=  4,	/*!< directory */
   23.47 +    BDEV	=  6,	/*!< block device */
   23.48 +    REG		=  8,	/*!< regular file */
   23.49 +    LINK	= 10,	/*!< hard link */
   23.50 +    SOCK	= 12	/*!< socket */
   23.51 +};
   23.52 +
   23.53 +enum {
   23.54 +    RPMSENSE_LESS	= (1 << 1),
   23.55 +    RPMSENSE_GREATER	= (1 << 2),
   23.56 +    RPMSENSE_EQUAL	= (1 << 3),
   23.57 +};
   23.58 +
   23.59 +enum {
   23.60 +    RPMTAG_NAME  		= 1000,	/* s */
   23.61 +    RPMTAG_VERSION		= 1001,	/* s */
   23.62 +    RPMTAG_RELEASE		= 1002,	/* s */
   23.63 +    RPMTAG_EPOCH   		= 1003,	/* i */
   23.64 +    RPMTAG_SUMMARY		= 1004,	/* s{} */
   23.65 +    RPMTAG_DESCRIPTION		= 1005,	/* s{} */
   23.66 +    RPMTAG_BUILDTIME		= 1006,	/* i */
   23.67 +    RPMTAG_BUILDHOST		= 1007,	/* s */
   23.68 +    RPMTAG_INSTALLTIME		= 1008,	/* i */
   23.69 +    RPMTAG_SIZE			= 1009,	/* i */
   23.70 +    RPMTAG_DISTRIBUTION		= 1010,	/* s */
   23.71 +    RPMTAG_VENDOR		= 1011,	/* s */
   23.72 +    RPMTAG_GIF			= 1012,	/* x */
   23.73 +    RPMTAG_XPM			= 1013,	/* x */
   23.74 +    RPMTAG_LICENSE		= 1014,	/* s */
   23.75 +    RPMTAG_PACKAGER		= 1015,	/* s */
   23.76 +    RPMTAG_GROUP		= 1016,	/* s{} */
   23.77 +    RPMTAG_CHANGELOG		= 1017, /*!< s[] internal */
   23.78 +    RPMTAG_SOURCE		= 1018,	/* s[] */
   23.79 +    RPMTAG_PATCH		= 1019,	/* s[] */
   23.80 +    RPMTAG_URL			= 1020,	/* s */
   23.81 +    RPMTAG_OS			= 1021,	/* s legacy used int */
   23.82 +    RPMTAG_ARCH			= 1022,	/* s legacy used int */
   23.83 +    RPMTAG_PREIN		= 1023,	/* s */
   23.84 +    RPMTAG_POSTIN		= 1024,	/* s */
   23.85 +    RPMTAG_PREUN		= 1025,	/* s */
   23.86 +    RPMTAG_POSTUN		= 1026,	/* s */
   23.87 +    RPMTAG_OLDFILENAMES		= 1027, /* s[] obsolete */
   23.88 +    RPMTAG_FILESIZES		= 1028,	/* i */
   23.89 +    RPMTAG_FILESTATES		= 1029, /* c */
   23.90 +    RPMTAG_FILEMODES		= 1030,	/* h */
   23.91 +    RPMTAG_FILEUIDS		= 1031, /*!< internal */
   23.92 +    RPMTAG_FILEGIDS		= 1032, /*!< internal */
   23.93 +    RPMTAG_FILERDEVS		= 1033,	/* h */
   23.94 +    RPMTAG_FILEMTIMES		= 1034, /* i */
   23.95 +    RPMTAG_FILEMD5S		= 1035,	/* s[] */
   23.96 +    RPMTAG_FILELINKTOS		= 1036,	/* s[] */
   23.97 +    RPMTAG_FILEFLAGS		= 1037,	/* i */
   23.98 +    RPMTAG_ROOT			= 1038, /*!< internal - obsolete */
   23.99 +    RPMTAG_FILEUSERNAME		= 1039,	/* s[] */
  23.100 +    RPMTAG_FILEGROUPNAME	= 1040,	/* s[] */
  23.101 +    RPMTAG_EXCLUDE		= 1041, /*!< internal - obsolete */
  23.102 +    RPMTAG_EXCLUSIVE		= 1042, /*!< internal - obsolete */
  23.103 +    RPMTAG_ICON			= 1043,
  23.104 +    RPMTAG_SOURCERPM		= 1044,	/* s */
  23.105 +    RPMTAG_FILEVERIFYFLAGS	= 1045,	/* i */
  23.106 +    RPMTAG_ARCHIVESIZE		= 1046,	/* i */
  23.107 +    RPMTAG_PROVIDENAME		= 1047,	/* s[] */
  23.108 +    RPMTAG_REQUIREFLAGS		= 1048,	/* i */
  23.109 +    RPMTAG_REQUIRENAME		= 1049,	/* s[] */
  23.110 +    RPMTAG_REQUIREVERSION	= 1050,	/* s[] */
  23.111 +    RPMTAG_NOSOURCE		= 1051, /*!< internal */
  23.112 +    RPMTAG_NOPATCH		= 1052, /*!< internal */
  23.113 +    RPMTAG_CONFLICTFLAGS	= 1053, /* i */
  23.114 +    RPMTAG_CONFLICTNAME		= 1054,	/* s[] */
  23.115 +    RPMTAG_CONFLICTVERSION	= 1055,	/* s[] */
  23.116 +    RPMTAG_DEFAULTPREFIX	= 1056, /*!< internal - deprecated */
  23.117 +    RPMTAG_BUILDROOT		= 1057, /*!< internal */
  23.118 +    RPMTAG_INSTALLPREFIX	= 1058, /*!< internal - deprecated */
  23.119 +    RPMTAG_EXCLUDEARCH		= 1059,
  23.120 +    RPMTAG_EXCLUDEOS		= 1060,
  23.121 +    RPMTAG_EXCLUSIVEARCH	= 1061,
  23.122 +    RPMTAG_EXCLUSIVEOS		= 1062,
  23.123 +    RPMTAG_AUTOREQPROV		= 1063, /*!< internal */
  23.124 +    RPMTAG_RPMVERSION		= 1064,	/* s */
  23.125 +    RPMTAG_TRIGGERSCRIPTS	= 1065,	/* s[] */
  23.126 +    RPMTAG_TRIGGERNAME		= 1066,	/* s[] */
  23.127 +    RPMTAG_TRIGGERVERSION	= 1067,	/* s[] */
  23.128 +    RPMTAG_TRIGGERFLAGS		= 1068,	/* i */
  23.129 +    RPMTAG_TRIGGERINDEX		= 1069,	/* i */
  23.130 +    RPMTAG_VERIFYSCRIPT		= 1079,	/* s */
  23.131 +    RPMTAG_CHANGELOGTIME	= 1080,	/* i */
  23.132 +    RPMTAG_CHANGELOGNAME	= 1081,	/* s[] */
  23.133 +    RPMTAG_CHANGELOGTEXT	= 1082,	/* s[] */
  23.134 +    RPMTAG_BROKENMD5		= 1083, /*!< internal - obsolete */
  23.135 +    RPMTAG_PREREQ		= 1084, /*!< internal */
  23.136 +    RPMTAG_PREINPROG		= 1085,	/* s */
  23.137 +    RPMTAG_POSTINPROG		= 1086,	/* s */
  23.138 +    RPMTAG_PREUNPROG		= 1087,	/* s */
  23.139 +    RPMTAG_POSTUNPROG		= 1088,	/* s */
  23.140 +    RPMTAG_BUILDARCHS		= 1089,
  23.141 +    RPMTAG_OBSOLETENAME		= 1090,	/* s[] */
  23.142 +    RPMTAG_VERIFYSCRIPTPROG	= 1091,	/* s */
  23.143 +    RPMTAG_TRIGGERSCRIPTPROG	= 1092,	/* s */
  23.144 +    RPMTAG_DOCDIR		= 1093, /*!< internal */
  23.145 +    RPMTAG_COOKIE		= 1094,	/* s */
  23.146 +    RPMTAG_FILEDEVICES		= 1095,	/* i */
  23.147 +    RPMTAG_FILEINODES		= 1096,	/* i */
  23.148 +    RPMTAG_FILELANGS		= 1097,	/* s[] */
  23.149 +    RPMTAG_PREFIXES		= 1098,	/* s[] */
  23.150 +    RPMTAG_INSTPREFIXES		= 1099,	/* s[] */
  23.151 +    RPMTAG_TRIGGERIN		= 1100, /*!< internal */
  23.152 +    RPMTAG_TRIGGERUN		= 1101, /*!< internal */
  23.153 +    RPMTAG_TRIGGERPOSTUN	= 1102, /*!< internal */
  23.154 +    RPMTAG_AUTOREQ		= 1103, /*!< internal */
  23.155 +    RPMTAG_AUTOPROV		= 1104, /*!< internal */
  23.156 +    RPMTAG_CAPABILITY		= 1105, /*!< internal - obsolete */
  23.157 +    RPMTAG_SOURCEPACKAGE	= 1106, /*!< i src.rpm header marker */
  23.158 +    RPMTAG_OLDORIGFILENAMES	= 1107, /*!< internal - obsolete */
  23.159 +    RPMTAG_BUILDPREREQ		= 1108, /*!< internal */
  23.160 +    RPMTAG_BUILDREQUIRES	= 1109, /*!< internal */
  23.161 +    RPMTAG_BUILDCONFLICTS	= 1110, /*!< internal */
  23.162 +    RPMTAG_BUILDMACROS		= 1111, /*!< internal - unused */
  23.163 +    RPMTAG_PROVIDEFLAGS		= 1112,	/* i */
  23.164 +    RPMTAG_PROVIDEVERSION	= 1113,	/* s[] */
  23.165 +    RPMTAG_OBSOLETEFLAGS	= 1114,	/* i */
  23.166 +    RPMTAG_OBSOLETEVERSION	= 1115,	/* s[] */
  23.167 +    RPMTAG_DIRINDEXES		= 1116,	/* i */
  23.168 +    RPMTAG_BASENAMES		= 1117,	/* s[] */
  23.169 +    RPMTAG_DIRNAMES		= 1118,	/* s[] */
  23.170 +    RPMTAG_ORIGDIRINDEXES	= 1119, /*!< internal */
  23.171 +    RPMTAG_ORIGBASENAMES	= 1120, /*!< internal */
  23.172 +    RPMTAG_ORIGDIRNAMES		= 1121, /*!< internal */
  23.173 +    RPMTAG_OPTFLAGS		= 1122,	/* s */
  23.174 +    RPMTAG_DISTURL		= 1123,	/* s */
  23.175 +    RPMTAG_PAYLOADFORMAT	= 1124,	/* s */
  23.176 +    RPMTAG_PAYLOADCOMPRESSOR	= 1125,	/* s */
  23.177 +    RPMTAG_PAYLOADFLAGS		= 1126,	/* s */
  23.178 +    RPMTAG_INSTALLCOLOR		= 1127, /*!< i transaction color when installed */
  23.179 +    RPMTAG_INSTALLTID		= 1128,	/* i */
  23.180 +    RPMTAG_REMOVETID		= 1129,	/* i */
  23.181 +    RPMTAG_SHA1RHN		= 1130, /*!< internal - obsolete */
  23.182 +    RPMTAG_RHNPLATFORM		= 1131,	/* s */
  23.183 +    RPMTAG_PLATFORM		= 1132,	/* s */
  23.184 +    RPMTAG_PATCHESNAME		= 1133, /*!< placeholder (SuSE) */
  23.185 +    RPMTAG_PATCHESFLAGS		= 1134, /*!< placeholder (SuSE) */
  23.186 +    RPMTAG_PATCHESVERSION	= 1135, /*!< placeholder (SuSE) */
  23.187 +    RPMTAG_CACHECTIME		= 1136,	/* i */
  23.188 +    RPMTAG_CACHEPKGPATH		= 1137,	/* s */
  23.189 +    RPMTAG_CACHEPKGSIZE		= 1138,	/* i */
  23.190 +    RPMTAG_CACHEPKGMTIME	= 1139,	/* i */
  23.191 +    RPMTAG_FILECOLORS		= 1140,	/* i */
  23.192 +    RPMTAG_FILECLASS		= 1141,	/* i */
  23.193 +    RPMTAG_CLASSDICT		= 1142,	/* s[] */
  23.194 +    RPMTAG_FILEDEPENDSX		= 1143,	/* i */
  23.195 +    RPMTAG_FILEDEPENDSN		= 1144,	/* i */
  23.196 +    RPMTAG_DEPENDSDICT		= 1145,	/* i */
  23.197 +    RPMTAG_SOURCEPKGID		= 1146,	/* x */
  23.198 +    RPMTAG_FILECONTEXTS		= 1147,	/* s[] */
  23.199 +    RPMTAG_FSCONTEXTS		= 1148,	/*!< s[] extension */
  23.200 +    RPMTAG_RECONTEXTS		= 1149,	/*!< s[] extension */
  23.201 +    RPMTAG_POLICIES		= 1150,	/*!< s[] selinux *.te policy file. */
  23.202 +    RPMTAG_PRETRANS		= 1151,	/* s */
  23.203 +    RPMTAG_POSTTRANS		= 1152,	/* s */
  23.204 +    RPMTAG_PRETRANSPROG		= 1153,	/* s */
  23.205 +    RPMTAG_POSTTRANSPROG	= 1154,	/* s */
  23.206 +    RPMTAG_DISTTAG		= 1155,	/* s */
  23.207 +    RPMTAG_SUGGESTSNAME		= 1156,	/* s[] extension placeholder */
  23.208 +    RPMTAG_SUGGESTSVERSION	= 1157,	/* s[] extension placeholder */
  23.209 +    RPMTAG_SUGGESTSFLAGS	= 1158,	/* i   extension placeholder */
  23.210 +    RPMTAG_ENHANCESNAME		= 1159,	/* s[] extension placeholder */
  23.211 +    RPMTAG_ENHANCESVERSION	= 1160,	/* s[] extension placeholder */
  23.212 +    RPMTAG_ENHANCESFLAGS	= 1161,	/* i   extension placeholder */
  23.213 +    RPMTAG_PRIORITY		= 1162, /* i   extension placeholder */
  23.214 +    RPMTAG_CVSID		= 1163, /* s */
  23.215 +    RPMTAG_TRIGGERPREIN		= 1171, /*!< internal */
  23.216 +};
  23.217 +
  23.218 +struct rpm_header {
  23.219 +	unsigned char magic[4];
  23.220 +	unsigned char reserved[4];
  23.221 +	int nindex;
  23.222 +	int hsize;
  23.223 +};
  23.224 +
  23.225 +struct rpm_header_index {
  23.226 +	int tag;
  23.227 +	int type;
  23.228 +	int offset;
  23.229 +	int count;
  23.230 +};
  23.231 +
  23.232 +struct razor_rpm {
  23.233 +	struct rpm_header *signature;
  23.234 +	struct rpm_header *header;
  23.235 +	const char **dirs;
  23.236 +	const char *pool;
  23.237 +	void *map;
  23.238 +	size_t size;
  23.239 +	void *payload;
  23.240 +};
  23.241 +
  23.242 +static struct rpm_header_index *
  23.243 +razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
  23.244 +{
  23.245 +	struct rpm_header_index *index, *end;
  23.246 +
  23.247 +	index = (struct rpm_header_index *) (rpm->header + 1);
  23.248 +	end = index + ntohl(rpm->header->nindex);
  23.249 +	while (index < end) {
  23.250 +		if (ntohl(index->tag) == tag)
  23.251 +			return index;
  23.252 +		index++;
  23.253 +	}
  23.254 +
  23.255 +	return NULL;
  23.256 +}
  23.257 +
  23.258 +static const void *
  23.259 +razor_rpm_get_indirect(struct razor_rpm *rpm,
  23.260 +		       unsigned int tag, unsigned int *count)
  23.261 +{
  23.262 +	struct rpm_header_index *index;
  23.263 +
  23.264 +	index = razor_rpm_get_header(rpm, tag);
  23.265 +	if (index != NULL) {
  23.266 +		if (count)
  23.267 +			*count = ntohl(index->count);
  23.268 +
  23.269 +		return rpm->pool + ntohl(index->offset);
  23.270 +	}
  23.271 +
  23.272 +	return NULL;
  23.273 +}
  23.274 +
  23.275 +static enum razor_version_relation
  23.276 +rpm_to_razor_flags(uint32_t flags)
  23.277 +{
  23.278 +	switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
  23.279 +	case RPMSENSE_LESS:
  23.280 +		return RAZOR_VERSION_LESS;
  23.281 +	case RPMSENSE_LESS|RPMSENSE_EQUAL:
  23.282 +		return RAZOR_VERSION_LESS_OR_EQUAL;
  23.283 +	case RPMSENSE_EQUAL:
  23.284 +		return RAZOR_VERSION_EQUAL;
  23.285 +	case RPMSENSE_GREATER|RPMSENSE_EQUAL:
  23.286 +		return RAZOR_VERSION_GREATER_OR_EQUAL;
  23.287 +	case RPMSENSE_GREATER:
  23.288 +		return RAZOR_VERSION_GREATER;
  23.289 +	}
  23.290 +
  23.291 +	/* FIXME? */
  23.292 +	return RAZOR_VERSION_EQUAL;
  23.293 +}
  23.294 +
  23.295 +static void
  23.296 +import_properties(struct razor_importer *importer, unsigned long type,
  23.297 +		  struct razor_rpm *rpm,
  23.298 +		  int name_tag, int version_tag, int flags_tag)
  23.299 +{
  23.300 +	const char *name, *version;
  23.301 +	const uint32_t *flags;
  23.302 +	uint32_t f;
  23.303 +	unsigned int i, count;
  23.304 +
  23.305 +	name = razor_rpm_get_indirect(rpm, name_tag, &count);
  23.306 +	if (name == NULL)
  23.307 +		return;
  23.308 +
  23.309 +	flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
  23.310 +
  23.311 +	version = razor_rpm_get_indirect(rpm, version_tag, &count);
  23.312 +	for (i = 0; i < count; i++) {
  23.313 +		f = rpm_to_razor_flags(ntohl(flags[i]));
  23.314 +		razor_importer_add_property(importer, name, f, version, type);
  23.315 +		name += strlen(name) + 1;
  23.316 +		version += strlen(version) + 1;
  23.317 +	}
  23.318 +}
  23.319 +
  23.320 +static void
  23.321 +import_files(struct razor_importer *importer, struct razor_rpm *rpm)
  23.322 +{
  23.323 +	const char *name;
  23.324 +	const uint32_t *index;
  23.325 +	unsigned int i, count;
  23.326 +	char buffer[256];
  23.327 +
  23.328 +	/* assert: count is the same for all arrays */
  23.329 +
  23.330 +	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
  23.331 +	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
  23.332 +	for (i = 0; i < count; i++) {
  23.333 +		snprintf(buffer, sizeof buffer,
  23.334 +			 "%s%s", rpm->dirs[ntohl(*index)], name);
  23.335 +		razor_importer_add_file(importer, buffer);
  23.336 +		name += strlen(name) + 1;
  23.337 +		index++;
  23.338 +	}
  23.339 +}
  23.340 +
  23.341 +struct razor_rpm *
  23.342 +razor_rpm_open(const char *filename)
  23.343 +{
  23.344 +	struct razor_rpm *rpm;
  23.345 +	struct rpm_header_index *base, *index;
  23.346 +	struct stat buf;
  23.347 +	unsigned int count, i, nindex, hsize;
  23.348 +	const char *name;
  23.349 +	int fd;
  23.350 +
  23.351 +	rpm = malloc(sizeof *rpm);
  23.352 +	memset(rpm, 0, sizeof *rpm);
  23.353 +
  23.354 +	fd = open(filename, O_RDONLY);
  23.355 +	if (fd < 0) {
  23.356 +		fprintf(stderr, "couldn't open %s\n", filename);
  23.357 +		return NULL;
  23.358 +	}
  23.359 +
  23.360 +	if (fstat(fd, &buf) < 0) {
  23.361 +		fprintf(stderr, "failed to stat %s (%m)\n", filename);
  23.362 +		return NULL;
  23.363 +	}
  23.364 +
  23.365 +	rpm->size = buf.st_size;
  23.366 +	rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
  23.367 +	if (rpm->map == MAP_FAILED) {
  23.368 +		fprintf(stderr, "couldn't mmap %s\n", filename);
  23.369 +		return NULL;
  23.370 +	}
  23.371 +	close(fd);
  23.372 +
  23.373 +	rpm->signature = rpm->map + RPM_LEAD_SIZE;
  23.374 +	nindex = ntohl(rpm->signature->nindex);
  23.375 +	hsize = ntohl(rpm->signature->hsize);
  23.376 +	rpm->header = (void *) (rpm->signature + 1) +
  23.377 +		ALIGN(nindex * sizeof *index + hsize, 8);
  23.378 +	nindex = ntohl(rpm->header->nindex);
  23.379 +	hsize = ntohl(rpm->header->hsize);
  23.380 +	rpm->payload = (void *) (rpm->header + 1) +
  23.381 +		nindex * sizeof *index + hsize;
  23.382 +
  23.383 +	base = (struct rpm_header_index *) (rpm->header + 1);
  23.384 +	rpm->pool = (void *) base + nindex * sizeof *index;
  23.385 +
  23.386 +	/* Look up dir names now so we can index them directly. */
  23.387 +	name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
  23.388 +	if (name) {
  23.389 +		rpm->dirs = calloc(count, sizeof *rpm->dirs);
  23.390 +		for (i = 0; i < count; i++) {
  23.391 +			rpm->dirs[i] = name;
  23.392 +			name += strlen(name) + 1;
  23.393 +		}
  23.394 +	} else {
  23.395 +		name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
  23.396 +					      &count);
  23.397 +		if (name) {
  23.398 +			fprintf(stderr, "old filenames not supported\n");
  23.399 +			return NULL;
  23.400 +		}
  23.401 +	}
  23.402 +
  23.403 +	return rpm;
  23.404 +}
  23.405 +
  23.406 +struct cpio_file_header {
  23.407 +	char magic[6];
  23.408 +	char inode[8];
  23.409 +	char mode[8];
  23.410 +	char uid[8];
  23.411 +	char gid[8];
  23.412 +	char nlink[8];
  23.413 +	char mtime[8];
  23.414 +	char filesize[8];
  23.415 +	char devmajor[8];
  23.416 +	char devminor[8];
  23.417 +	char rdevmajor[8];
  23.418 +	char rdevminor[8];
  23.419 +	char namesize[8];
  23.420 +	char checksum[8];
  23.421 +	char filename[0];
  23.422 +};
  23.423 +
  23.424 +/* gzip flags */
  23.425 +#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
  23.426 +#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
  23.427 +#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  23.428 +#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  23.429 +#define COMMENT      0x10 /* bit 4 set: file comment present */
  23.430 +#define RESERVED     0xE0 /* bits 5..7: reserved */
  23.431 +
  23.432 +struct installer {
  23.433 +	const char *root;
  23.434 +	struct razor_rpm *rpm;
  23.435 +	z_stream stream;
  23.436 +	unsigned char buffer[32768];
  23.437 +	size_t rest, length;
  23.438 +};
  23.439 +
  23.440 +static int
  23.441 +installer_inflate(struct installer *installer)
  23.442 +{
  23.443 +	size_t length;
  23.444 +	int err;
  23.445 +
  23.446 +	if (installer->rest > sizeof installer->buffer)
  23.447 +		length = sizeof installer->buffer;
  23.448 +	else
  23.449 +		length = installer->rest;
  23.450 +
  23.451 +	installer->stream.next_out = installer->buffer;
  23.452 +	installer->stream.avail_out = length;
  23.453 +	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  23.454 +	if (err != Z_OK && err != Z_STREAM_END) {
  23.455 +		fprintf(stderr, "inflate error: %d (%m)\n", err);
  23.456 +		return -1;
  23.457 +	}
  23.458 +
  23.459 +	installer->rest -= length;
  23.460 +	installer->length = length;
  23.461 +
  23.462 +	return 0;
  23.463 +}
  23.464 +
  23.465 +static int
  23.466 +installer_align(struct installer *installer, size_t size)
  23.467 +{
  23.468 +	unsigned char buffer[4];
  23.469 +	int err;
  23.470 +
  23.471 +	installer->stream.next_out = buffer;
  23.472 +	installer->stream.avail_out =
  23.473 +		(size - installer->stream.total_out) & (size - 1);
  23.474 +
  23.475 +	if (installer->stream.avail_out == 0)
  23.476 +		return 0;
  23.477 +
  23.478 +	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  23.479 +	if (err != Z_OK && err != Z_STREAM_END) {
  23.480 +		fprintf(stderr, "inflate error: %d (%m)\n", err);
  23.481 +		return -1;
  23.482 +	}
  23.483 +
  23.484 +	return 0;
  23.485 +}
  23.486 +
  23.487 +static int
  23.488 +create_path(struct installer *installer, const char *path, unsigned int mode)
  23.489 +{
  23.490 +	char buffer[PATH_MAX];
  23.491 +	struct stat buf;
  23.492 +	int fd, ret;
  23.493 +
  23.494 +	if (razor_create_dir(installer->root, path) < 0)
  23.495 +		return -1;
  23.496 +
  23.497 +	snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
  23.498 +
  23.499 +	switch (mode >> 12) {
  23.500 +	case REG:
  23.501 +		/* FIXME: handle the case where a file is already there. */
  23.502 +		fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, mode & 0x1ff);
  23.503 +		if (fd < 0){
  23.504 +			fprintf(stderr, "failed to create file %s\n", buffer);
  23.505 +			return -1;
  23.506 +		}
  23.507 +		while (installer->rest > 0) {
  23.508 +			if (installer_inflate(installer)) {
  23.509 +				fprintf(stderr, "failed to inflate\n");
  23.510 +				return -1;
  23.511 +			}
  23.512 +			if (razor_write(fd, installer->buffer,
  23.513 +					installer->length)) {
  23.514 +				fprintf(stderr, "failed to write payload\n");
  23.515 +				return -1;
  23.516 +			}
  23.517 +		}
  23.518 +		if (close(fd) < 0) {
  23.519 +			fprintf(stderr, "failed to close %s: %m\n", buffer);
  23.520 +			return -1;
  23.521 +		}
  23.522 +		return 0;
  23.523 +	case XDIR:
  23.524 +		ret = mkdir(buffer, mode & 0x1ff);
  23.525 +		if (ret == 0 || errno != EEXIST)
  23.526 +			return ret;
  23.527 +		if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
  23.528 +			/* FIXME: also check that mode match. */
  23.529 +			fprintf(stderr,
  23.530 +				"%s exists but is not a directory\n", buffer);
  23.531 +			return -1;
  23.532 +		}
  23.533 +		return 0;
  23.534 +	case PIPE:
  23.535 +	case CDEV:
  23.536 +	case BDEV:
  23.537 +	case SOCK:
  23.538 +		printf("%s: unhandled file type %d\n", buffer, mode >> 12);
  23.539 +		return 0;
  23.540 +	case LINK:
  23.541 +		if (installer_inflate(installer)) {
  23.542 +			fprintf(stderr, "failed to inflate\n");
  23.543 +			return -1;
  23.544 +		}
  23.545 +		if (installer->length >= sizeof installer->buffer) {
  23.546 +			fprintf(stderr, "link name too long\n");
  23.547 +			return -1;
  23.548 +		}
  23.549 +		installer->buffer[installer->length] = '\0';
  23.550 +		if (symlink((const char *) installer->buffer, buffer)) {
  23.551 +			fprintf(stderr, "failed to create symlink, %m\n");
  23.552 +			return -1;
  23.553 +		}
  23.554 +		return 0;
  23.555 +	default:
  23.556 +		printf("%s: unknown file type %d\n", buffer, mode >> 12);
  23.557 +		return 0;
  23.558 +	}
  23.559 +}
  23.560 +
  23.561 +static int
  23.562 +run_script(struct installer *installer,
  23.563 +	   unsigned int program_tag, unsigned int script_tag)
  23.564 +{
  23.565 +	int pid, status, fd[2];
  23.566 +	const char *script = NULL, *program = NULL;
  23.567 +
  23.568 +	program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
  23.569 +	script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
  23.570 +	if (program == NULL && script == NULL) {
  23.571 +		return 0;
  23.572 +	} else if (program == NULL) {
  23.573 +		program = "/bin/sh";
  23.574 +	}
  23.575 +
  23.576 +	if (pipe(fd) < 0) {
  23.577 +		fprintf(stderr, "failed to create pipe\n");
  23.578 +		return -1;
  23.579 +	}
  23.580 +	pid = fork();
  23.581 +	if (pid < 0) {
  23.582 +		fprintf(stderr, "failed to fork, %m\n");
  23.583 +	} else if (pid == 0) {
  23.584 +		if (dup2(fd[0], STDIN_FILENO) < 0) {
  23.585 +			fprintf(stderr, "failed redirect stdin, %m\n");
  23.586 +			return -1;
  23.587 +		}
  23.588 +		if (close(fd[0]) < 0 || close(fd[1]) < 0) {
  23.589 +			fprintf(stderr, "failed to close pipe, %m\n");
  23.590 +			return -1;
  23.591 +		}
  23.592 +		if (chroot(installer->root) < 0) {
  23.593 +			fprintf(stderr, "failed to chroot to %s, %m\n",
  23.594 +				installer->root);
  23.595 +			return -1;
  23.596 +		}
  23.597 +		printf("executing program %s in chroot %s\n",
  23.598 +		       program, installer->root);
  23.599 +		if (execl(program, program, NULL)) {
  23.600 +			fprintf(stderr, "failed to exec %s, %m\n", program);
  23.601 +			exit(-1);
  23.602 +		}
  23.603 +	} else {
  23.604 +		if (script && razor_write(fd[1], script, strlen(script)) < 0) {
  23.605 +			fprintf(stderr, "failed to pipe script, %m\n");
  23.606 +			return -1;
  23.607 +		}
  23.608 +		if (close(fd[0]) || close(fd[1])) {
  23.609 +			fprintf(stderr, "failed to close pipe, %m\n");
  23.610 +			return -1;
  23.611 +		}
  23.612 +		if (wait(&status) < 0) {
  23.613 +			fprintf(stderr, "wait for child failed, %m");
  23.614 +			return -1;
  23.615 +		}
  23.616 +		if (status)
  23.617 +			printf("script exited with status %d\n", status);
  23.618 +	}
  23.619 +
  23.620 +	return 0;
  23.621 +}
  23.622 +
  23.623 +static int
  23.624 +installer_init(struct installer *installer)
  23.625 +{
  23.626 +	unsigned char *gz_header;
  23.627 +	int method, flags, err;
  23.628 +
  23.629 +	gz_header = installer->rpm->payload;
  23.630 +	if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
  23.631 +		fprintf(stderr, "payload section doesn't have gz header\n");
  23.632 +		return -1;
  23.633 +	}
  23.634 +
  23.635 +	method = gz_header[2];
  23.636 +	flags = gz_header[3];
  23.637 +
  23.638 +	if (method != Z_DEFLATED || flags != 0) {
  23.639 +		fprintf(stderr,
  23.640 +			"unknown payload compression method or flags set\n");
  23.641 +		return -1;
  23.642 +	}
  23.643 +
  23.644 +	installer->stream.zalloc = NULL;
  23.645 +	installer->stream.zfree = NULL;
  23.646 +	installer->stream.opaque = NULL;
  23.647 +
  23.648 +	installer->stream.next_in  = gz_header + 10;
  23.649 +	installer->stream.avail_in =
  23.650 +		(installer->rpm->map + installer->rpm->size) -
  23.651 +		(void *) installer->stream.next_in;
  23.652 +	installer->stream.next_out = NULL;
  23.653 +	installer->stream.avail_out = 0;
  23.654 +
  23.655 +	err = inflateInit2(&installer->stream, -MAX_WBITS);
  23.656 +	if (err != Z_OK) {
  23.657 +		fprintf(stderr, "inflateInit error: %d\n", err);
  23.658 +		return -1;
  23.659 +	}
  23.660 +
  23.661 +	return 0;
  23.662 +}
  23.663 +
  23.664 +static int
  23.665 +installer_finish(struct installer *installer)
  23.666 +{
  23.667 +	int err;
  23.668 +
  23.669 +	err = inflateEnd(&installer->stream);
  23.670 +
  23.671 +	if (err != Z_OK) {
  23.672 +		fprintf(stderr, "inflateEnd error: %d\n", err);
  23.673 +		return -1;
  23.674 +	}
  23.675 +
  23.676 +	return 0;
  23.677 +}
  23.678 +
  23.679 +static unsigned long
  23.680 +fixed_hex_to_ulong(const char *hex, int length)
  23.681 +{
  23.682 +	long l;
  23.683 +	int i;
  23.684 +
  23.685 +	for (i = 0, l = 0; i < length; i++) {
  23.686 +		if (hex[i] < 'a')
  23.687 +			l = l * 16 + hex[i] - '0';
  23.688 +		else
  23.689 +			l = l * 16 + hex[i] - 'a' + 10;
  23.690 +	}
  23.691 +
  23.692 +	return l;
  23.693 +}
  23.694 +
  23.695 +int
  23.696 +razor_rpm_install(struct razor_rpm *rpm, const char *root)
  23.697 +{
  23.698 +	struct installer installer;
  23.699 +	struct cpio_file_header *header;
  23.700 +	struct stat buf;
  23.701 +	unsigned int mode;
  23.702 +	char *path;
  23.703 +	size_t filesize;
  23.704 +
  23.705 +	installer.rpm = rpm;
  23.706 +	installer.root = root;
  23.707 +
  23.708 +	/* FIXME: Only do this before a transaction, not per rpm. */
  23.709 +	if (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
  23.710 +		fprintf(stderr,
  23.711 +			"root installation directory \"%s\" does not exist\n",
  23.712 +			root);
  23.713 +		return -1;
  23.714 +	}
  23.715 +
  23.716 +	if (installer_init(&installer))
  23.717 +		return -1;
  23.718 +
  23.719 +	run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
  23.720 +
  23.721 +	while (installer.stream.avail_in > 0) {
  23.722 +		installer.rest = sizeof *header;
  23.723 +		if (installer_inflate(&installer))
  23.724 +			return -1;
  23.725 +
  23.726 +		header = (struct cpio_file_header *) installer.buffer;
  23.727 +		mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
  23.728 +		filesize = fixed_hex_to_ulong(header->filesize,
  23.729 +					      sizeof header->filesize);
  23.730 +
  23.731 +		installer.rest = fixed_hex_to_ulong(header->namesize,
  23.732 +						    sizeof header->namesize);
  23.733 +
  23.734 +		if (installer_inflate(&installer) ||
  23.735 +		    installer_align(&installer, 4))
  23.736 +			return -1;
  23.737 +
  23.738 +		path = (char *) installer.buffer;
  23.739 +		/* This convention is so lame... */
  23.740 +		if (strcmp(path, "TRAILER!!!") == 0)
  23.741 +			break;
  23.742 +
  23.743 +		installer.rest = filesize;
  23.744 +		if (create_path(&installer, path + 1, mode) < 0)
  23.745 +			return -1;
  23.746 +		if (installer_align(&installer, 4))
  23.747 +			return -1;
  23.748 +	}
  23.749 +
  23.750 +	if (installer_finish(&installer))
  23.751 +		return -1;
  23.752 +
  23.753 +	run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
  23.754 +
  23.755 +	return 0;
  23.756 +}
  23.757 +
  23.758 +int
  23.759 +razor_rpm_close(struct razor_rpm *rpm)
  23.760 +{
  23.761 +	int err;
  23.762 +
  23.763 +	free(rpm->dirs);
  23.764 +	err = munmap(rpm->map, rpm->size);
  23.765 +	free(rpm);
  23.766 +
  23.767 +	return err;
  23.768 +}
  23.769 +
  23.770 +int
  23.771 +razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
  23.772 +{
  23.773 +	const char *name, *version, *release, *arch;
  23.774 +	const uint32_t *epoch;
  23.775 +	char evr[128], buf[16];
  23.776 +
  23.777 +	name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
  23.778 +	epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
  23.779 +	version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
  23.780 +	release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
  23.781 +	arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
  23.782 +
  23.783 +	if (epoch) {
  23.784 +		snprintf(buf, sizeof buf, "%u", ntohl(*epoch));
  23.785 +		razor_build_evr(evr, sizeof evr, buf, version, release);
  23.786 +	} else {
  23.787 +		razor_build_evr(evr, sizeof evr, NULL, version, release);
  23.788 +	}
  23.789 +	razor_importer_begin_package(importer, name, evr, arch);
  23.790 +
  23.791 +	import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
  23.792 +			  RPMTAG_REQUIRENAME,
  23.793 +			  RPMTAG_REQUIREVERSION,
  23.794 +			  RPMTAG_REQUIREFLAGS);
  23.795 +
  23.796 +	import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
  23.797 +			  RPMTAG_PROVIDENAME,
  23.798 +			  RPMTAG_PROVIDEVERSION,
  23.799 +			  RPMTAG_PROVIDEFLAGS);
  23.800 +
  23.801 +	import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
  23.802 +			  RPMTAG_OBSOLETENAME,
  23.803 +			  RPMTAG_OBSOLETEVERSION,
  23.804 +			  RPMTAG_OBSOLETEFLAGS);
  23.805 +
  23.806 +	import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
  23.807 +			  RPMTAG_CONFLICTNAME,
  23.808 +			  RPMTAG_CONFLICTVERSION,
  23.809 +			  RPMTAG_CONFLICTFLAGS);
  23.810 +
  23.811 +	import_files(importer, rpm);
  23.812 +
  23.813 +	razor_importer_finish_package(importer);
  23.814 +
  23.815 +	return 0;
  23.816 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/librazor/types.c	Mon Jun 16 15:40:30 2008 -0400
    24.3 @@ -0,0 +1,246 @@
    24.4 +#include <stdlib.h>
    24.5 +#include <string.h>
    24.6 +
    24.7 +#include "types.h"
    24.8 +
    24.9 +void
   24.10 +array_init(struct array *array)
   24.11 +{
   24.12 +	memset(array, 0, sizeof *array);
   24.13 +}
   24.14 +
   24.15 +void
   24.16 +array_release(struct array *array)
   24.17 +{
   24.18 +	free(array->data);
   24.19 +}
   24.20 +
   24.21 +void *
   24.22 +array_add(struct array *array, int size)
   24.23 +{
   24.24 +	int alloc;
   24.25 +	void *data, *p;
   24.26 +
   24.27 +	if (array->alloc > 0)
   24.28 +		alloc = array->alloc;
   24.29 +	else
   24.30 +		alloc = 16;
   24.31 +
   24.32 +	while (alloc < array->size + size)
   24.33 +		alloc *= 2;
   24.34 +
   24.35 +	if (array->alloc < alloc) {
   24.36 +		data = realloc(array->data, alloc);
   24.37 +		if (data == NULL)
   24.38 +			return 0;
   24.39 +		array->data = data;
   24.40 +		array->alloc = alloc;
   24.41 +	}
   24.42 +
   24.43 +	p = array->data + array->size;
   24.44 +	array->size += size;
   24.45 +
   24.46 +	return p;
   24.47 +}
   24.48 +
   24.49 +/* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
   24.50 +#define RAZOR_ENTRY_LAST 0x80
   24.51 +#define RAZOR_IMMEDIATE  0x80
   24.52 +#define RAZOR_EMPTY_LIST 0xff
   24.53 +
   24.54 +void
   24.55 +list_set_empty(struct list_head *head)
   24.56 +{
   24.57 +	head->list_ptr = ~0;
   24.58 +	head->flags = RAZOR_EMPTY_LIST;
   24.59 +}
   24.60 +
   24.61 +void
   24.62 +list_set_ptr(struct list_head *head, uint32_t ptr)
   24.63 +{
   24.64 +	head->list_ptr = ptr;
   24.65 +	head->flags = 0;
   24.66 +}
   24.67 +
   24.68 +void
   24.69 +list_set_array(struct list_head *head, struct array *pool,
   24.70 +	       struct array *items, int force_indirect)
   24.71 +{
   24.72 +	struct list *p;
   24.73 +
   24.74 +	if (!force_indirect) {
   24.75 +		if (items->size == 0) {
   24.76 +			list_set_empty(head);
   24.77 +			return;
   24.78 +		} else if (items->size == sizeof (uint32_t)) {
   24.79 +			head->list_ptr = *(uint32_t *) items->data;
   24.80 +			head->flags = RAZOR_IMMEDIATE;
   24.81 +			return;
   24.82 +		}
   24.83 +	}
   24.84 +
   24.85 +	p = array_add(pool, items->size);
   24.86 +	memcpy(p, items->data, items->size);
   24.87 +	p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
   24.88 +	list_set_ptr(head, p - (struct list *) pool->data);
   24.89 +}
   24.90 +
   24.91 +struct list *
   24.92 +list_first(struct list_head *head, struct array *pool)
   24.93 +{
   24.94 +	if (head->flags == RAZOR_EMPTY_LIST)
   24.95 +		return NULL;
   24.96 +	else if (head->flags == RAZOR_IMMEDIATE)
   24.97 +		return (struct list *) head;
   24.98 +	else
   24.99 +		return (struct list *) pool->data + head->list_ptr;
  24.100 +}
  24.101 +
  24.102 +struct list *
  24.103 +list_next(struct list *list)
  24.104 +{
  24.105 +	if (list->flags)
  24.106 +		return NULL;
  24.107 +	return ++list;
  24.108 +}
  24.109 +
  24.110 +void
  24.111 +list_remap_pool(struct array *pool, uint32_t *map)
  24.112 +{
  24.113 +	struct list *p, *end;
  24.114 +
  24.115 +	end = pool->data + pool->size;
  24.116 +	for (p = pool->data; p < end; p++)
  24.117 +		p->data = map[p->data];
  24.118 +}
  24.119 +
  24.120 +void
  24.121 +list_remap_head(struct list_head *head, uint32_t *map)
  24.122 +{
  24.123 +	if (head->flags == RAZOR_IMMEDIATE)
  24.124 +		head->list_ptr = map[head->list_ptr];
  24.125 +}
  24.126 +
  24.127 +
  24.128 +void
  24.129 +hashtable_init(struct hashtable *table, struct array *pool)
  24.130 +{
  24.131 +	array_init(&table->buckets);
  24.132 +	table->pool = pool;
  24.133 +}
  24.134 +
  24.135 +void
  24.136 +hashtable_release(struct hashtable *table)
  24.137 +{
  24.138 +	array_release(&table->buckets);
  24.139 +}
  24.140 +
  24.141 +static unsigned int
  24.142 +hash_string(const char *key)
  24.143 +{
  24.144 +	const char *p;
  24.145 +	unsigned int hash = 0;
  24.146 +
  24.147 +	for (p = key; *p; p++)
  24.148 +		hash = (hash * 617) ^ *p;
  24.149 +
  24.150 +	return hash;
  24.151 +}
  24.152 +
  24.153 +uint32_t
  24.154 +hashtable_lookup(struct hashtable *table, const char *key)
  24.155 +{
  24.156 +	unsigned int mask, start, i;
  24.157 +	uint32_t *b;
  24.158 +	char *pool;
  24.159 +
  24.160 +	pool = table->pool->data;
  24.161 +	mask = table->buckets.alloc - 1;
  24.162 +	start = hash_string(key) * sizeof(uint32_t);
  24.163 +
  24.164 +	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  24.165 +		b = table->buckets.data + ((start + i) & mask);
  24.166 +
  24.167 +		if (*b == 0)
  24.168 +			return 0;
  24.169 +
  24.170 +		if (strcmp(key, &pool[*b]) == 0)
  24.171 +			return *b;
  24.172 +	}
  24.173 +
  24.174 +	return 0;
  24.175 +}
  24.176 +
  24.177 +static void
  24.178 +do_insert(struct hashtable *table, uint32_t value)
  24.179 +{
  24.180 +	unsigned int mask, start, i;
  24.181 +	uint32_t *b;
  24.182 +	const char *key;
  24.183 +
  24.184 +	key = (char *) table->pool->data + value;
  24.185 +	mask = table->buckets.alloc - 1;
  24.186 +	start = hash_string(key) * sizeof(uint32_t);
  24.187 +
  24.188 +	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  24.189 +		b = table->buckets.data + ((start + i) & mask);
  24.190 +		if (*b == 0) {
  24.191 +			*b = value;
  24.192 +			break;
  24.193 +		}
  24.194 +	}
  24.195 +}
  24.196 +
  24.197 +static uint32_t
  24.198 +add_to_string_pool(struct hashtable *table, const char *key)
  24.199 +{
  24.200 +	int len;
  24.201 +	char *p;
  24.202 +
  24.203 +	len = strlen(key) + 1;
  24.204 +	p = array_add(table->pool, len);
  24.205 +	memcpy(p, key, len);
  24.206 +
  24.207 +	return p - (char *) table->pool->data;
  24.208 +}
  24.209 +
  24.210 +uint32_t
  24.211 +hashtable_insert(struct hashtable *table, const char *key)
  24.212 +{
  24.213 +	uint32_t value, *buckets, *b, *end;
  24.214 +	int alloc;
  24.215 +
  24.216 +	alloc = table->buckets.alloc;
  24.217 +	array_add(&table->buckets, 4 * sizeof *buckets);
  24.218 +	if (alloc != table->buckets.alloc) {
  24.219 +		end = table->buckets.data + alloc;
  24.220 +		memset(end, 0, table->buckets.alloc - alloc);
  24.221 +		for (b = table->buckets.data; b < end; b++) {
  24.222 +			value = *b;
  24.223 +			if (value != 0) {
  24.224 +				*b = 0;
  24.225 +				do_insert(table, value);
  24.226 +			}
  24.227 +		}
  24.228 +	}
  24.229 +
  24.230 +	value = add_to_string_pool(table, key);
  24.231 +	do_insert (table, value);
  24.232 +
  24.233 +	return value;
  24.234 +}
  24.235 +
  24.236 +uint32_t
  24.237 +hashtable_tokenize(struct hashtable *table, const char *string)
  24.238 +{
  24.239 +	uint32_t token;
  24.240 +
  24.241 +	if (string == NULL)
  24.242 +		string = "";
  24.243 +
  24.244 +	token = hashtable_lookup(table, string);
  24.245 +	if (token != 0)
  24.246 +		return token;
  24.247 +
  24.248 +	return hashtable_insert(table, string);
  24.249 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/librazor/types.h	Mon Jun 16 15:40:30 2008 -0400
    25.3 @@ -0,0 +1,59 @@
    25.4 +#ifndef _RAZOR_TYPES_H_
    25.5 +#define _RAZOR_TYPES_H_
    25.6 +
    25.7 +#include <stdint.h>
    25.8 +
    25.9 +struct array {
   25.10 +	void *data;
   25.11 +	int size, alloc;
   25.12 +};
   25.13 +
   25.14 +void array_init(struct array *array);
   25.15 +void array_release(struct array *array);
   25.16 +void *array_add(struct array *array, int size);
   25.17 +
   25.18 +
   25.19 +struct list_head {
   25.20 +	uint list_ptr : 24;
   25.21 +	uint flags    : 8;
   25.22 +};
   25.23 +
   25.24 +struct list {
   25.25 +	uint data  : 24;
   25.26 +	uint flags : 8;
   25.27 +};
   25.28 +
   25.29 +void list_set_empty(struct list_head *head);
   25.30 +void list_set_ptr(struct list_head *head, uint32_t ptr);
   25.31 +void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
   25.32 +
   25.33 +struct list *list_first(struct list_head *head, struct array *pool);
   25.34 +struct list *list_next(struct list *list);
   25.35 +
   25.36 +void list_remap_pool(struct array *pool, uint32_t *map);
   25.37 +void list_remap_head(struct list_head *list, uint32_t *map);
   25.38 +
   25.39 +
   25.40 +struct hashtable {
   25.41 +	struct array buckets;
   25.42 +	struct array *pool;
   25.43 +};
   25.44 +
   25.45 +void hashtable_init(struct hashtable *table, struct array *pool);
   25.46 +void hashtable_release(struct hashtable *table);
   25.47 +uint32_t hashtable_insert(struct hashtable *table, const char *key);
   25.48 +uint32_t hashtable_lookup(struct hashtable *table, const char *key);
   25.49 +uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
   25.50 +
   25.51 +
   25.52 +struct bitarray {
   25.53 +	uint32_t *bits;
   25.54 +};
   25.55 +
   25.56 +void bitarray_init(struct bitarray *bitarray, int size, int intial_value);
   25.57 +void bitarray_release(struct bitarray *bitarray);
   25.58 +void bitarray_set(struct bitarray *bitarray, int bit, int value);
   25.59 +int bitarray_get(struct bitarray *bitarray, int bit);
   25.60 +
   25.61 +
   25.62 +#endif /* _RAZOR_TYPES_H_ */
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/librazor/util.c	Mon Jun 16 15:40:30 2008 -0400
    26.3 @@ -0,0 +1,167 @@
    26.4 +#include <limits.h>
    26.5 +#include <string.h>
    26.6 +#include <sys/stat.h>
    26.7 +#include <stdlib.h>
    26.8 +#include <stdio.h>
    26.9 +#include <stdint.h>
   26.10 +#include <unistd.h>
   26.11 +
   26.12 +#include "razor-internal.h"
   26.13 +
   26.14 +int
   26.15 +razor_create_dir(const char *root, const char *path)
   26.16 +{
   26.17 +	char buffer[PATH_MAX], *p;
   26.18 +	const char *slash, *next;
   26.19 +	struct stat buf;
   26.20 +
   26.21 +	/* Create all sub-directories in dir. We know root exists and
   26.22 +	 * is a dir, root does not end in a '/', and path has a
   26.23 +	 * leading '/'. */
   26.24 +
   26.25 +	strcpy(buffer, root);
   26.26 +	p = buffer + strlen(buffer);
   26.27 +	slash = path;
   26.28 +	for (slash = path; *slash != '\0'; slash = next) {
   26.29 +		next = strchr(slash + 1, '/');
   26.30 +		if (next == NULL)
   26.31 +			break;
   26.32 +
   26.33 +		memcpy(p, slash, next - slash);
   26.34 +		p += next - slash;
   26.35 +		*p = '\0';
   26.36 +
   26.37 +		if (stat(buffer, &buf) == 0) {
   26.38 +			if (!S_ISDIR(buf.st_mode)) {
   26.39 +				fprintf(stderr,
   26.40 +					"%s exists but is not a directory\n",
   26.41 +					buffer);
   26.42 +				return -1;
   26.43 +			}
   26.44 +		} else if (mkdir(buffer, 0777) < 0) {
   26.45 +			fprintf(stderr, "failed to make directory %s: %m\n",
   26.46 +				buffer);
   26.47 +			return -1;
   26.48 +		}
   26.49 +
   26.50 +		/* FIXME: What to do about permissions for dirs we
   26.51 +		 * have to create but are not in the cpio archive? */
   26.52 +	}
   26.53 +
   26.54 +	return 0;
   26.55 +}
   26.56 +
   26.57 +int
   26.58 +razor_write(int fd, const void *data, size_t size)
   26.59 +{
   26.60 +	size_t rest;
   26.61 +	ssize_t written;
   26.62 +	const unsigned char *p;
   26.63 +
   26.64 +	rest = size;
   26.65 +	p = data;
   26.66 +	while (rest > 0) {
   26.67 +		written = write(fd, p, rest);
   26.68 +		if (written < 0) {
   26.69 +			fprintf(stderr, "write error: %m\n");
   26.70 +			return -1;
   26.71 +		}
   26.72 +		rest -= written;
   26.73 +		p += written;
   26.74 +	}
   26.75 +
   26.76 +	return 0;
   26.77 +}
   26.78 +
   26.79 +struct qsort_context {
   26.80 +	size_t size;
   26.81 +	razor_compare_with_data_func_t compare;
   26.82 +	void *data;
   26.83 +};
   26.84 +
   26.85 +static void
   26.86 +qsort_swap(void *p1, void *p2, size_t size)
   26.87 +{
   26.88 +	char buffer[size];
   26.89 +
   26.90 +	memcpy(buffer, p1, size);
   26.91 +	memcpy(p1, p2, size);
   26.92 +	memcpy(p2, buffer, size);
   26.93 +}
   26.94 +
   26.95 +static void
   26.96 +__qsort_with_data(void *base, size_t nelem, uint32_t *map,
   26.97 +		  struct qsort_context *ctx)
   26.98 +{
   26.99 +	void *p, *start, *end, *pivot;
  26.100 +	uint32_t *mp, *mstart, *mend, tmp;
  26.101 +	int left, right, result;
  26.102 +	size_t size = ctx->size;
  26.103 +
  26.104 +	p = base;
  26.105 +	start = base;
  26.106 +	end = base + nelem * size;
  26.107 +	mp = map;
  26.108 +	mstart = map;
  26.109 +	mend = map + nelem;
  26.110 +	pivot = base + (random() % nelem) * size;
  26.111 +
  26.112 +	while (p < end) {
  26.113 +		result = ctx->compare(p, pivot, ctx->data);
  26.114 +		if (result < 0) {
  26.115 +			qsort_swap(p, start, size);
  26.116 +			tmp = *mp;
  26.117 +			*mp = *mstart;
  26.118 +			*mstart = tmp;
  26.119 +			if (start == pivot)
  26.120 +				pivot = p;
  26.121 +			start += size;
  26.122 +			mstart++;
  26.123 +			p += size;
  26.124 +			mp++;
  26.125 +		} else if (result == 0) {
  26.126 +			p += size;
  26.127 +			mp++;
  26.128 +		} else {
  26.129 + 			end -= size;
  26.130 +			mend--;
  26.131 +			qsort_swap(p, end, size);
  26.132 +			tmp = *mp;
  26.133 +			*mp = *mend;
  26.134 +			*mend = tmp;
  26.135 +			if (end == pivot)
  26.136 +				pivot = p;
  26.137 +		}
  26.138 +	}
  26.139 +
  26.140 +	left = (start - base) / size;
  26.141 +	right = (base + nelem * size - end) / size;
  26.142 +	if (left > 1)
  26.143 +		__qsort_with_data(base, left, map, ctx);
  26.144 +	if (right > 1)
  26.145 +		__qsort_with_data(end, right, mend, ctx);
  26.146 +}
  26.147 +
  26.148 +uint32_t *
  26.149 +razor_qsort_with_data(void *base, size_t nelem, size_t size,
  26.150 +		      razor_compare_with_data_func_t compare, void *data)
  26.151 +{
  26.152 +	struct qsort_context ctx;
  26.153 +	uint32_t *map;
  26.154 +	int i;
  26.155 +
  26.156 +	if (nelem == 0)
  26.157 +		return NULL;
  26.158 +
  26.159 +	ctx.size = size;
  26.160 +	ctx.compare = compare;
  26.161 +	ctx.data = data;
  26.162 +
  26.163 +	map = malloc(nelem * sizeof (uint32_t));
  26.164 +	for (i = 0; i < nelem; i++)
  26.165 +		map[i] = i;
  26.166 +
  26.167 +	__qsort_with_data(base, nelem, map, &ctx);
  26.168 +
  26.169 +	return map;
  26.170 +}
    27.1 --- a/main.c	Sun Jun 15 23:15:59 2008 -0400
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,804 +0,0 @@
    27.4 -/*
    27.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    27.6 - * Copyright (C) 2008  Red Hat, Inc
    27.7 - *
    27.8 - * This program is free software; you can redistribute it and/or modify
    27.9 - * it under the terms of the GNU General Public License as published by
   27.10 - * the Free Software Foundation; either version 2 of the License, or
   27.11 - * (at your option) any later version.
   27.12 - *
   27.13 - * This program is distributed in the hope that it will be useful,
   27.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.16 - * GNU General Public License for more details.
   27.17 - *
   27.18 - * You should have received a copy of the GNU General Public License along
   27.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   27.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   27.21 - */
   27.22 -
   27.23 -#include <stdlib.h>
   27.24 -#include <stddef.h>
   27.25 -#include <stdio.h>
   27.26 -#include <stdint.h>
   27.27 -#include <string.h>
   27.28 -#include <sys/stat.h>
   27.29 -#include <unistd.h>
   27.30 -#include <fcntl.h>
   27.31 -#include <dirent.h>
   27.32 -#include <curl/curl.h>
   27.33 -#include <fnmatch.h>
   27.34 -#include <errno.h>
   27.35 -#include "razor.h"
   27.36 -
   27.37 -static const char system_repo_filename[] = "system.repo";
   27.38 -static const char next_repo_filename[] = "system-next.repo";
   27.39 -static const char rawhide_repo_filename[] = "rawhide.repo";
   27.40 -static const char updated_repo_filename[] = "system-updated.repo";
   27.41 -static const char install_root[] = "install";
   27.42 -static const char *repo_filename = system_repo_filename;
   27.43 -static const char *yum_url;
   27.44 -
   27.45 -static int
   27.46 -command_list(int argc, const char *argv[])
   27.47 -{
   27.48 -	struct razor_set *set;
   27.49 -	struct razor_package_iterator *pi;
   27.50 -	struct razor_package *package;
   27.51 -	const char *pattern, *name, *version, *arch;
   27.52 -	int only_names = 0, i = 0;
   27.53 -
   27.54 -	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
   27.55 -		only_names = 1;
   27.56 -		i++;
   27.57 -	}
   27.58 -
   27.59 -	pattern = argv[i];
   27.60 -	set = razor_set_open(repo_filename);
   27.61 -	pi = razor_package_iterator_create(set);
   27.62 -	while (razor_package_iterator_next(pi, &package,
   27.63 -					   &name, &version, &arch)) {
   27.64 -		if (pattern && fnmatch(pattern, name, 0) != 0)
   27.65 -			continue;
   27.66 -
   27.67 -		if (only_names)
   27.68 -			printf("%s\n", name);
   27.69 -		else
   27.70 -			printf("%s-%s.%s\n", name, version, arch);
   27.71 -	}
   27.72 -	razor_package_iterator_destroy(pi);
   27.73 -	razor_set_destroy(set);
   27.74 -
   27.75 -	return 0;
   27.76 -}
   27.77 -
   27.78 -static int
   27.79 -list_properties(const char *package_name,
   27.80 -		enum razor_property_type required_type)
   27.81 -{
   27.82 -	static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
   27.83 -	struct razor_set *set;
   27.84 -	struct razor_property *property;
   27.85 -	struct razor_package *package;
   27.86 -	struct razor_property_iterator *pi;
   27.87 -	const char *name, *version;
   27.88 -	enum razor_property_type type;
   27.89 -	enum razor_version_relation relation;
   27.90 -
   27.91 -	set = razor_set_open(repo_filename);
   27.92 -	if (package_name)
   27.93 -		package = razor_set_get_package(set, package_name);
   27.94 -	else
   27.95 -		package = NULL;
   27.96 -
   27.97 -	pi = razor_property_iterator_create(set, package);
   27.98 -	while (razor_property_iterator_next(pi, &property,
   27.99 -					    &name, &relation, &version,
  27.100 -					    &type)) {
  27.101 -		if (type != required_type)
  27.102 -			continue;
  27.103 -		if (version[0] == '\0')
  27.104 -			printf("%s\n", name);
  27.105 -		else
  27.106 -			printf("%s %s %s\n", name,
  27.107 -			       relation_string[relation], version);
  27.108 -	}
  27.109 -	razor_property_iterator_destroy(pi);
  27.110 -
  27.111 -	razor_set_destroy(set);
  27.112 -
  27.113 -	return 0;
  27.114 -}
  27.115 -
  27.116 -static int
  27.117 -command_list_requires(int argc, const char *argv[])
  27.118 -{
  27.119 -	return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
  27.120 -}
  27.121 -
  27.122 -static int
  27.123 -command_list_provides(int argc, const char *argv[])
  27.124 -{
  27.125 -	return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
  27.126 -}
  27.127 -
  27.128 -static int
  27.129 -command_list_obsoletes(int argc, const char *argv[])
  27.130 -{
  27.131 -	return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
  27.132 -}
  27.133 -
  27.134 -static int
  27.135 -command_list_conflicts(int argc, const char *argv[])
  27.136 -{
  27.137 -	return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
  27.138 -}
  27.139 -
  27.140 -static int
  27.141 -command_list_files(int argc, const char *argv[])
  27.142 -{
  27.143 -	struct razor_set *set;
  27.144 -
  27.145 -	set = razor_set_open(repo_filename);
  27.146 -	if (set == NULL)
  27.147 -		return 1;
  27.148 -	razor_set_list_files(set, argv[0]);
  27.149 -	razor_set_destroy(set);
  27.150 -
  27.151 -	return 0;
  27.152 -}
  27.153 -
  27.154 -static int
  27.155 -command_list_file_packages(int argc, const char *argv[])
  27.156 -{
  27.157 -	struct razor_set *set;
  27.158 -	struct razor_package_iterator *pi;
  27.159 -	struct razor_package *package;
  27.160 -	const char *name, *version, *arch;
  27.161 -
  27.162 -	set = razor_set_open(repo_filename);
  27.163 -	if (set == NULL)
  27.164 -		return 1;
  27.165 -
  27.166 -	pi = razor_package_iterator_create_for_file(set, argv[0]);
  27.167 -	while (razor_package_iterator_next(pi, &package,
  27.168 -					   &name, &version, &arch))
  27.169 -		printf("%s-%s\n", name, version);
  27.170 -	razor_package_iterator_destroy(pi);
  27.171 -
  27.172 -	razor_set_destroy(set);
  27.173 -
  27.174 -	return 0;
  27.175 -}
  27.176 -
  27.177 -static int
  27.178 -command_list_package_files(int argc, const char *argv[])
  27.179 -{
  27.180 -	struct razor_set *set;
  27.181 -
  27.182 -	set = razor_set_open(repo_filename);
  27.183 -	if (set == NULL)
  27.184 -		return 1;
  27.185 -	razor_set_list_package_files(set, argv[0]);
  27.186 -	razor_set_destroy(set);
  27.187 -
  27.188 -	return 0;
  27.189 -}
  27.190 -
  27.191 -static void
  27.192 -list_packages_for_property(struct razor_set *set,
  27.193 -			   struct razor_property *property)
  27.194 -{
  27.195 -	struct razor_package_iterator *pi;
  27.196 -	struct razor_package *package;
  27.197 -	const char *name, *version, *arch;
  27.198 -
  27.199 -	pi = razor_package_iterator_create_for_property(set, property);
  27.200 -	while (razor_package_iterator_next(pi, &package,
  27.201 -					   &name, &version, &arch))
  27.202 -		printf("%s-%s.%s\n", name, version, arch);
  27.203 -	razor_package_iterator_destroy(pi);
  27.204 -}
  27.205 -
  27.206 -static int
  27.207 -list_property_packages(const char *ref_name,
  27.208 -		       const char *ref_version,
  27.209 -		       enum razor_property_type ref_type)
  27.210 -{
  27.211 -	struct razor_set *set;
  27.212 -	struct razor_property *property;
  27.213 -	struct razor_property_iterator *pi;
  27.214 -	const char *name, *version;
  27.215 -	enum razor_property_type type;
  27.216 -	enum razor_version_relation relation;
  27.217 -
  27.218 -	if (ref_name == NULL)
  27.219 -		return 0;
  27.220 -
  27.221 -	set = razor_set_open(repo_filename);
  27.222 -	if (set == NULL)
  27.223 -		return 1;
  27.224 -
  27.225 -	pi = razor_property_iterator_create(set, NULL);
  27.226 -	while (razor_property_iterator_next(pi, &property,
  27.227 -					    &name, &relation, &version,
  27.228 -					    &type)) {
  27.229 -		if (strcmp(ref_name, name) != 0)
  27.230 -			continue;
  27.231 -		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
  27.232 -		    strcmp(ref_version, version) != 0)
  27.233 -			continue;
  27.234 -		if (ref_type != type)
  27.235 -			continue;
  27.236 -
  27.237 -		list_packages_for_property(set, property);
  27.238 -	}
  27.239 -	razor_property_iterator_destroy(pi);
  27.240 -
  27.241 -	return 0;
  27.242 -}
  27.243 -
  27.244 -static int
  27.245 -command_what_requires(int argc, const char *argv[])
  27.246 -{
  27.247 -	return list_property_packages(argv[0], argv[1],
  27.248 -				      RAZOR_PROPERTY_REQUIRES);
  27.249 -}
  27.250 -
  27.251 -static int
  27.252 -command_what_provides(int argc, const char *argv[])
  27.253 -{
  27.254 -	return list_property_packages(argv[0], argv[1],
  27.255 -				      RAZOR_PROPERTY_PROVIDES);
  27.256 -}
  27.257 -
  27.258 -static int
  27.259 -show_progress(void *clientp,
  27.260 -	      double dltotal, double dlnow, double ultotal, double ulnow)
  27.261 -{
  27.262 -	const char *file = clientp;
  27.263 -
  27.264 -	if (!dlnow < dltotal)
  27.265 -		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
  27.266 -			file, (int) dlnow / 1024, (int) dltotal / 1024);
  27.267 -
  27.268 -	return 0;
  27.269 -}
  27.270 -
  27.271 -static int
  27.272 -download_if_missing(const char *url, const char *file)
  27.273 -{
  27.274 -	CURL *curl;
  27.275 -	struct stat buf;
  27.276 -	char error[256];
  27.277 -	FILE *fp;
  27.278 -	CURLcode res;
  27.279 -	long response;
  27.280 -
  27.281 -	curl = curl_easy_init();
  27.282 -	if (curl == NULL)
  27.283 -		return 1;
  27.284 -
  27.285 -	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
  27.286 -	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
  27.287 -	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
  27.288 -	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
  27.289 -
  27.290 -	if (stat(file, &buf) < 0) {
  27.291 -		fp = fopen(file, "w");
  27.292 -		if (fp == NULL) {
  27.293 -			fprintf(stderr,
  27.294 -				"failed to open %s for writing\n", file);
  27.295 -			return -1;
  27.296 -		}
  27.297 -		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
  27.298 -		curl_easy_setopt(curl, CURLOPT_URL, url);
  27.299 -		res = curl_easy_perform(curl);
  27.300 -		fclose(fp);
  27.301 -		if (res != CURLE_OK) {
  27.302 -			fprintf(stderr, "curl error: %s\n", error);
  27.303 -			unlink(file);
  27.304 -			return -1;
  27.305 -		}
  27.306 -		res = curl_easy_getinfo(curl,
  27.307 -					CURLINFO_RESPONSE_CODE, &response);
  27.308 -		if (res != CURLE_OK) {
  27.309 -			fprintf(stderr, "curl error: %s\n", error);
  27.310 -                        unlink(file);
  27.311 -                        return -1;
  27.312 -		}
  27.313 -		if (response != 200) {
  27.314 -			fprintf(stderr, " - failed %ld\n", response);
  27.315 -                        unlink(file);
  27.316 -                        return -1;
  27.317 -		}
  27.318 -		fprintf(stderr, "\n");
  27.319 -	}
  27.320 -
  27.321 -	curl_easy_cleanup(curl);
  27.322 -
  27.323 -	return 0;
  27.324 -}
  27.325 -
  27.326 -#define YUM_URL "http://download.fedora.redhat.com" \
  27.327 -	"/pub/fedora/linux/development/i386/os"
  27.328 -
  27.329 -static int
  27.330 -command_import_yum(int argc, const char *argv[])
  27.331 -{
  27.332 -	struct razor_set *set;
  27.333 -	char buffer[512];
  27.334 -
  27.335 -	printf("downloading from %s.\n", yum_url);
  27.336 -	snprintf(buffer, sizeof buffer,
  27.337 -		 "%s/repodata/primary.xml.gz", yum_url);
  27.338 -	if (download_if_missing(buffer, "primary.xml.gz") < 0)
  27.339 -		return -1;
  27.340 -	snprintf(buffer, sizeof buffer,
  27.341 -		 "%s/repodata/filelists.xml.gz", yum_url);
  27.342 -	if (download_if_missing(buffer, "filelists.xml.gz") < 0)
  27.343 -		return -1;
  27.344 -
  27.345 -	set = razor_set_create_from_yum();
  27.346 -	if (set == NULL)
  27.347 -		return 1;
  27.348 -	razor_set_write(set, rawhide_repo_filename);
  27.349 -	razor_set_destroy(set);
  27.350 -	printf("wrote %s\n", rawhide_repo_filename);
  27.351 -
  27.352 -	return 0;
  27.353 -}
  27.354 -
  27.355 -static int
  27.356 -command_import_rpmdb(int argc, const char *argv[])
  27.357 -{
  27.358 -	struct razor_set *set;
  27.359 -
  27.360 -	set = razor_set_create_from_rpmdb();
  27.361 -	if (set == NULL)
  27.362 -		return 1;
  27.363 -	razor_set_write(set, repo_filename);
  27.364 -	razor_set_destroy(set);
  27.365 -	printf("wrote %s\n", repo_filename);
  27.366 -
  27.367 -	return 0;
  27.368 -}
  27.369 -
  27.370 -static int
  27.371 -mark_packages_for_update(struct razor_transaction *trans,
  27.372 -			 struct razor_set *set, const char *pattern)
  27.373 -{
  27.374 -	struct razor_package_iterator *pi;
  27.375 -	struct razor_package *package;
  27.376 -	const char *name, *version, *arch;
  27.377 -	int matches = 0;
  27.378 -
  27.379 -	pi = razor_package_iterator_create(set);
  27.380 -	while (razor_package_iterator_next(pi, &package,
  27.381 -					   &name, &version, &arch)) {
  27.382 -		if (pattern && fnmatch(pattern, name, 0) == 0) {
  27.383 -			razor_transaction_update_package(trans, package);
  27.384 -			matches++;
  27.385 -		}
  27.386 -	}
  27.387 -	razor_package_iterator_destroy(pi);
  27.388 -
  27.389 -	return matches;
  27.390 -}
  27.391 -
  27.392 -static int
  27.393 -mark_packages_for_removal(struct razor_transaction *trans,
  27.394 -			  struct razor_set *set, const char *pattern)
  27.395 -{
  27.396 -	struct razor_package_iterator *pi;
  27.397 -	struct razor_package *package;
  27.398 -	const char *name, *version, *arch;
  27.399 -	int matches = 0;
  27.400 -
  27.401 -	pi = razor_package_iterator_create(set);
  27.402 -	while (razor_package_iterator_next(pi, &package,
  27.403 -					   &name, &version, &arch)) {
  27.404 -		if (pattern && fnmatch(pattern, name, 0) == 0) {
  27.405 -			razor_transaction_remove_package(trans, package);
  27.406 -			matches++;
  27.407 -		}
  27.408 -	}
  27.409 -	razor_package_iterator_destroy(pi);
  27.410 -
  27.411 -	return matches;
  27.412 -}
  27.413 -
  27.414 -static int
  27.415 -command_update(int argc, const char *argv[])
  27.416 -{
  27.417 -	struct razor_set *set, *upstream;
  27.418 -	struct razor_transaction *trans;
  27.419 -	int i, errors;
  27.420 -
  27.421 -	set = razor_set_open(repo_filename);
  27.422 -	upstream = razor_set_open(rawhide_repo_filename);
  27.423 -	if (set == NULL || upstream == NULL)
  27.424 -		return 1;
  27.425 -
  27.426 -	trans = razor_transaction_create(set, upstream);
  27.427 -	if (argc == 0)
  27.428 -		razor_transaction_update_all(trans);
  27.429 -	for (i = 0; i < argc; i++) {
  27.430 -		if (mark_packages_for_update(trans, set, argv[i]) == 0) {
  27.431 -			fprintf(stderr, "no match for %s\n", argv[i]);
  27.432 -			return 1;
  27.433 -		}
  27.434 -	}
  27.435 -		
  27.436 -	errors = razor_transaction_resolve(trans);
  27.437 -	if (errors)
  27.438 -		return 1;
  27.439 -
  27.440 -	set = razor_transaction_finish(trans);
  27.441 -	razor_set_write(set, updated_repo_filename);
  27.442 -	razor_set_destroy(set);
  27.443 -	razor_set_destroy(upstream);
  27.444 -	printf("wrote system-updated.repo\n");
  27.445 -
  27.446 -	return 0;
  27.447 -}
  27.448 -
  27.449 -static int
  27.450 -command_remove(int argc, const char *argv[])
  27.451 -{
  27.452 -	struct razor_set *set, *upstream;
  27.453 -	struct razor_transaction *trans;
  27.454 -	int i, errors;
  27.455 -
  27.456 -	set = razor_set_open(repo_filename);
  27.457 -	if (set == NULL)
  27.458 -		return 1;
  27.459 -
  27.460 -	upstream = razor_set_create();
  27.461 -	trans = razor_transaction_create(set, upstream);
  27.462 -	for (i = 0; i < argc; i++) {
  27.463 -		if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
  27.464 -			fprintf(stderr, "no match for %s\n", argv[i]);
  27.465 -			return 1;
  27.466 -		}
  27.467 -	}
  27.468 -
  27.469 -	errors = razor_transaction_resolve(trans);
  27.470 -	if (errors)
  27.471 -		return 1;
  27.472 -
  27.473 -	set = razor_transaction_finish(trans);
  27.474 -	razor_set_write(set, updated_repo_filename);
  27.475 -	razor_set_destroy(set);
  27.476 -	razor_set_destroy(upstream);
  27.477 -	printf("wrote system-updated.repo\n");
  27.478 -
  27.479 -	return 0;
  27.480 -}
  27.481 -
  27.482 -static void
  27.483 -print_diff(const char *name,
  27.484 -	   const char *old_version, const char *new_version, const char *arch,
  27.485 -	   void *data)
  27.486 -{
  27.487 -	if (old_version)
  27.488 -		printf("removing %s %s\n", name, old_version);
  27.489 -	else
  27.490 -		printf("install %s %s\n", name, new_version);
  27.491 -}
  27.492 -
  27.493 -static int
  27.494 -command_diff(int argc, const char *argv[])
  27.495 -{
  27.496 -	struct razor_set *set, *updated;
  27.497 -
  27.498 -	set = razor_set_open(repo_filename);
  27.499 -	updated = razor_set_open(updated_repo_filename);
  27.500 -	if (set == NULL || updated == NULL)
  27.501 -		return 1;
  27.502 -
  27.503 -	razor_set_diff(set, updated, print_diff, NULL);	
  27.504 -
  27.505 -	razor_set_destroy(set);
  27.506 -	razor_set_destroy(updated);
  27.507 -
  27.508 -	return 0;
  27.509 -}
  27.510 -
  27.511 -static int
  27.512 -command_import_rpms(int argc, const char *argv[])
  27.513 -{
  27.514 -	DIR *dir;
  27.515 -	struct dirent *de;
  27.516 -	struct razor_importer *importer;
  27.517 -	struct razor_set *set;
  27.518 -	struct razor_rpm *rpm;
  27.519 -	int len;
  27.520 -	char filename[256];
  27.521 -	const char *dirname = argv[0];
  27.522 -
  27.523 -	if (dirname == NULL) {
  27.524 -		fprintf(stderr, "usage: razor import-rpms DIR\n");
  27.525 -		return -1;
  27.526 -	}
  27.527 -
  27.528 -	dir = opendir(dirname);
  27.529 -	if (dir == NULL) {
  27.530 -		fprintf(stderr, "couldn't read dir %s\n", dirname);
  27.531 -		return -1;
  27.532 -	}
  27.533 -
  27.534 -	importer = razor_importer_new();
  27.535 -
  27.536 -	while (de = readdir(dir), de != NULL) {
  27.537 -		len = strlen(de->d_name);
  27.538 -		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
  27.539 -		    continue;
  27.540 -		snprintf(filename, sizeof filename,
  27.541 -			 "%s/%s", dirname, de->d_name);
  27.542 -		rpm = razor_rpm_open(filename);
  27.543 -		if (rpm == NULL) {
  27.544 -			fprintf(stderr,
  27.545 -				"failed to open rpm \"%s\"\n", filename);
  27.546 -			continue;
  27.547 -		}
  27.548 -		if (razor_importer_add_rpm(importer, rpm)) {
  27.549 -			fprintf(stderr, "couldn't import %s\n", filename);
  27.550 -			break;
  27.551 -		}
  27.552 -		razor_rpm_close(rpm);
  27.553 -	}
  27.554 -
  27.555 -	if (de != NULL) {
  27.556 -		razor_importer_destroy(importer);
  27.557 -		return -1;
  27.558 -	}
  27.559 -
  27.560 -	set = razor_importer_finish(importer);
  27.561 -
  27.562 -	razor_set_write(set, repo_filename);
  27.563 -	razor_set_destroy(set);
  27.564 -	printf("wrote %s\n", repo_filename);
  27.565 -
  27.566 -	return 0;
  27.567 -}
  27.568 -
  27.569 -static void
  27.570 -download_package(const char *name,
  27.571 -		 const char *old_version,
  27.572 -		 const char *new_version,
  27.573 -		 const char *arch,
  27.574 -		 void *data)
  27.575 -{
  27.576 -	char file[PATH_MAX], url[256];
  27.577 -	const char *v;
  27.578 -	int *errors = data;
  27.579 -
  27.580 -	if (old_version)
  27.581 -		return;
  27.582 -
  27.583 -	/* Skip epoch */
  27.584 -	v = strchr(new_version, ':');
  27.585 -	if (v != NULL)
  27.586 -		v = v + 1;
  27.587 -	else
  27.588 -		v = new_version;
  27.589 -
  27.590 -	snprintf(url, sizeof url,
  27.591 -		 "%s/Packages/%s-%s.%s.rpm", yum_url, name, v, arch);
  27.592 -	snprintf(file, sizeof file,
  27.593 -		 "rpms/%s-%s.%s.rpm", name, v, arch);
  27.594 -	if (download_if_missing(url, file) < 0)
  27.595 -		(*errors)++;
  27.596 -}
  27.597 -
  27.598 -static void
  27.599 -install_package(const char *name,
  27.600 -		const char *old_version,
  27.601 -		const char *new_version,
  27.602 -		const char *arch,
  27.603 -		void *data)
  27.604 -{
  27.605 -	const char *v, *root = data;
  27.606 -	char file[PATH_MAX];
  27.607 -	struct razor_rpm *rpm;
  27.608 -
  27.609 -	if (old_version) {
  27.610 -		printf("removing %s %s not handled\n", name, old_version);
  27.611 -		return;
  27.612 -	}
  27.613 -
  27.614 -	/* Skip epoch */
  27.615 -	v = strchr(new_version, ':');
  27.616 -	if (v != NULL)
  27.617 -		v = v + 1;
  27.618 -	else
  27.619 -		v = new_version;
  27.620 -
  27.621 -	printf("install %s %s\n", name, v);
  27.622 -	snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
  27.623 -
  27.624 - 	rpm = razor_rpm_open(file);
  27.625 -	if (rpm == NULL) {
  27.626 -		fprintf(stderr, "failed to open rpm %s\n", file);
  27.627 -		return;
  27.628 -	}
  27.629 -	if (razor_rpm_install(rpm, root) < 0) {
  27.630 -		fprintf(stderr,
  27.631 -			"failed to install rpm %s\n", file);
  27.632 -		return;
  27.633 -	}
  27.634 -	razor_rpm_close(rpm);
  27.635 -}
  27.636 -
  27.637 -static int
  27.638 -command_install(int argc, const char *argv[])
  27.639 -{
  27.640 -	struct razor_root *root;
  27.641 -	struct razor_set *upstream, *next;
  27.642 -	struct razor_transaction *trans;
  27.643 -	int i = 0, errors, dependencies = 1;
  27.644 -
  27.645 -	if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
  27.646 -		dependencies = 0;
  27.647 -		i++;
  27.648 -	}
  27.649 -
  27.650 -	root = razor_root_open(install_root, RAZOR_ROOT_OPEN_WRITE);
  27.651 -	upstream = razor_set_open(rawhide_repo_filename);
  27.652 -	trans = razor_root_create_transaction(root, upstream);
  27.653 -
  27.654 -	for (; i < argc; i++) {
  27.655 -		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
  27.656 -			fprintf(stderr, "no package matched %s\n", argv[i]);
  27.657 -			razor_root_close(root);
  27.658 -			return 1;
  27.659 -		}
  27.660 -	}
  27.661 -
  27.662 -	if (dependencies) {
  27.663 -		errors = razor_transaction_resolve(trans);
  27.664 -		if (errors) {
  27.665 -			razor_root_close(root);
  27.666 -			return 1;
  27.667 -		}
  27.668 -	}
  27.669 -
  27.670 -	next = razor_transaction_finish(trans);
  27.671 -
  27.672 -	razor_root_update(root, next);
  27.673 -
  27.674 -	if (mkdir("rpms", 0777) && errno != EEXIST) {
  27.675 -		fprintf(stderr, "failed to create rpms directory.\n");
  27.676 -		razor_root_close(root);
  27.677 -		return 1;
  27.678 -	}
  27.679 -
  27.680 -	razor_root_diff(root, download_package, &errors);
  27.681 -	if (errors > 0) {
  27.682 -		fprintf(stderr, "failed to download %d packages\n", errors);
  27.683 -		razor_root_close(root);
  27.684 -                return 1;
  27.685 -        }
  27.686 -
  27.687 -	/* FIXME: We need to figure out the right install order here,
  27.688 -	 * so the post and pre scripts can run. */
  27.689 -	razor_root_diff(root, install_package, (void *) root);
  27.690 -
  27.691 -	razor_set_destroy(next);
  27.692 -	razor_set_destroy(upstream);
  27.693 -
  27.694 -	return razor_root_commit(root);
  27.695 -}
  27.696 -
  27.697 -static int
  27.698 -command_init(int argc, const char *argv[])
  27.699 -{
  27.700 -	return razor_root_create(install_root);
  27.701 -}
  27.702 -
  27.703 -static int
  27.704 -command_download(int argc, const char *argv[])
  27.705 -{
  27.706 -	struct razor_set *set;
  27.707 -	struct razor_package_iterator *pi;
  27.708 -	struct razor_package *package;
  27.709 -	const char *pattern = argv[0], *name, *version, *arch;
  27.710 -	char url[256], file[256];
  27.711 -	int matches = 0;
  27.712 -
  27.713 -	if (mkdir("rpms", 0777) && errno != EEXIST) {
  27.714 -		fprintf(stderr, "failed to create rpms directory.\n");
  27.715 -		return 1;
  27.716 -	}
  27.717 -
  27.718 -	set = razor_set_open(rawhide_repo_filename);
  27.719 -	pi = razor_package_iterator_create(set);
  27.720 -	while (razor_package_iterator_next(pi, &package,
  27.721 -					   &name, &version, &arch)) {
  27.722 -		if (pattern && fnmatch(pattern, name, 0) != 0)
  27.723 -			continue;
  27.724 -
  27.725 -		matches++;
  27.726 -		snprintf(url, sizeof url,
  27.727 -			 "%s/Packages/%s-%s.%s.rpm",
  27.728 -			 yum_url, name, version, arch);
  27.729 -		snprintf(file, sizeof file,
  27.730 -			 "rpms/%s-%s.%s.rpm", name, version, arch);
  27.731 -		download_if_missing(url, file);
  27.732 -	}
  27.733 -	razor_package_iterator_destroy(pi);
  27.734 -	razor_set_destroy(set);
  27.735 -
  27.736 -	if (matches == 0)
  27.737 -		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
  27.738 -	else if (matches == 1)
  27.739 -		fprintf(stderr, "downloaded 1 package\n");
  27.740 -	else
  27.741 -		fprintf(stderr, "downloaded %d packages\n", matches);
  27.742 -
  27.743 -	return 0;
  27.744 -}
  27.745 -
  27.746 -static struct {
  27.747 -	const char *name;
  27.748 -	const char *description;
  27.749 -	int (*func)(int argc, const char *argv[]);
  27.750 -} razor_commands[] = {
  27.751 -	{ "list", "list all packages", command_list },
  27.752 -	{ "list-requires", "list all requires for the given package", command_list_requires },
  27.753 -	{ "list-provides", "list all provides for the given package", command_list_provides },
  27.754 -	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
  27.755 -	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
  27.756 -	{ "list-files", "list files for package set", command_list_files },
  27.757 -	{ "list-file-packages", "list packages owning file", command_list_file_packages },
  27.758 -	{ "list-package-files", "list files in package", command_list_package_files },
  27.759 -	{ "what-requires", "list the packages that have the given requires", command_what_requires },
  27.760 -	{ "what-provides", "list the packages that have the given provides", command_what_provides },
  27.761 -	{ "import-yum", "import yum metadata files", command_import_yum },
  27.762 -	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
  27.763 -	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
  27.764 -	{ "update", "update all or specified packages", command_update },
  27.765 -	{ "remove", "remove specified packages", command_remove },
  27.766 -	{ "diff", "show diff between two package sets", command_diff },
  27.767 -	{ "install", "install rpm", command_install },
  27.768 -	{ "init", "init razor root", command_init },
  27.769 -	{ "download", "download packages", command_download }
  27.770 -};
  27.771 -
  27.772 -static int
  27.773 -usage(void)
  27.774 -{
  27.775 -	int i;
  27.776 -
  27.777 -	printf("usage:\n");
  27.778 -	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  27.779 -		printf("  %-20s%s\n",
  27.780 -		       razor_commands[i].name, razor_commands[i].description);
  27.781 -
  27.782 -	return 1;
  27.783 -}
  27.784 -
  27.785 -int
  27.786 -main(int argc, const char *argv[])
  27.787 -{
  27.788 -	char *repo;
  27.789 -	int i;
  27.790 -
  27.791 -	repo = getenv("RAZOR_REPO");
  27.792 -	if (repo != NULL)
  27.793 -		repo_filename = repo;
  27.794 -
  27.795 -	yum_url = getenv("YUM_URL");
  27.796 -	if (yum_url == NULL)
  27.797 -		yum_url = YUM_URL;
  27.798 -
  27.799 -	if (argc < 2)
  27.800 -		return usage();
  27.801 -
  27.802 -	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  27.803 -		if (strcmp(razor_commands[i].name, argv[1]) == 0)
  27.804 -			return razor_commands[i].func(argc - 2, argv + 2);
  27.805 -
  27.806 -	return usage();
  27.807 -}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/po/.gitignore	Mon Jun 16 15:40:30 2008 -0400
    28.3 @@ -0,0 +1,4 @@
    28.4 +POTFILES
    28.5 +Makefile.in.in
    28.6 +stamp-it
    28.7 +
    29.1 --- a/razor-internal.h	Sun Jun 15 23:15:59 2008 -0400
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,19 +0,0 @@
    29.4 -#ifndef _RAZOR_INTERNAL_H_
    29.5 -#define _RAZOR_INTERNAL_H_
    29.6 -
    29.7 -#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
    29.8 -
    29.9 -/* Utility functions */
   29.10 -
   29.11 -int razor_create_dir(const char *root, const char *path);
   29.12 -int razor_write(int fd, const void *data, size_t size);
   29.13 -
   29.14 -
   29.15 -typedef int (*razor_compare_with_data_func_t)(const void *p1,
   29.16 -					      const void *p,
   29.17 -					      void *data);
   29.18 -uint32_t *
   29.19 -razor_qsort_with_data(void *base, size_t nelem, size_t size,
   29.20 -		      razor_compare_with_data_func_t compare, void *data);
   29.21 -
   29.22 -#endif /* _RAZOR_INTERNAL_H_ */
    30.1 --- a/razor-root.c	Sun Jun 15 23:15:59 2008 -0400
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,168 +0,0 @@
    30.4 -#include <stdlib.h>
    30.5 -#include <stdint.h>
    30.6 -#include <stdio.h>
    30.7 -#include <sys/stat.h>
    30.8 -#include <dirent.h>
    30.9 -#include <unistd.h>
   30.10 -#include <fcntl.h>
   30.11 -#include "razor.h"
   30.12 -#include "razor-internal.h"
   30.13 -
   30.14 -static const char system_repo_filename[] = "system.repo";
   30.15 -static const char next_repo_filename[] = "system-next.repo";
   30.16 -static const char razor_root_path[] = "/var/lib/razor";
   30.17 -
   30.18 -struct razor_root {
   30.19 -	struct razor_set *system;
   30.20 -	struct razor_set *next;
   30.21 -	int fd;
   30.22 -	char path[PATH_MAX];
   30.23 -	char new_path[PATH_MAX];
   30.24 -};
   30.25 -
   30.26 -int
   30.27 -razor_root_create(const char *root)
   30.28 -{	
   30.29 -	struct stat buf;
   30.30 -	struct razor_set *set;
   30.31 -	char path[PATH_MAX];
   30.32 -
   30.33 -	if (stat(root, &buf) < 0) {
   30.34 -		if (mkdir(root, 0777) < 0) {
   30.35 -			fprintf(stderr,
   30.36 -				"could not create install root \"%s\"\n",
   30.37 -				root);
   30.38 -			return -1;
   30.39 -		}
   30.40 -		fprintf(stderr, "created install root \"%s\"\n", root);
   30.41 -	} else if (!S_ISDIR(buf.st_mode)) {
   30.42 -		fprintf(stderr,
   30.43 -			"install root \"%s\" exists, but is not a directory\n",
   30.44 -			root);
   30.45 -		return -1;
   30.46 -	}
   30.47 -
   30.48 -	snprintf(path, sizeof path, "%s/%s",
   30.49 -		 razor_root_path, system_repo_filename);
   30.50 -	if (razor_create_dir(root, path) < 0) {
   30.51 -		fprintf(stderr, "could not create %s%s\n",
   30.52 -			root, razor_root_path);
   30.53 -		return -1;
   30.54 -	}
   30.55 -
   30.56 -	set = razor_set_create();
   30.57 -	snprintf(path, sizeof path, "%s%s/%s",
   30.58 -		 root, razor_root_path, system_repo_filename);
   30.59 -	if (stat(path, &buf) == 0) {
   30.60 -		fprintf(stderr,
   30.61 -			"a razor install root is already initialized\n");
   30.62 -		return -1;
   30.63 -	}
   30.64 -	if (razor_set_write(set, path) < 0) {
   30.65 -		fprintf(stderr, "could not write initial package set\n");
   30.66 -		return -1;
   30.67 -	}
   30.68 -	razor_set_destroy(set);
   30.69 -
   30.70 -	return 0;
   30.71 -}
   30.72 -
   30.73 -struct razor_root *
   30.74 -razor_root_open(const char *root, int flags)
   30.75 -{
   30.76 -	struct razor_root *image;
   30.77 -
   30.78 -	image = malloc(sizeof *image);
   30.79 -	if (image == NULL)
   30.80 -		return NULL;
   30.81 -
   30.82 -	/* Create the new next repo file up front to ensure exclusive
   30.83 -	 * access. */
   30.84 -	snprintf(image->new_path, sizeof image->new_path,
   30.85 -		 "%s%s/%s", root, root, next_repo_filename);
   30.86 -	image->fd = open(image->new_path,
   30.87 -			 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
   30.88 -	if (image->fd < 0) {
   30.89 -		fprintf(stderr, "failed to get lock file, "
   30.90 -			"maybe previous operation crashed?\n");
   30.91 -
   30.92 -		/* FIXME: Use fcntl advisory locking on the system
   30.93 -		 * package set file to figure out whether previous
   30.94 -		 * operation crashed or is still in progress. */
   30.95 -
   30.96 -		free(image);
   30.97 -		return NULL;
   30.98 -	}
   30.99 -
  30.100 -	snprintf(image->path, sizeof image->path,
  30.101 -		 "%s%s/%s", root, razor_root_path, system_repo_filename);
  30.102 -	image->system = razor_set_open(image->path);
  30.103 -	if (image->system == NULL) {
  30.104 -		unlink(image->new_path);
  30.105 -		close(image->fd);
  30.106 -		free(image);
  30.107 -		return NULL;
  30.108 -	}
  30.109 -
  30.110 -	return image;
  30.111 -}
  30.112 -
  30.113 -struct razor_set *
  30.114 -razor_root_open_read_only(const char *root)
  30.115 -{
  30.116 -	char path[PATH_MAX];
  30.117 -
  30.118 -	snprintf(path, sizeof path, "%s%s/%s",
  30.119 -		 root, razor_root_path, system_repo_filename);
  30.120 -
  30.121 -	return razor_set_open(path);
  30.122 -}
  30.123 -
  30.124 -struct razor_transaction *
  30.125 -razor_root_create_transaction(struct razor_root *image,
  30.126 -			      struct razor_set *upstream)
  30.127 -{
  30.128 -	/* FIXME: This should take a number of upstream repos. */
  30.129 -	return razor_transaction_create(image->system, upstream);
  30.130 -}
  30.131 -
  30.132 -int
  30.133 -razor_root_close(struct razor_root *image)
  30.134 -{
  30.135 -	unlink(image->new_path);
  30.136 -	close(image->fd);
  30.137 -	free(image);
  30.138 -
  30.139 -	return 0;
  30.140 -}
  30.141 -
  30.142 -void
  30.143 -razor_root_update(struct razor_root *root, struct razor_set *next)
  30.144 -{
  30.145 -	razor_set_write_to_fd(next, root->fd);
  30.146 -	root->next = next;
  30.147 -
  30.148 -	/* Sync the new repo file so the new package set is on disk
  30.149 -	 * before we start upgrading. */
  30.150 -	fsync(root->fd);
  30.151 -	printf("wrote %s\n", root->new_path);
  30.152 -}
  30.153 -
  30.154 -int
  30.155 -razor_root_commit(struct razor_root *image)
  30.156 -{
  30.157 -	/* Make it so. */
  30.158 -	rename(image->new_path, image->path);
  30.159 -	printf("renamed %s to %s\n", image->new_path, image->path);
  30.160 -	close(image->fd);
  30.161 -	free(image);
  30.162 -
  30.163 -	return 0;
  30.164 -}
  30.165 -
  30.166 -void
  30.167 -razor_root_diff(struct razor_root *root,
  30.168 -		razor_package_callback_t callback, void *data)
  30.169 -{
  30.170 -	return razor_set_diff(root->system, root->next, callback, data);
  30.171 -}
    31.1 --- a/razor.c	Sun Jun 15 23:15:59 2008 -0400
    31.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.3 @@ -1,2611 +0,0 @@
    31.4 -/*
    31.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    31.6 - * Copyright (C) 2008  Red Hat, Inc
    31.7 - *
    31.8 - * This program is free software; you can redistribute it and/or modify
    31.9 - * it under the terms of the GNU General Public License as published by
   31.10 - * the Free Software Foundation; either version 2 of the License, or
   31.11 - * (at your option) any later version.
   31.12 - *
   31.13 - * This program is distributed in the hope that it will be useful,
   31.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   31.16 - * GNU General Public License for more details.
   31.17 - *
   31.18 - * You should have received a copy of the GNU General Public License along
   31.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   31.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   31.21 - */
   31.22 -
   31.23 -#define _GNU_SOURCE
   31.24 -
   31.25 -#include <stdlib.h>
   31.26 -#include <stddef.h>
   31.27 -#include <stdint.h>
   31.28 -#include <stdio.h>
   31.29 -#include <string.h>
   31.30 -#include <sys/types.h>
   31.31 -#include <sys/stat.h>
   31.32 -#include <sys/mman.h>
   31.33 -#include <unistd.h>
   31.34 -#include <fcntl.h>
   31.35 -#include <errno.h>
   31.36 -#include <ctype.h>
   31.37 -#include <fnmatch.h>
   31.38 -
   31.39 -#include "razor.h"
   31.40 -#include "razor-internal.h"
   31.41 -#include "types.h"
   31.42 -
   31.43 -struct razor_set_section {
   31.44 -	uint32_t type;
   31.45 -	uint32_t offset;
   31.46 -	uint32_t size;
   31.47 -};
   31.48 -
   31.49 -struct razor_set_header {
   31.50 -	uint32_t magic;
   31.51 -	uint32_t version;
   31.52 -	struct razor_set_section sections[0];
   31.53 -};
   31.54 -
   31.55 -#define RAZOR_MAGIC 0x7a7a7a7a
   31.56 -#define RAZOR_VERSION 1
   31.57 -
   31.58 -#define RAZOR_STRING_POOL	0
   31.59 -#define RAZOR_PACKAGES		1
   31.60 -#define RAZOR_PROPERTIES	2
   31.61 -#define RAZOR_FILES		3
   31.62 -#define RAZOR_PACKAGE_POOL	4
   31.63 -#define RAZOR_PROPERTY_POOL	5
   31.64 -#define RAZOR_FILE_POOL		6
   31.65 -
   31.66 -struct razor_package {
   31.67 -	uint name  : 24;
   31.68 -	uint flags : 8;
   31.69 -	uint32_t version;
   31.70 -	uint32_t arch;
   31.71 -	struct list_head properties;
   31.72 -	struct list_head files;
   31.73 -};
   31.74 -
   31.75 -struct razor_property {
   31.76 -	uint name  : 24;
   31.77 -	uint flags : 6;
   31.78 -	enum razor_property_type type : 2;
   31.79 -	enum razor_version_relation relation : 32;
   31.80 -	uint32_t version;
   31.81 -	struct list_head packages;
   31.82 -};
   31.83 -
   31.84 -struct razor_entry {
   31.85 -	uint name  : 24;
   31.86 -	uint flags : 8;
   31.87 -	uint32_t start;
   31.88 -	struct list_head packages;
   31.89 -};
   31.90 -
   31.91 -#define RAZOR_ENTRY_LAST	0x80
   31.92 -
   31.93 -struct razor_set {
   31.94 -	struct array string_pool;
   31.95 - 	struct array packages;
   31.96 - 	struct array properties;
   31.97 - 	struct array files;
   31.98 -	struct array package_pool;
   31.99 - 	struct array property_pool;
  31.100 - 	struct array file_pool;
  31.101 -	struct razor_set_header *header;
  31.102 -};
  31.103 -
  31.104 -struct import_entry {
  31.105 -	uint32_t package;
  31.106 -	char *name;
  31.107 -};
  31.108 -
  31.109 -struct import_directory {
  31.110 -	uint32_t name, count;
  31.111 -	struct array files;
  31.112 -	struct array packages;
  31.113 -	struct import_directory *last;
  31.114 -};
  31.115 -
  31.116 -struct razor_importer {
  31.117 -	struct razor_set *set;
  31.118 -	struct hashtable table;
  31.119 -	struct razor_package *package;
  31.120 -	struct array properties;
  31.121 -	struct array files;
  31.122 -	struct array file_requires;
  31.123 -};
  31.124 -
  31.125 -static void *
  31.126 -zalloc(size_t size)
  31.127 -{
  31.128 -	void *p;
  31.129 -
  31.130 -	p = malloc(size);
  31.131 -	memset(p, 0, size);
  31.132 -
  31.133 -	return p;
  31.134 -}
  31.135 -
  31.136 -struct razor_set_section razor_sections[] = {
  31.137 -	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
  31.138 -	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
  31.139 -	{ RAZOR_PROPERTIES,	offsetof(struct razor_set, properties) },
  31.140 -	{ RAZOR_FILES,		offsetof(struct razor_set, files) },
  31.141 -	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
  31.142 -	{ RAZOR_PROPERTY_POOL,	offsetof(struct razor_set, property_pool) },
  31.143 -	{ RAZOR_FILE_POOL,	offsetof(struct razor_set, file_pool) },
  31.144 -};
  31.145 -
  31.146 -struct razor_set *
  31.147 -razor_set_create(void)
  31.148 -{
  31.149 -	struct razor_set *set;
  31.150 -	struct razor_entry *e;
  31.151 -	char *empty;
  31.152 -
  31.153 -	set = zalloc(sizeof *set);
  31.154 -
  31.155 -	e = array_add(&set->files, sizeof *e);
  31.156 -	empty = array_add(&set->string_pool, 1);
  31.157 -	*empty = '\0';
  31.158 -	e->name = 0;
  31.159 -	e->flags = RAZOR_ENTRY_LAST;
  31.160 -	e->start = 0;
  31.161 -	list_set_empty(&e->packages);
  31.162 -
  31.163 -	return set;
  31.164 -}
  31.165 -
  31.166 -struct razor_set *
  31.167 -razor_set_open(const char *filename)
  31.168 -{
  31.169 -	struct razor_set *set;
  31.170 -	struct razor_set_section *s;
  31.171 -	struct stat stat;
  31.172 -	struct array *array;
  31.173 -	int fd;
  31.174 -
  31.175 -	set = zalloc(sizeof *set);
  31.176 -	fd = open(filename, O_RDONLY);
  31.177 -	if (fstat(fd, &stat) < 0)
  31.178 -		return NULL;
  31.179 -	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  31.180 -	if (set->header == MAP_FAILED) {
  31.181 -		free(set);
  31.182 -		return NULL;
  31.183 -	}
  31.184 -
  31.185 -	for (s = set->header->sections; ~s->type; s++) {
  31.186 -		if (s->type >= ARRAY_SIZE(razor_sections))
  31.187 -			continue;
  31.188 -		if (s->type != razor_sections[s->type].type)
  31.189 -			continue;
  31.190 -		array = (void *) set + razor_sections[s->type].offset;
  31.191 -		array->data = (void *) set->header + s->offset;
  31.192 -		array->size = s->size;
  31.193 -		array->alloc = s->size;
  31.194 -	}
  31.195 -	close(fd);
  31.196 -
  31.197 -	return set;
  31.198 -}
  31.199 -
  31.200 -void
  31.201 -razor_set_destroy(struct razor_set *set)
  31.202 -{
  31.203 -	unsigned int size;
  31.204 -	struct array *a;
  31.205 -	int i;
  31.206 -
  31.207 -	if (set->header) {
  31.208 -		for (i = 0; set->header->sections[i].type; i++)
  31.209 -			;
  31.210 -		size = set->header->sections[i].type;
  31.211 -		munmap(set->header, size);
  31.212 -	} else {
  31.213 -		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  31.214 -			a = (void *) set + razor_sections[i].offset;
  31.215 -			free(a->data);
  31.216 -		}
  31.217 -	}
  31.218 -
  31.219 -	free(set);
  31.220 -}
  31.221 -
  31.222 -int
  31.223 -razor_set_write_to_fd(struct razor_set *set, int fd)
  31.224 -{
  31.225 -	char data[4096];
  31.226 -	struct razor_set_header *header = (struct razor_set_header *) data;
  31.227 -	struct array *a;
  31.228 -	uint32_t offset;
  31.229 -	int i;
  31.230 -
  31.231 -	memset(data, 0, sizeof data);
  31.232 -	header->magic = RAZOR_MAGIC;
  31.233 -	header->version = RAZOR_VERSION;
  31.234 -	offset = sizeof data;
  31.235 -
  31.236 -	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  31.237 -		if (razor_sections[i].type != i)
  31.238 -			continue;
  31.239 -		a = (void *) set + razor_sections[i].offset;
  31.240 -		header->sections[i].type = i;
  31.241 -		header->sections[i].offset = offset;
  31.242 -		header->sections[i].size = a->size;
  31.243 -		offset += ALIGN(a->size, 4096);
  31.244 -	}
  31.245 -
  31.246 -	header->sections[i].type = ~0;
  31.247 -	header->sections[i].offset = 0;
  31.248 -	header->sections[i].size = 0;
  31.249 -
  31.250 -	razor_write(fd, data, sizeof data);
  31.251 -	memset(data, 0, sizeof data);
  31.252 -	for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  31.253 -		if (razor_sections[i].type != i)
  31.254 -			continue;
  31.255 -		a = (void *) set + razor_sections[i].offset;
  31.256 -		razor_write(fd, a->data, a->size);
  31.257 -		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
  31.258 -	}
  31.259 -
  31.260 -	return 0;
  31.261 -}
  31.262 -
  31.263 -int
  31.264 -razor_set_write(struct razor_set *set, const char *filename)
  31.265 -{
  31.266 -	int fd, status;
  31.267 -
  31.268 -	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
  31.269 -	if (fd < 0)
  31.270 -		return -1;
  31.271 -
  31.272 -	status = razor_set_write_to_fd(set, fd);
  31.273 -	if (status) {
  31.274 -	    close(fd);
  31.275 -	    return status;
  31.276 -	}
  31.277 -
  31.278 -	return close(fd);
  31.279 -}
  31.280 -
  31.281 -void
  31.282 -razor_build_evr(char *evr_buf, int size, const char *epoch,
  31.283 -		const char *version, const char *release)
  31.284 -{
  31.285 -	int len;
  31.286 -
  31.287 -	if (!version || !*version) {
  31.288 -		*evr_buf = '\0';
  31.289 -		return;
  31.290 -	}
  31.291 -
  31.292 -	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
  31.293 -		len = snprintf(evr_buf, size, "%s:", epoch);
  31.294 -		evr_buf += len;
  31.295 -		size -= len;
  31.296 -	}
  31.297 -	len = snprintf(evr_buf, size, "%s", version);
  31.298 -	evr_buf += len;
  31.299 -	size -= len;
  31.300 -	if (release && *release)
  31.301 -		snprintf(evr_buf, size, "-%s", release);
  31.302 -}
  31.303 -
  31.304 -void
  31.305 -razor_importer_begin_package(struct razor_importer *importer,
  31.306 -			     const char *name,
  31.307 -			     const char *version,
  31.308 -			     const char *arch)
  31.309 -{
  31.310 -	struct razor_package *p;
  31.311 -
  31.312 -	p = array_add(&importer->set->packages, sizeof *p);
  31.313 -	p->name = hashtable_tokenize(&importer->table, name);
  31.314 -	p->flags = 0;
  31.315 -	p->version = hashtable_tokenize(&importer->table, version);
  31.316 -	p->arch = hashtable_tokenize(&importer->table, arch);
  31.317 -
  31.318 -	importer->package = p;
  31.319 -	array_init(&importer->properties);
  31.320 -}
  31.321 -
  31.322 -void
  31.323 -razor_importer_finish_package(struct razor_importer *importer)
  31.324 -{
  31.325 -	list_set_array(&importer->package->properties,
  31.326 -		       &importer->set->property_pool,
  31.327 -		       &importer->properties,
  31.328 -		       1);
  31.329 -
  31.330 -	array_release(&importer->properties);
  31.331 -}
  31.332 -
  31.333 -void
  31.334 -razor_importer_add_property(struct razor_importer *importer,
  31.335 -			    const char *name,
  31.336 -			    enum razor_version_relation relation,
  31.337 -			    const char *version,
  31.338 -			    enum razor_property_type type)
  31.339 -{
  31.340 -	struct razor_property *p;
  31.341 -	uint32_t *r;
  31.342 -
  31.343 -	p = array_add(&importer->set->properties, sizeof *p);
  31.344 -	p->name = hashtable_tokenize(&importer->table, name);
  31.345 -	p->flags = 0;
  31.346 -	p->type = type;
  31.347 -	p->relation = relation;
  31.348 -	p->version = hashtable_tokenize(&importer->table, version);
  31.349 -	list_set_ptr(&p->packages, importer->package -
  31.350 -		     (struct razor_package *) importer->set->packages.data);
  31.351 -
  31.352 -	r = array_add(&importer->properties, sizeof *r);
  31.353 -	*r = p - (struct razor_property *) importer->set->properties.data;
  31.354 -
  31.355 -	if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
  31.356 -		r = array_add(&importer->file_requires, sizeof *r);
  31.357 -		*r = p->name;
  31.358 -	}
  31.359 -}
  31.360 -
  31.361 -void
  31.362 -razor_importer_add_file(struct razor_importer *importer, const char *name)
  31.363 -{
  31.364 -	struct import_entry *e;
  31.365 -
  31.366 -	e = array_add(&importer->files, sizeof *e);
  31.367 -
  31.368 -	e->package = importer->package -
  31.369 -		(struct razor_package *) importer->set->packages.data;
  31.370 -	e->name = strdup(name);
  31.371 -}
  31.372 -
  31.373 -struct razor_importer *
  31.374 -razor_importer_new(void)
  31.375 -{
  31.376 -	struct razor_importer *importer;
  31.377 -
  31.378 -	importer = zalloc(sizeof *importer);
  31.379 -	importer->set = razor_set_create();
  31.380 -	hashtable_init(&importer->table, &importer->set->string_pool);
  31.381 -
  31.382 -	return importer;
  31.383 -}
  31.384 -
  31.385 -/* Destroy an importer without creating the set. */
  31.386 -void
  31.387 -razor_importer_destroy(struct razor_importer *importer)
  31.388 -{
  31.389 -	/* FIXME: write this */
  31.390 -}
  31.391 -
  31.392 -static int
  31.393 -versioncmp(const char *s1, const char *s2)
  31.394 -{
  31.395 -	const char *p1, *p2;
  31.396 -	long n1, n2;
  31.397 -	int res;
  31.398 -
  31.399 -	n1 = strtol(s1, (char **) &p1, 10);
  31.400 -	n2 = strtol(s2, (char **) &p2, 10);
  31.401 -
  31.402 -	/* Epoch; if one but not the other has an epoch set, default
  31.403 -	 * the epoch-less version to 0. */
  31.404 -	res = (*p1 == ':') - (*p2 == ':');
  31.405 -	if (res < 0) {
  31.406 -		n1 = 0;
  31.407 -		p1 = s1;
  31.408 -		p2++;
  31.409 -	} else if (res > 0) {
  31.410 -		p1++;
  31.411 -		n2 = 0;
  31.412 -		p2 = s2;
  31.413 -	}
  31.414 -
  31.415 -	if (n1 != n2)
  31.416 -		return n1 - n2;
  31.417 -	while (*p1 && *p2) {
  31.418 -		if (*p1 != *p2)
  31.419 -			return *p1 - *p2;
  31.420 -		p1++;
  31.421 -		p2++;
  31.422 -		if (isdigit(*p1) && isdigit(*p2))
  31.423 -			return versioncmp(p1, p2);
  31.424 -	}
  31.425 -
  31.426 -	return *p1 - *p2;
  31.427 -}
  31.428 -
  31.429 -static int
  31.430 -compare_packages(const void *p1, const void *p2, void *data)
  31.431 -{
  31.432 -	const struct razor_package *pkg1 = p1, *pkg2 = p2;
  31.433 -	struct razor_set *set = data;
  31.434 -	char *pool = set->string_pool.data;
  31.435 -
  31.436 -	/* FIXME: what if the flags are different? */
  31.437 -	if (pkg1->name == pkg2->name)
  31.438 -		return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
  31.439 -	else
  31.440 -		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
  31.441 -}
  31.442 -
  31.443 -static int
  31.444 -compare_properties(const void *p1, const void *p2, void *data)
  31.445 -{
  31.446 -	const struct razor_property *prop1 = p1, *prop2 = p2;
  31.447 -	struct razor_set *set = data;
  31.448 -	char *pool = set->string_pool.data;
  31.449 -
  31.450 -	if (prop1->name != prop2->name) 
  31.451 -		return strcmp(&pool[prop1->name], &pool[prop2->name]);
  31.452 -	else if (prop1->type != prop2->type)
  31.453 -		return prop1->type - prop2->type;
  31.454 -	else if (prop1->relation != prop2->relation)
  31.455 -		return prop1->relation - prop2->relation;
  31.456 -	else
  31.457 -		return versioncmp(&pool[prop1->version], &pool[prop2->version]);
  31.458 -}
  31.459 -
  31.460 -static uint32_t *
  31.461 -uniqueify_properties(struct razor_set *set)
  31.462 -{
  31.463 -	struct razor_property *rp, *up, *rp_end;
  31.464 -	struct array *pkgs, *p;
  31.465 -	struct list_head *r;
  31.466 -	uint32_t *map, *rmap;
  31.467 -	int i, count, unique;
  31.468 -
  31.469 -	count = set->properties.size / sizeof(struct razor_property);
  31.470 -	map = razor_qsort_with_data(set->properties.data,
  31.471 -				    count,
  31.472 -				    sizeof(struct razor_property),
  31.473 -				    compare_properties,
  31.474 -				    set);
  31.475 -
  31.476 -	rp_end = set->properties.data + set->properties.size;
  31.477 -	rmap = malloc(count * sizeof *map);
  31.478 -	pkgs = zalloc(count * sizeof *pkgs);
  31.479 -	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
  31.480 -		if (rp->name != up->name || rp->type != up->type ||
  31.481 -		    rp->relation != up->relation || rp->version != up->version) {
  31.482 -			up++;
  31.483 -			up->name = rp->name;
  31.484 -			up->flags = 0;
  31.485 -			up->type = rp->type;
  31.486 -			up->relation = rp->relation;
  31.487 -			up->version = rp->version;
  31.488 -		}
  31.489 -
  31.490 -		unique = up - (struct razor_property *) set->properties.data;
  31.491 -		rmap[map[i]] = unique;
  31.492 -		r = array_add(&pkgs[unique], sizeof *r);
  31.493 -		*r = rp->packages;
  31.494 -	}
  31.495 -	free(map);
  31.496 -
  31.497 -	if (up != rp)
  31.498 -		up++;
  31.499 -	set->properties.size = (void *) up - set->properties.data;
  31.500 -	rp_end = up;
  31.501 -	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
  31.502 -		list_set_array(&rp->packages, &set->package_pool, p, 0);
  31.503 -		array_release(p);
  31.504 -	}
  31.505 -
  31.506 -	free(pkgs);
  31.507 -
  31.508 -	return rmap;
  31.509 -}
  31.510 -
  31.511 -static int
  31.512 -compare_filenames(const void *p1, const void *p2, void *data)
  31.513 -{
  31.514 -	const struct import_entry *e1 = p1;
  31.515 -	const struct import_entry *e2 = p2;
  31.516 -	const char *n1 = e1->name;
  31.517 -	const char *n2 = e2->name;
  31.518 -
  31.519 -	/* Need to make sure that the contents of a directory
  31.520 -	 * are sorted immediately after it. So "foo/bar" has to
  31.521 -	 * sort before "foo.conf"
  31.522 -	 *
  31.523 -	 * FIXME: this is about 60% slower than strcmp
  31.524 -	 */
  31.525 -	while (*n1 && *n2) {
  31.526 -		if (*n1 < *n2)
  31.527 -			return *n2 == '/' ? 1 : -1;
  31.528 -		else if (*n1 > *n2)
  31.529 -			return *n1 == '/' ? -1 : 1;
  31.530 -		n1++;
  31.531 -		n2++;
  31.532 -	}
  31.533 -	if (*n1)
  31.534 -		return 1;
  31.535 -	else if (*n2)
  31.536 -		return -1;
  31.537 -	else
  31.538 -		return 0;
  31.539 -}
  31.540 -
  31.541 -static void
  31.542 -count_entries(struct import_directory *d)
  31.543 -{
  31.544 -	struct import_directory *p, *end;
  31.545 -
  31.546 -	p = d->files.data;
  31.547 -	end = d->files.data + d->files.size;
  31.548 -	d->count = 0;
  31.549 -	while (p < end) {
  31.550 -		count_entries(p);
  31.551 -		d->count += p->count + 1;
  31.552 -		p++;
  31.553 -	}		
  31.554 -}
  31.555 -
  31.556 -static void
  31.557 -serialize_files(struct razor_set *set,
  31.558 -		struct import_directory *d, struct array *array)
  31.559 -{
  31.560 -	struct import_directory *p, *end;
  31.561 -	struct razor_entry *e = NULL;
  31.562 -	uint32_t s;
  31.563 -
  31.564 -	p = d->files.data;
  31.565 -	end = d->files.data + d->files.size;
  31.566 -	s = array->size / sizeof *e + d->files.size / sizeof *p;
  31.567 -	while (p < end) {
  31.568 -		e = array_add(array, sizeof *e);
  31.569 -		e->name = p->name;
  31.570 -		e->flags = 0;
  31.571 -		e->start = p->count > 0 ? s : 0;
  31.572 -		s += p->count;
  31.573 -
  31.574 -		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
  31.575 -		array_release(&p->packages);
  31.576 -		p++;
  31.577 -	}		
  31.578 -	if (e != NULL)
  31.579 -		e->flags |= RAZOR_ENTRY_LAST;
  31.580 -
  31.581 -	p = d->files.data;
  31.582 -	end = d->files.data + d->files.size;
  31.583 -	while (p < end) {
  31.584 -		serialize_files(set, p, array);
  31.585 -		p++;
  31.586 -	}
  31.587 -}
  31.588 -
  31.589 -static void
  31.590 -remap_property_package_links(struct array *properties, uint32_t *rmap)
  31.591 -{
  31.592 -	struct razor_property *p, *end;
  31.593 -
  31.594 -	end = properties->data + properties->size;
  31.595 -	for (p = properties->data; p < end; p++)
  31.596 -		list_remap_head(&p->packages, rmap);
  31.597 -}
  31.598 -
  31.599 -static void
  31.600 -build_file_tree(struct razor_importer *importer)
  31.601 -{
  31.602 -	int count, i, length;
  31.603 -	struct import_entry *filenames;
  31.604 -	char *f, *end;
  31.605 -	uint32_t name, *r;
  31.606 -	char dirname[256];
  31.607 -	struct import_directory *d, root;
  31.608 -	struct razor_entry *e;
  31.609 -
  31.610 -	count = importer->files.size / sizeof (struct import_entry);
  31.611 -	razor_qsort_with_data(importer->files.data,
  31.612 -			      count,
  31.613 -			      sizeof (struct import_entry),
  31.614 -			      compare_filenames,
  31.615 -			      NULL);
  31.616 -
  31.617 -	root.name = hashtable_tokenize(&importer->table, "");
  31.618 -	array_init(&root.files);
  31.619 -	array_init(&root.packages);
  31.620 -	root.last = NULL;
  31.621 -
  31.622 -	filenames = importer->files.data;
  31.623 -	for (i = 0; i < count; i++) {
  31.624 -		f = filenames[i].name;
  31.625 -		if (*f != '/')
  31.626 -			continue;
  31.627 -		f++;
  31.628 -
  31.629 -		d = &root;
  31.630 -		while (*f) {
  31.631 -			end = strchr(f, '/');
  31.632 -			if (end == NULL)
  31.633 -				end = f + strlen(f);
  31.634 -			length = end - f;
  31.635 -			memcpy(dirname, f, length);
  31.636 -			dirname[length] ='\0';
  31.637 -			name = hashtable_tokenize(&importer->table, dirname);
  31.638 -			if (d->last == NULL || d->last->name != name) {
  31.639 -				d->last = array_add(&d->files, sizeof *d);
  31.640 -				d->last->name = name;
  31.641 -				d->last->last = NULL;
  31.642 -				array_init(&d->last->files);
  31.643 -				array_init(&d->last->packages);
  31.644 -			}
  31.645 -			d = d->last;				
  31.646 -			f = end + 1;
  31.647 -			if (*end == '\0')
  31.648 -				break;
  31.649 -		}
  31.650 -
  31.651 -		r = array_add(&d->packages, sizeof *r);
  31.652 -		*r = filenames[i].package;
  31.653 -		free(filenames[i].name);
  31.654 -	}
  31.655 -
  31.656 -	count_entries(&root);
  31.657 -	e = importer->set->files.data;
  31.658 -	e->name = root.name;
  31.659 -	e->flags = RAZOR_ENTRY_LAST;
  31.660 -	e->start = importer->files.size ? 1 : 0;
  31.661 -	list_set_empty(&e->packages);
  31.662 -
  31.663 -	serialize_files(importer->set, &root, &importer->set->files);
  31.664 -
  31.665 -	array_release(&importer->files);
  31.666 -}
  31.667 -
  31.668 -static struct razor_entry *
  31.669 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
  31.670 -
  31.671 -static void
  31.672 -list_to_array(struct list *list, struct array *array)
  31.673 -{
  31.674 -	uint32_t *item;
  31.675 -
  31.676 -	while (list) {
  31.677 -		 item = array_add(array, sizeof *item);
  31.678 -		 *item = list->data;
  31.679 -		 list = list_next(list);
  31.680 -	}
  31.681 -}
  31.682 -
  31.683 -static int
  31.684 -compare_file_requires(const void *p1, const void *p2, void *data)
  31.685 -{
  31.686 -	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
  31.687 -	const char *pool = data;
  31.688 -
  31.689 -	return strcmp(&pool[*f1], &pool[*f2]);
  31.690 -}
  31.691 -
  31.692 -static void
  31.693 -find_file_provides(struct razor_importer *importer)
  31.694 -{
  31.695 -	struct razor_property *prop;
  31.696 -	struct razor_entry *top, *entry;
  31.697 -	struct razor_package *packages;
  31.698 -	struct array pkgprops;
  31.699 -	struct list *pkg;
  31.700 -	uint32_t *req, *req_start, *req_end;
  31.701 -	uint32_t *map, *newprop;
  31.702 -	char *pool;
  31.703 -
  31.704 -	pool = importer->set->string_pool.data;
  31.705 -	packages = importer->set->packages.data;
  31.706 -	top = importer->set->files.data;
  31.707 -
  31.708 -	req = req_start = importer->file_requires.data;
  31.709 -	req_end = importer->file_requires.data + importer->file_requires.size;
  31.710 -	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
  31.711 -				    compare_file_requires, pool);
  31.712 -	free(map);
  31.713 -
  31.714 -	for (req = req_start; req < req_end; req++) {
  31.715 -		if (req > req_start && req[0] == req[-1])
  31.716 -			continue;
  31.717 -		entry = find_entry(importer->set, top, &pool[*req]);
  31.718 -		if (!entry)
  31.719 -			continue;
  31.720 -
  31.721 -		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
  31.722 -			prop = array_add(&importer->set->properties, sizeof *prop);
  31.723 -			prop->name = *req;
  31.724 -			prop->type = RAZOR_PROPERTY_PROVIDES;
  31.725 -			prop->relation = RAZOR_VERSION_EQUAL;
  31.726 -			prop->version = hashtable_tokenize(&importer->table, "");
  31.727 -			list_set_ptr(&prop->packages, pkg->data);
  31.728 -
  31.729 -			/* Update property list of pkg */
  31.730 -			array_init(&pkgprops);
  31.731 -			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
  31.732 -			newprop = array_add(&pkgprops, sizeof *newprop);
  31.733 -			*newprop = prop - (struct razor_property *)importer->set->properties.data;
  31.734 -			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
  31.735 -			array_release(&pkgprops);
  31.736 -		}
  31.737 -	}
  31.738 -
  31.739 -	array_release(&importer->file_requires);
  31.740 -}
  31.741 -
  31.742 -static void
  31.743 -build_package_file_lists(struct razor_set *set, uint32_t *rmap)
  31.744 -{
  31.745 -	struct razor_package *p, *packages;
  31.746 -	struct array *pkgs;
  31.747 -	struct razor_entry *e, *end;
  31.748 -	struct list *r;
  31.749 -	uint32_t *q;
  31.750 -	int i, count;
  31.751 -
  31.752 -	count = set->packages.size / sizeof *p;
  31.753 -	pkgs = zalloc(count * sizeof *pkgs);
  31.754 -
  31.755 -	end = set->files.data + set->files.size;
  31.756 -	for (e = set->files.data; e < end; e++) {
  31.757 -		list_remap_head(&e->packages, rmap);
  31.758 -		r = list_first(&e->packages, &set->package_pool);
  31.759 -		while (r) {
  31.760 -			q = array_add(&pkgs[r->data], sizeof *q);
  31.761 -			*q = e - (struct razor_entry *) set->files.data;
  31.762 -			r = list_next(r);
  31.763 -		}
  31.764 -	}
  31.765 -
  31.766 -	packages = set->packages.data;
  31.767 -	for (i = 0; i < count; i++) {
  31.768 -		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
  31.769 -		array_release(&pkgs[i]);
  31.770 -	}
  31.771 -	free(pkgs);
  31.772 -}
  31.773 -
  31.774 -struct razor_set *
  31.775 -razor_importer_finish(struct razor_importer *importer)
  31.776 -{
  31.777 -	struct razor_set *set;
  31.778 -	uint32_t *map, *rmap;
  31.779 -	int i, count;
  31.780 -
  31.781 -	build_file_tree(importer);
  31.782 -	find_file_provides(importer);
  31.783 -
  31.784 -	map = uniqueify_properties(importer->set);
  31.785 -	list_remap_pool(&importer->set->property_pool, map);
  31.786 -	free(map);
  31.787 -
  31.788 -	count = importer->set->packages.size / sizeof(struct razor_package);
  31.789 -	map = razor_qsort_with_data(importer->set->packages.data,
  31.790 -				    count,
  31.791 -				    sizeof(struct razor_package),
  31.792 -				    compare_packages,
  31.793 -				    importer->set);
  31.794 -
  31.795 -	rmap = malloc(count * sizeof *rmap);
  31.796 -	for (i = 0; i < count; i++)
  31.797 -		rmap[map[i]] = i;
  31.798 -	free(map);
  31.799 -
  31.800 -	list_remap_pool(&importer->set->package_pool, rmap);
  31.801 -	build_package_file_lists(importer->set, rmap);
  31.802 -	remap_property_package_links(&importer->set->properties, rmap);
  31.803 -	free(rmap);
  31.804 -
  31.805 -	set = importer->set;
  31.806 -	hashtable_release(&importer->table);
  31.807 -	free(importer);
  31.808 -
  31.809 -	return set;
  31.810 -}
  31.811 -
  31.812 -struct razor_package_iterator {
  31.813 -	struct razor_set *set;
  31.814 -	struct razor_package *package, *end;
  31.815 -	struct list *index;
  31.816 -	int free_index;
  31.817 -};
  31.818 -
  31.819 -static struct razor_package_iterator *
  31.820 -razor_package_iterator_create_with_index(struct razor_set *set,
  31.821 -					 struct list *index)
  31.822 -{
  31.823 -	struct razor_package_iterator *pi;
  31.824 -
  31.825 -	pi = zalloc(sizeof *pi);
  31.826 -	pi->set = set;
  31.827 -	pi->index = index;
  31.828 -
  31.829 -	return pi;
  31.830 -}
  31.831 -
  31.832 -struct razor_package_iterator *
  31.833 -razor_package_iterator_create(struct razor_set *set)
  31.834 -{
  31.835 -	struct razor_package_iterator *pi;
  31.836 -
  31.837 -	pi = zalloc(sizeof *pi);
  31.838 -	pi->set = set;
  31.839 -	pi->end = set->packages.data + set->packages.size;
  31.840 -	pi->package = set->packages.data;
  31.841 -
  31.842 -	return pi;
  31.843 -}
  31.844 -
  31.845 -static void
  31.846 -razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
  31.847 -					 struct razor_set *set,
  31.848 -					 struct razor_property *property)
  31.849 -{
  31.850 -	memset(pi, 0, sizeof *pi);
  31.851 -	pi->set = set;
  31.852 -	pi->index = list_first(&property->packages, &set->package_pool);
  31.853 -}
  31.854 -
  31.855 -struct razor_package_iterator *
  31.856 -razor_package_iterator_create_for_property(struct razor_set *set,
  31.857 -					   struct razor_property *property)
  31.858 -{
  31.859 -	struct list *index;
  31.860 -
  31.861 -	index = list_first(&property->packages, &set->package_pool);
  31.862 -	return razor_package_iterator_create_with_index(set, index);
  31.863 -}
  31.864 -
  31.865 -int
  31.866 -razor_package_iterator_next(struct razor_package_iterator *pi,
  31.867 -			    struct razor_package **package,
  31.868 -			    const char **name,
  31.869 -			    const char **version,
  31.870 -			    const char **arch)
  31.871 -{
  31.872 -	char *pool;
  31.873 -	int valid;
  31.874 -	struct razor_package *p, *packages;
  31.875 -
  31.876 -	if (pi->package) {
  31.877 -		p = pi->package++;
  31.878 -		valid = p < pi->end;
  31.879 -	} else if (pi->index) {
  31.880 -		packages = pi->set->packages.data;
  31.881 -		p = &packages[pi->index->data];
  31.882 -		pi->index = list_next(pi->index);
  31.883 -		valid = 1;
  31.884 -	} else
  31.885 -		valid = 0;
  31.886 -
  31.887 -	if (valid) {
  31.888 -		pool = pi->set->string_pool.data;
  31.889 -		*package = p;
  31.890 -		*name = &pool[p->name];
  31.891 -		*version = &pool[p->version];
  31.892 -		*arch = &pool[p->arch];
  31.893 -	} else {
  31.894 -		*package = NULL;
  31.895 -	}
  31.896 -
  31.897 -	return valid;
  31.898 -}
  31.899 -
  31.900 -void
  31.901 -razor_package_iterator_destroy(struct razor_package_iterator *pi)
  31.902 -{
  31.903 -	if (pi->free_index)
  31.904 -		free(pi->index);
  31.905 -
  31.906 -	free(pi);
  31.907 -}
  31.908 -
  31.909 -struct razor_package *
  31.910 -razor_set_get_package(struct razor_set *set, const char *package)
  31.911 -{
  31.912 -	struct razor_package_iterator *pi;
  31.913 -	struct razor_package *p;
  31.914 -	const char *name, *version, *arch;
  31.915 -
  31.916 -	pi = razor_package_iterator_create(set);
  31.917 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  31.918 -		if (strcmp(package, name) == 0)
  31.919 -			break;
  31.920 -	}
  31.921 -	razor_package_iterator_destroy(pi);
  31.922 -
  31.923 -	return p;
  31.924 -}
  31.925 -
  31.926 -struct razor_property_iterator {
  31.927 -	struct razor_set *set;
  31.928 -	struct razor_property *property, *end;
  31.929 -	struct list *index;
  31.930 -};
  31.931 -
  31.932 -struct razor_property_iterator *
  31.933 -razor_property_iterator_create(struct razor_set *set,
  31.934 -			       struct razor_package *package)
  31.935 -{
  31.936 -	struct razor_property_iterator *pi;
  31.937 -
  31.938 -	pi = zalloc(sizeof *pi);
  31.939 -	pi->set = set;
  31.940 -
  31.941 -	if (package) {
  31.942 -		pi->index = list_first(&package->properties,
  31.943 -				       &set->property_pool);
  31.944 -	} else {
  31.945 -		pi->property = set->properties.data;
  31.946 -		pi->end = set->properties.data + set->properties.size;
  31.947 -	}
  31.948 -
  31.949 -	return pi;
  31.950 -}
  31.951 -
  31.952 -int
  31.953 -razor_property_iterator_next(struct razor_property_iterator *pi,
  31.954 -			     struct razor_property **property,
  31.955 -			     const char **name,
  31.956 -			     enum razor_version_relation *relation,
  31.957 -			     const char **version,
  31.958 -			     enum razor_property_type *type)
  31.959 -{
  31.960 -	char *pool;
  31.961 -	int valid;
  31.962 -	struct razor_property *p, *properties;
  31.963 -
  31.964 -	if (pi->property) {
  31.965 -		p = pi->property++;
  31.966 -		valid = p < pi->end;
  31.967 -	} else if (pi->index) {
  31.968 -		properties = pi->set->properties.data;
  31.969 -		p = &properties[pi->index->data];
  31.970 -		pi->index = list_next(pi->index);
  31.971 -		valid = 1;
  31.972 -	} else
  31.973 -		valid = 0;
  31.974 -
  31.975 -	if (valid) {
  31.976 -		pool = pi->set->string_pool.data;
  31.977 -		*property = p;
  31.978 -		*name = &pool[p->name];
  31.979 -		*relation = p->relation;
  31.980 -		*version = &pool[p->version];
  31.981 -		*type = p->type;
  31.982 -	} else {
  31.983 -		*property = NULL;
  31.984 -	}
  31.985 -
  31.986 -	return valid;
  31.987 -}
  31.988 -
  31.989 -void
  31.990 -razor_property_iterator_destroy(struct razor_property_iterator *pi)
  31.991 -{
  31.992 -	free(pi);
  31.993 -}
  31.994 -
  31.995 -static struct razor_entry *
  31.996 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
  31.997 -{
  31.998 -	struct razor_entry *e;
  31.999 -	const char *n, *pool = set->string_pool.data;
 31.1000 -	int len;
 31.1001 -
 31.1002 -	e = (struct razor_entry *) set->files.data + dir->start;
 31.1003 -	do {
 31.1004 -		n = pool + e->name;
 31.1005 -		if (strcmp(pattern + 1, n) == 0)
 31.1006 -			return e;
 31.1007 -		len = strlen(n);
 31.1008 -		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
 31.1009 -		    pattern[len + 1] == '/') {
 31.1010 -			return find_entry(set, e, pattern + len + 1);
 31.1011 -		}
 31.1012 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 31.1013 -
 31.1014 -	return NULL;
 31.1015 -}
 31.1016 -
 31.1017 -static void
 31.1018 -list_dir(struct razor_set *set, struct razor_entry *dir,
 31.1019 -	 char *prefix, const char *pattern)
 31.1020 -{
 31.1021 -	struct razor_entry *e;
 31.1022 -	const char *n, *pool = set->string_pool.data;
 31.1023 -
 31.1024 -	e = (struct razor_entry *) set->files.data + dir->start;
 31.1025 -	do {
 31.1026 -		n = pool + e->name;
 31.1027 -		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
 31.1028 -			continue;
 31.1029 -		printf("%s/%s\n", prefix, n);
 31.1030 -		if (e->start) {
 31.1031 -			char *sub = prefix + strlen (prefix);
 31.1032 -			*sub = '/';
 31.1033 -			strcpy (sub + 1, n);
 31.1034 -			list_dir(set, e, prefix, pattern);
 31.1035 -			*sub = '\0';
 31.1036 -		}
 31.1037 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 31.1038 -}
 31.1039 -
 31.1040 -void
 31.1041 -razor_set_list_files(struct razor_set *set, const char *pattern)
 31.1042 -{
 31.1043 -	struct razor_entry *e;
 31.1044 -	char buffer[512], *p, *base;
 31.1045 -
 31.1046 -	if (pattern == NULL || !strcmp (pattern, "/")) {
 31.1047 -		buffer[0] = '\0';
 31.1048 -		list_dir(set, set->files.data, buffer, NULL);
 31.1049 -		return;
 31.1050 -	}
 31.1051 -
 31.1052 -	strcpy(buffer, pattern);
 31.1053 -	e = find_entry(set, set->files.data, buffer);
 31.1054 -	if (e && e->start > 0) {
 31.1055 -		base = NULL;
 31.1056 -	} else {
 31.1057 -		p = strrchr(buffer, '/');
 31.1058 -		if (p) {
 31.1059 -			*p = '\0';
 31.1060 -			base = p + 1;
 31.1061 -		} else {
 31.1062 -			base = NULL;
 31.1063 -		}
 31.1064 -	}
 31.1065 -	e = find_entry(set, set->files.data, buffer);
 31.1066 -	if (e->start != 0)
 31.1067 -		list_dir(set, e, buffer, base);
 31.1068 -}
 31.1069 -
 31.1070 -struct razor_package_iterator *
 31.1071 -razor_package_iterator_create_for_file(struct razor_set *set,
 31.1072 -				       const char *filename)
 31.1073 -{
 31.1074 -	struct razor_entry *entry;
 31.1075 -	struct list *index;
 31.1076 -
 31.1077 -	entry = find_entry(set, set->files.data, filename);
 31.1078 -	if (entry == NULL)
 31.1079 -		return NULL;
 31.1080 -	
 31.1081 -	index = list_first(&entry->packages, &set->package_pool);
 31.1082 -	return razor_package_iterator_create_with_index(set, index);
 31.1083 -}
 31.1084 -
 31.1085 -static struct list *
 31.1086 -list_package_files(struct razor_set *set, struct list *r,
 31.1087 -		   struct razor_entry *dir, uint32_t end,
 31.1088 -		   char *prefix)
 31.1089 -{
 31.1090 -	struct razor_entry *e, *f, *entries;
 31.1091 -	uint32_t next, file;
 31.1092 -	char *pool;
 31.1093 -	int len;
 31.1094 -	
 31.1095 -	entries = (struct razor_entry *) set->files.data;
 31.1096 -	pool = set->string_pool.data;
 31.1097 -
 31.1098 -	e = entries + dir->start;
 31.1099 -	do {
 31.1100 -		if (entries + r->data == e) {
 31.1101 -			printf("%s/%s\n", prefix, pool + e->name);
 31.1102 -			r = list_next(r);
 31.1103 -			if (!r)
 31.1104 -				return NULL;
 31.1105 -			if (r->data >= end)
 31.1106 -				return r;
 31.1107 -		}
 31.1108 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 31.1109 -
 31.1110 -	e = entries + dir->start;
 31.1111 -	do {
 31.1112 -		if (e->start == 0)
 31.1113 -			continue;
 31.1114 -
 31.1115 -		if (e->flags & RAZOR_ENTRY_LAST)
 31.1116 -			next = end;
 31.1117 -		else {
 31.1118 -			f = e + 1; 
 31.1119 -			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
 31.1120 -				f++;
 31.1121 -			if (f->start == 0)
 31.1122 -				next = end;
 31.1123 -			else
 31.1124 -				next = f->start;
 31.1125 -		}
 31.1126 -
 31.1127 -		file = r->data;
 31.1128 -		if (e->start <= file && file < next) {
 31.1129 -			len = strlen(prefix);
 31.1130 -			prefix[len] = '/';
 31.1131 -			strcpy(prefix + len + 1, pool + e->name);
 31.1132 -			r = list_package_files(set, r, e, next, prefix);
 31.1133 -			prefix[len] = '\0';
 31.1134 -		}
 31.1135 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
 31.1136 -
 31.1137 -	return r;
 31.1138 -}
 31.1139 -
 31.1140 -void
 31.1141 -razor_set_list_package_files(struct razor_set *set, const char *name)
 31.1142 -{
 31.1143 -	struct razor_package *package;
 31.1144 -	struct list *r;
 31.1145 -	uint32_t end;
 31.1146 -	char buffer[512];
 31.1147 -
 31.1148 -	package = razor_set_get_package(set, name);
 31.1149 -
 31.1150 -	r = list_first(&package->files, &set->file_pool);
 31.1151 -	end = set->files.size / sizeof (struct razor_entry);
 31.1152 -	buffer[0] = '\0';
 31.1153 -	list_package_files(set, r, set->files.data, end, buffer);
 31.1154 -}
 31.1155 -
 31.1156 -#define UPSTREAM_SOURCE 0x80
 31.1157 -
 31.1158 -struct source {
 31.1159 -	struct razor_set *set;
 31.1160 -	uint32_t *property_map;
 31.1161 -	uint32_t *file_map;
 31.1162 -};
 31.1163 -
 31.1164 -struct razor_merger {
 31.1165 -	struct razor_set *set;
 31.1166 -	struct hashtable table;
 31.1167 -	struct source source1;
 31.1168 -	struct source source2;
 31.1169 -};
 31.1170 -
 31.1171 -static struct razor_merger *
 31.1172 -razor_merger_create(struct razor_set *set1, struct razor_set *set2)
 31.1173 -{
 31.1174 -	struct razor_merger *merger;
 31.1175 -	int count;
 31.1176 -	size_t size;
 31.1177 -
 31.1178 -	merger = zalloc(sizeof *merger);
 31.1179 -	merger->set = razor_set_create();
 31.1180 -	hashtable_init(&merger->table, &merger->set->string_pool);
 31.1181 -
 31.1182 -	merger->source1.set = set1;
 31.1183 -	count = set1->properties.size / sizeof (struct razor_property);
 31.1184 -	size = count * sizeof merger->source1.property_map[0];
 31.1185 -	merger->source1.property_map = zalloc(size);
 31.1186 -	count = set1->files.size / sizeof (struct razor_entry);
 31.1187 -	size = count * sizeof merger->source1.file_map[0];
 31.1188 -	merger->source1.file_map = zalloc(size);
 31.1189 -
 31.1190 -	merger->source2.set = set2;
 31.1191 -	count = set2->properties.size / sizeof (struct razor_property);
 31.1192 -	size = count * sizeof merger->source2.property_map[0];
 31.1193 -	merger->source2.property_map = zalloc(size);
 31.1194 -	count = set2->files.size / sizeof (struct razor_entry);
 31.1195 -	size = count * sizeof merger->source2.file_map[0];
 31.1196 -	merger->source2.file_map = zalloc(size);
 31.1197 -
 31.1198 -	return merger;
 31.1199 -}
 31.1200 -
 31.1201 -static void
 31.1202 -razor_merger_add_package(struct razor_merger *merger,
 31.1203 -			 struct razor_package *package)
 31.1204 -{
 31.1205 -	char *pool;
 31.1206 -	struct list *r;
 31.1207 -	struct razor_package *p;
 31.1208 -	struct razor_set *set1;
 31.1209 -	struct source *source;
 31.1210 -	uint32_t flags;
 31.1211 -
 31.1212 -	set1 = merger->source1.set;
 31.1213 -	if (set1->packages.data <= (void *) package &&
 31.1214 -	    (void *) package < set1->packages.data + set1->packages.size) {
 31.1215 -		source = &merger->source1;
 31.1216 -		flags = 0;
 31.1217 -	} else {
 31.1218 -		source = &merger->source2;
 31.1219 -		flags = UPSTREAM_SOURCE;
 31.1220 -	}
 31.1221 -
 31.1222 -	pool = source->set->string_pool.data;
 31.1223 -	p = array_add(&merger->set->packages, sizeof *p);
 31.1224 -	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
 31.1225 -	p->flags = flags;
 31.1226 -	p->version = hashtable_tokenize(&merger->table,
 31.1227 -					&pool[package->version]);
 31.1228 -	p->arch = hashtable_tokenize(&merger->table,
 31.1229 -				     &pool[package->arch]);
 31.1230 -
 31.1231 -	p->properties = package->properties;
 31.1232 -	r = list_first(&package->properties, &source->set->property_pool);
 31.1233 -	while (r) {
 31.1234 -		source->property_map[r->data] = 1;
 31.1235 -		r = list_next(r);
 31.1236 -	}
 31.1237 -
 31.1238 -	p->files = package->files;
 31.1239 -	r = list_first(&package->files, &source->set->file_pool);
 31.1240 -	while (r) {
 31.1241 -		source->file_map[r->data] = 1;
 31.1242 -		r = list_next(r);
 31.1243 -	}
 31.1244 -}
 31.1245 -
 31.1246 -static uint32_t
 31.1247 -add_property(struct razor_merger *merger,
 31.1248 -	     const char *name, enum razor_version_relation relation,
 31.1249 -	     const char *version, int type)
 31.1250 -{
 31.1251 -	struct razor_property *p;
 31.1252 -
 31.1253 -	p = array_add(&merger->set->properties, sizeof *p);
 31.1254 -	p->name = hashtable_tokenize(&merger->table, name);
 31.1255 -	p->flags = 0;
 31.1256 -	p->type = type;
 31.1257 -	p->relation = relation;
 31.1258 -	p->version = hashtable_tokenize(&merger->table, version);
 31.1259 -
 31.1260 -	return p - (struct razor_property *) merger->set->properties.data;
 31.1261 -}
 31.1262 -
 31.1263 -static void
 31.1264 -merge_properties(struct razor_merger *merger)
 31.1265 -{
 31.1266 -	struct razor_property *p1, *p2;
 31.1267 -	struct razor_set *set1, *set2;
 31.1268 -	uint32_t *map1, *map2;
 31.1269 -	int i, j, cmp, count1, count2;
 31.1270 -	char *pool1, *pool2;
 31.1271 -
 31.1272 -	set1 = merger->source1.set;
 31.1273 -	set2 = merger->source2.set;
 31.1274 -	map1 = merger->source1.property_map;
 31.1275 -	map2 = merger->source2.property_map;
 31.1276 -
 31.1277 -	i = 0;
 31.1278 -	j = 0;
 31.1279 -	pool1 = set1->string_pool.data;
 31.1280 -	pool2 = set2->string_pool.data;
 31.1281 -
 31.1282 -	count1 = set1->properties.size / sizeof *p1;
 31.1283 -	count2 = set2->properties.size / sizeof *p2;
 31.1284 -	while (i < count1 || j < count2) {
 31.1285 -		if (i < count1 && map1[i] == 0) {
 31.1286 -			i++;
 31.1287 -			continue;
 31.1288 -		}
 31.1289 -		if (j < count2 && map2[j] == 0) {
 31.1290 -			j++;
 31.1291 -			continue;
 31.1292 -		}
 31.1293 -		p1 = (struct razor_property *) set1->properties.data + i;
 31.1294 -		p2 = (struct razor_property *) set2->properties.data + j;
 31.1295 -		if (i < count1 && j < count2)
 31.1296 -			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
 31.1297 -		else if (i < count1)
 31.1298 -			cmp = -1;
 31.1299 -		else
 31.1300 -			cmp = 1;
 31.1301 -		if (cmp == 0)
 31.1302 -			cmp = p1->type - p2->type;
 31.1303 -		if (cmp == 0)
 31.1304 -			cmp = p1->relation - p2->relation;
 31.1305 -		if (cmp == 0)
 31.1306 -			cmp = versioncmp(&pool1[p1->version],
 31.1307 -					 &pool2[p2->version]);
 31.1308 -		if (cmp < 0) {
 31.1309 -			map1[i++] = add_property(merger,
 31.1310 -						 &pool1[p1->name],
 31.1311 -						 p1->relation,
 31.1312 -						 &pool1[p1->version],
 31.1313 -						 p1->type);
 31.1314 -		} else if (cmp > 0) {
 31.1315 -			map2[j++] = add_property(merger,
 31.1316 -						 &pool2[p2->name],
 31.1317 -						 p2->relation,
 31.1318 -						 &pool2[p2->version],
 31.1319 -						 p2->type);
 31.1320 -		} else  {
 31.1321 -			map1[i++] = map2[j++] = add_property(merger,
 31.1322 -							     &pool1[p1->name],
 31.1323 -							     p1->relation,
 31.1324 -							     &pool1[p1->version],
 31.1325 -							     p1->type);
 31.1326 -		}
 31.1327 -	}
 31.1328 -}
 31.1329 -
 31.1330 -static void
 31.1331 -emit_properties(struct list_head *properties, struct array *source_pool,
 31.1332 -		uint32_t *map, struct array *pool)
 31.1333 -{
 31.1334 -	uint32_t r;
 31.1335 -	struct list *p, *q;
 31.1336 -
 31.1337 -	r = pool->size / sizeof *q;
 31.1338 -	p = list_first(properties, source_pool);
 31.1339 -	while (p) {
 31.1340 -		q = array_add(pool, sizeof *q);
 31.1341 -		q->data = map[p->data];
 31.1342 -		q->flags = p->flags;
 31.1343 -		p = list_next(p);
 31.1344 -	}
 31.1345 -
 31.1346 -	list_set_ptr(properties, r);
 31.1347 -}
 31.1348 -
 31.1349 -static uint32_t
 31.1350 -add_file(struct razor_merger *merger, const char *name)
 31.1351 -{
 31.1352 -	struct razor_entry *e;
 31.1353 -
 31.1354 -	e = array_add(&merger->set->files, sizeof *e);
 31.1355 -	e->name = hashtable_tokenize(&merger->table, name);
 31.1356 -	e->flags = 0;
 31.1357 -	e->start = 0;
 31.1358 -
 31.1359 -	return e - (struct razor_entry *)merger->set->files.data;
 31.1360 -}
 31.1361 -
 31.1362 -/* FIXME. Blah */
 31.1363 -static int
 31.1364 -fix_file_map(uint32_t *map,
 31.1365 -	     struct razor_entry *files,
 31.1366 -	     struct razor_entry *top)
 31.1367 -{
 31.1368 -	uint32_t e;
 31.1369 -	int found_file = 0;
 31.1370 -
 31.1371 -	e = top->start;
 31.1372 -	do {
 31.1373 -		if (files[e].start)
 31.1374 -			fix_file_map(map, files, &files[e]);
 31.1375 -		if (map[e])
 31.1376 -			found_file = 1;
 31.1377 -	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
 31.1378 -
 31.1379 -	if (found_file)
 31.1380 -		map[top - files] = 1;
 31.1381 -	return found_file;
 31.1382 -}
 31.1383 -
 31.1384 -struct merge_directory {
 31.1385 -	uint32_t merged, dir1, dir2;
 31.1386 -};
 31.1387 -
 31.1388 -static void
 31.1389 -merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
 31.1390 -{
 31.1391 -	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
 31.1392 -	struct razor_set *set1, *set2;
 31.1393 -	struct array merge_stack;
 31.1394 -	struct merge_directory *child_md, *end_md;
 31.1395 -	uint32_t *map1, *map2, start, last;
 31.1396 -	int cmp;
 31.1397 -	char *pool1, *pool2;
 31.1398 -
 31.1399 -	set1 = merger->source1.set;
 31.1400 -	set2 = merger->source2.set;
 31.1401 -	map1 = merger->source1.file_map;
 31.1402 -	map2 = merger->source2.file_map;
 31.1403 -	pool1 = set1->string_pool.data;
 31.1404 -	pool2 = set2->string_pool.data;
 31.1405 -	root1 = (struct razor_entry *) set1->files.data;
 31.1406 -	root2 = (struct razor_entry *) set2->files.data;
 31.1407 -
 31.1408 -	array_init(&merge_stack);
 31.1409 -
 31.1410 -	start = merger->set->files.size / sizeof (struct razor_entry);
 31.1411 -	last = 0;
 31.1412 -	e1 = md->dir1 ? root1 + md->dir1 : NULL;
 31.1413 -	e2 = md->dir2 ? root2 + md->dir2 : NULL;
 31.1414 -	while (e1 || e2) {
 31.1415 -		if (!e2 && !map1[e1 - root1]) {
 31.1416 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 31.1417 -				e1 = NULL;
 31.1418 -			continue;
 31.1419 -		}
 31.1420 -		if (!e1 && !map2[e2 - root2]) {
 31.1421 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 31.1422 -				e2 = NULL;
 31.1423 -			continue;
 31.1424 -		}
 31.1425 -		if (e1 && !map1[e1 - root1] &&
 31.1426 -		    e2 && !map1[e2 - root2]) {
 31.1427 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 31.1428 -				e1 = NULL;
 31.1429 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 31.1430 -				e2 = NULL;
 31.1431 -			continue;
 31.1432 -		}
 31.1433 -
 31.1434 -		if (!e1)
 31.1435 -			cmp = 1;
 31.1436 -		else if (!e2)
 31.1437 -			cmp = -1;
 31.1438 -		else {
 31.1439 -			cmp = strcmp (&pool1[e1->name],
 31.1440 -				      &pool2[e2->name]);
 31.1441 -		}
 31.1442 -
 31.1443 -		if (cmp < 0) {
 31.1444 -			if (map1[e1 - root1]) {
 31.1445 -				map1[e1 - root1] = last =
 31.1446 -					add_file(merger, &pool1[e1->name]);
 31.1447 -				if (e1->start) {
 31.1448 -					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 31.1449 -					child_md->merged = last;
 31.1450 -					child_md->dir1 = e1->start;
 31.1451 -					child_md->dir2 = 0;
 31.1452 -				}
 31.1453 -			}
 31.1454 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 31.1455 -				e1 = NULL;
 31.1456 -		} else if (cmp > 0) {
 31.1457 -			if (map2[e2 - root2]) {
 31.1458 -				map2[e2 - root2] = last =
 31.1459 -					add_file(merger, &pool2[e2->name]);
 31.1460 -				if (e2->start) {
 31.1461 -					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 31.1462 -					child_md->merged = last;
 31.1463 -					child_md->dir1 = 0;
 31.1464 -					child_md->dir2 = e2->start;
 31.1465 -				}
 31.1466 -			}
 31.1467 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 31.1468 -				e2 = NULL;
 31.1469 -		} else {
 31.1470 -			map1[e1 - root1] = map2[e2- root2] = last =
 31.1471 -				add_file(merger, &pool1[e1->name]);
 31.1472 -			if (e1->start || e2->start) {
 31.1473 -				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 31.1474 -				child_md->merged = last;
 31.1475 -				child_md->dir1 = e1->start;
 31.1476 -				child_md->dir2 = e2->start;
 31.1477 -			}
 31.1478 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 31.1479 -				e1 = NULL;
 31.1480 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 31.1481 -				e2 = NULL;
 31.1482 -		}
 31.1483 -	}
 31.1484 -
 31.1485 -	mroot = (struct razor_entry *)merger->set->files.data;
 31.1486 -	if (last) {
 31.1487 -		mroot[last].flags = RAZOR_ENTRY_LAST;
 31.1488 -		mroot[md->merged].start = start;
 31.1489 -	} else
 31.1490 -		mroot[md->merged].start = 0;
 31.1491 -
 31.1492 -	end_md = merge_stack.data + merge_stack.size;
 31.1493 -	for (child_md = merge_stack.data; child_md < end_md; child_md++)
 31.1494 -		merge_one_directory(merger, child_md);
 31.1495 -	array_release(&merge_stack);
 31.1496 -}
 31.1497 -
 31.1498 -static void
 31.1499 -merge_files(struct razor_merger *merger)
 31.1500 -{
 31.1501 -	struct razor_entry *root;
 31.1502 -	struct merge_directory md;
 31.1503 -	uint32_t *map1, *map2;
 31.1504 -
 31.1505 -	map1 = merger->source1.file_map;
 31.1506 -	map2 = merger->source2.file_map;
 31.1507 -
 31.1508 -	md.merged = 0;
 31.1509 -
 31.1510 -	if (merger->source1.set->files.size) {
 31.1511 -		root = (struct razor_entry *) merger->source1.set->files.data;
 31.1512 -		if (root->start)
 31.1513 -			fix_file_map(map1, root, root);
 31.1514 -		md.dir1 = root->start;
 31.1515 -	} else
 31.1516 -		md.dir1 = 0;
 31.1517 -
 31.1518 -	if (merger->source2.set->files.size) {
 31.1519 -		root = (struct razor_entry *) merger->source2.set->files.data;
 31.1520 -		if (root->start)
 31.1521 -			fix_file_map(map2, root, root);
 31.1522 -		md.dir2 = root->start;
 31.1523 -	} else
 31.1524 -		md.dir2 = 0;
 31.1525 -
 31.1526 -	merge_one_directory(merger, &md);
 31.1527 -}
 31.1528 -
 31.1529 -static void
 31.1530 -emit_files(struct list_head *files, struct array *source_pool,
 31.1531 -	   uint32_t *map, struct array *pool)
 31.1532 -{
 31.1533 -	uint32_t r;
 31.1534 -	struct list *p, *q;
 31.1535 -
 31.1536 -	r = pool->size / sizeof *q;
 31.1537 -	p = list_first(files, source_pool);
 31.1538 -	while (p) {
 31.1539 -		q = array_add(pool, sizeof *q);
 31.1540 -		q->data = map[p->data];
 31.1541 -		q->flags = p->flags;
 31.1542 -		p = list_next(p);
 31.1543 -	}
 31.1544 -
 31.1545 -	list_set_ptr(files, r);
 31.1546 -}
 31.1547 -
 31.1548 -/* Rebuild property->packages maps.  We can't just remap these, as a
 31.1549 - * property may have lost or gained a number of packages.  Allocate an
 31.1550 - * array per property and loop through the packages and add them to
 31.1551 - * the arrays for their properties. */
 31.1552 -static void
 31.1553 -rebuild_property_package_lists(struct razor_set *set)
 31.1554 -{
 31.1555 -	struct array *pkgs, *a;
 31.1556 -	struct razor_package *pkg, *pkg_end;
 31.1557 -	struct razor_property *prop, *prop_end;
 31.1558 -	struct list *r;
 31.1559 -	uint32_t *q;
 31.1560 -	int count;
 31.1561 -
 31.1562 -	count = set->properties.size / sizeof (struct razor_property);
 31.1563 -	pkgs = zalloc(count * sizeof *pkgs);
 31.1564 -	pkg_end = set->packages.data + set->packages.size;
 31.1565 -
 31.1566 -	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
 31.1567 -		r = list_first(&pkg->properties, &set->property_pool);
 31.1568 -		while (r) {
 31.1569 -			q = array_add(&pkgs[r->data], sizeof *q);
 31.1570 -			*q = pkg - (struct razor_package *) set->packages.data;
 31.1571 -			r = list_next(r);
 31.1572 -		}
 31.1573 -	}
 31.1574 -
 31.1575 -	prop_end = set->properties.data + set->properties.size;
 31.1576 -	a = pkgs;
 31.1577 -	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
 31.1578 -		list_set_array(&prop->packages, &set->package_pool, a, 0);
 31.1579 -		array_release(a);
 31.1580 -	}
 31.1581 -	free(pkgs);
 31.1582 -}
 31.1583 -
 31.1584 -static void
 31.1585 -rebuild_file_package_lists(struct razor_set *set)
 31.1586 -{
 31.1587 -	struct array *pkgs, *a;
 31.1588 -	struct razor_package *pkg, *pkg_end;
 31.1589 -	struct razor_entry *entry, *entry_end;
 31.1590 -	struct list *r;
 31.1591 -	uint32_t *q;
 31.1592 -	int count;
 31.1593 -
 31.1594 -	count = set->files.size / sizeof (struct razor_entry);
 31.1595 -	pkgs = zalloc(count * sizeof *pkgs);
 31.1596 -	pkg_end = set->packages.data + set->packages.size;
 31.1597 -
 31.1598 -	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
 31.1599 -		r = list_first(&pkg->files, &set->file_pool);
 31.1600 -		while (r) {
 31.1601 -			q = array_add(&pkgs[r->data], sizeof *q);
 31.1602 -			*q = pkg - (struct razor_package *) set->packages.data;
 31.1603 -			r = list_next(r);
 31.1604 -		}
 31.1605 -	}
 31.1606 -
 31.1607 -	entry_end = set->files.data + set->files.size;
 31.1608 -	a = pkgs;
 31.1609 -	for (entry = set->files.data; entry < entry_end; entry++, a++) {
 31.1610 -		list_set_array(&entry->packages, &set->package_pool, a, 0);
 31.1611 -		array_release(a);
 31.1612 -	}
 31.1613 -	free(pkgs);
 31.1614 -}
 31.1615 -
 31.1616 -static struct razor_set *
 31.1617 -razor_merger_finish(struct razor_merger *merger)
 31.1618 -{
 31.1619 -	struct razor_set *result;
 31.1620 -	struct razor_package *p, *pend;
 31.1621 -
 31.1622 -	/* As we built the package list, we filled out a bitvector of
 31.1623 -	 * the properties that are referenced by the packages in the
 31.1624 -	 * new set.  Now we do a parallel loop through the properties
 31.1625 -	 * and emit those marked in the bit vector to the new set.  In
 31.1626 -	 * the process, we update the bit vector to actually map from
 31.1627 -	 * indices in the old property list to indices in the new
 31.1628 -	 * property list for both sets. */
 31.1629 -
 31.1630 -	merge_properties(merger);
 31.1631 -	merge_files(merger);
 31.1632 -
 31.1633 -	/* Now we loop through the packages again and emit the
 31.1634 -	 * property lists, remapped to point to the new properties. */
 31.1635 -
 31.1636 -	pend = merger->set->packages.data + merger->set->packages.size;
 31.1637 -	for (p = merger->set->packages.data; p < pend; p++) {
 31.1638 -		struct source *src;
 31.1639 -
 31.1640 -		if (p->flags & UPSTREAM_SOURCE)
 31.1641 -			src = &merger->source2;
 31.1642 -		else
 31.1643 -			src = &merger->source1;
 31.1644 -
 31.1645 -		emit_properties(&p->properties,
 31.1646 -				&src->set->property_pool,
 31.1647 -				src->property_map,
 31.1648 -				&merger->set->property_pool);
 31.1649 -		emit_files(&p->files,
 31.1650 -			   &src->set->file_pool,
 31.1651 -			   src->file_map,
 31.1652 -			   &merger->set->file_pool);
 31.1653 -		p->flags &= ~UPSTREAM_SOURCE;
 31.1654 -	}
 31.1655 -
 31.1656 -	rebuild_property_package_lists(merger->set);
 31.1657 -	rebuild_file_package_lists(merger->set);
 31.1658 -
 31.1659 -	result = merger->set;
 31.1660 -	hashtable_release(&merger->table);
 31.1661 -	free(merger);
 31.1662 -
 31.1663 -	return result;
 31.1664 -}
 31.1665 -
 31.1666 -/* The diff order matters.  We should sort the packages so that a
 31.1667 - * REMOVE of a package comes before the INSTALL, and so that all
 31.1668 - * requires for a package have been installed before the package.
 31.1669 - **/
 31.1670 -
 31.1671 -void
 31.1672 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
 31.1673 -	       razor_package_callback_t callback, void *data)
 31.1674 -{
 31.1675 - 	struct razor_package_iterator *pi1, *pi2;
 31.1676 - 	struct razor_package *p1, *p2;
 31.1677 -	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
 31.1678 -	int res;
 31.1679 -
 31.1680 -	pi1 = razor_package_iterator_create(set);
 31.1681 -	pi2 = razor_package_iterator_create(upstream);
 31.1682 -
 31.1683 -	razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
 31.1684 -	razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
 31.1685 -
 31.1686 -	while (p1 || p2) {
 31.1687 -		if (p1 && p2) {
 31.1688 -			res = strcmp(name1, name2);
 31.1689 -			if (res == 0)
 31.1690 -				res = versioncmp(version1, version2);
 31.1691 -		} else {
 31.1692 -			res = 0;
 31.1693 -		}
 31.1694 -
 31.1695 -		if (p2 == NULL || res < 0)
 31.1696 -			callback(name1, version1, NULL, arch1, data);
 31.1697 -		else if (p1 == NULL || res > 0)
 31.1698 -			callback(name2, NULL, version2, arch2, data);
 31.1699 -
 31.1700 -		if (p1 != NULL && res <= 0)
 31.1701 -			razor_package_iterator_next(pi1, &p1,
 31.1702 -						    &name1, &version1, &arch1);
 31.1703 -		if (p2 != NULL && res >= 0)
 31.1704 -			razor_package_iterator_next(pi2, &p2,
 31.1705 -						    &name2, &version2, &arch2);
 31.1706 -	}
 31.1707 -
 31.1708 -	razor_package_iterator_destroy(pi1);
 31.1709 -	razor_package_iterator_destroy(pi2);
 31.1710 -}
 31.1711 -
 31.1712 -static int
 31.1713 -provider_satisfies_requirement(struct razor_property *provider,
 31.1714 -			       const char *provider_strings,
 31.1715 -			       enum razor_version_relation relation,
 31.1716 -			       const char *required)
 31.1717 -{
 31.1718 -	int cmp, len;
 31.1719 -	const char *provided = &provider_strings[provider->version];
 31.1720 -
 31.1721 -	if (!*required)
 31.1722 -		return 1;
 31.1723 -	if (!*provided) {
 31.1724 -		if (relation >= RAZOR_VERSION_EQUAL)
 31.1725 -			return 1;
 31.1726 -		else
 31.1727 -			return 0;
 31.1728 -	}
 31.1729 -
 31.1730 -	cmp = versioncmp(provided, required);
 31.1731 -
 31.1732 -	switch (relation) {
 31.1733 -	case RAZOR_VERSION_LESS:
 31.1734 -		return cmp < 0;
 31.1735 -
 31.1736 -	case RAZOR_VERSION_LESS_OR_EQUAL:
 31.1737 -		if (cmp <= 0)
 31.1738 -			return 1;
 31.1739 -		/* fall through: FIXME, make sure this is correct */
 31.1740 -
 31.1741 -	case RAZOR_VERSION_EQUAL:
 31.1742 -		if (cmp == 0)
 31.1743 -			return 1;
 31.1744 -
 31.1745 -		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
 31.1746 -		len = strlen(required);
 31.1747 -		if (!strncmp(required, provided, len) && provided[len] == '-')
 31.1748 -			return 1;
 31.1749 -		return 0;
 31.1750 -
 31.1751 -	case RAZOR_VERSION_GREATER_OR_EQUAL:
 31.1752 -		return cmp >= 0;
 31.1753 -
 31.1754 -	case RAZOR_VERSION_GREATER:
 31.1755 -		return cmp > 0;
 31.1756 -	}
 31.1757 -
 31.1758 -	/* shouldn't happen */
 31.1759 -	return 0;
 31.1760 -}
 31.1761 -
 31.1762 -#define TRANS_PACKAGE_PRESENT		1
 31.1763 -#define TRANS_PACKAGE_UPDATE		2
 31.1764 -#define TRANS_PROPERTY_SATISFIED	0x80000000
 31.1765 -
 31.1766 -struct transaction_set {
 31.1767 -	struct razor_set *set;
 31.1768 -	uint32_t *packages;
 31.1769 -	uint32_t *properties;
 31.1770 -};
 31.1771 -
 31.1772 -struct razor_transaction {
 31.1773 -	int package_count, errors;
 31.1774 -	struct transaction_set system, upstream;
 31.1775 -	int changes;
 31.1776 -};
 31.1777 -
 31.1778 -static void
 31.1779 -transaction_set_init(struct transaction_set *ts, struct razor_set *set)
 31.1780 -{
 31.1781 -	int count;
 31.1782 -
 31.1783 -	ts->set = set;
 31.1784 -	count = set->packages.size / sizeof (struct razor_package);
 31.1785 -	ts->packages = zalloc(count * sizeof *ts->packages);
 31.1786 -	count = set->properties.size / sizeof (struct razor_property);
 31.1787 -	ts->properties = zalloc(count * sizeof *ts->properties);
 31.1788 -}
 31.1789 -
 31.1790 -static void
 31.1791 -transaction_set_release(struct transaction_set *ts)
 31.1792 -{
 31.1793 -	free(ts->packages);
 31.1794 -	free(ts->properties);
 31.1795 -}
 31.1796 -
 31.1797 -static void
 31.1798 -transaction_set_install_package(struct transaction_set *ts,
 31.1799 -				struct razor_package *package)
 31.1800 -{
 31.1801 -	struct razor_package *pkgs;
 31.1802 -	struct list *prop;
 31.1803 -	int i;
 31.1804 -
 31.1805 -	pkgs = ts->set->packages.data;
 31.1806 -	i = package - pkgs;
 31.1807 -	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
 31.1808 -		return;
 31.1809 -
 31.1810 -	ts->packages[i] = TRANS_PACKAGE_PRESENT;
 31.1811 -
 31.1812 -	prop = list_first(&package->properties, &ts->set->property_pool);
 31.1813 -	while (prop) {
 31.1814 -		ts->properties[prop->data]++;
 31.1815 -		prop = list_next(prop);
 31.1816 -	}
 31.1817 -}
 31.1818 -
 31.1819 -static void
 31.1820 -transaction_set_remove_package(struct transaction_set *ts,
 31.1821 -			       struct razor_package *package)
 31.1822 -{
 31.1823 -	struct razor_package *pkgs;
 31.1824 -	struct list *prop;
 31.1825 -	int i;
 31.1826 -
 31.1827 -	pkgs = ts->set->packages.data;
 31.1828 -	i = package - pkgs;
 31.1829 -	if (ts->packages[i] == 0)
 31.1830 -		return;
 31.1831 -
 31.1832 -	ts->packages[i] = 0;
 31.1833 -
 31.1834 -	prop = list_first(&package->properties, &ts->set->property_pool);
 31.1835 -	while (prop) {
 31.1836 -		ts->properties[prop->data]--;
 31.1837 -		prop = list_next(prop);
 31.1838 -	}
 31.1839 -}
 31.1840 -
 31.1841 -struct razor_transaction *
 31.1842 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
 31.1843 -{
 31.1844 -	struct razor_transaction *trans;
 31.1845 -	struct razor_package *p, *spkgs, *pend;
 31.1846 -
 31.1847 -	trans = zalloc(sizeof *trans);
 31.1848 -	transaction_set_init(&trans->system, system);
 31.1849 -	transaction_set_init(&trans->upstream, upstream);
 31.1850 -
 31.1851 -	spkgs = trans->system.set->packages.data;
 31.1852 -	pend = trans->system.set->packages.data +
 31.1853 -		trans->system.set->packages.size;
 31.1854 -	for (p = spkgs; p < pend; p++)
 31.1855 -		transaction_set_install_package(&trans->system, p);
 31.1856 -
 31.1857 -	return trans;
 31.1858 -}
 31.1859 -
 31.1860 -void
 31.1861 -razor_transaction_install_package(struct razor_transaction *trans,
 31.1862 -				  struct razor_package *package)
 31.1863 -{
 31.1864 -	transaction_set_install_package(&trans->upstream, package);
 31.1865 -	trans->changes++;
 31.1866 -}
 31.1867 -
 31.1868 -void
 31.1869 -razor_transaction_remove_package(struct razor_transaction *trans,
 31.1870 -				 struct razor_package *package)
 31.1871 -{
 31.1872 -	transaction_set_remove_package(&trans->system, package);
 31.1873 -	trans->changes++;
 31.1874 -}
 31.1875 -
 31.1876 -void
 31.1877 -razor_transaction_update_package(struct razor_transaction *trans,
 31.1878 -				  struct razor_package *package)
 31.1879 -{
 31.1880 -	struct razor_package *spkgs, *upkgs, *end;
 31.1881 -
 31.1882 -	spkgs = trans->system.set->packages.data;
 31.1883 -	upkgs = trans->upstream.set->packages.data;
 31.1884 -	end = trans->system.set->packages.data +
 31.1885 -		trans->system.set->packages.size;
 31.1886 -	if (spkgs <= package && package < end)
 31.1887 -		trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
 31.1888 -	else
 31.1889 -		trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
 31.1890 -}
 31.1891 -
 31.1892 -struct prop_iter {
 31.1893 -	struct razor_property *p, *start, *end;
 31.1894 -	const char *pool;
 31.1895 -	uint32_t *present;
 31.1896 -};
 31.1897 -
 31.1898 -static void
 31.1899 -prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
 31.1900 -{
 31.1901 -	pi->p = ts->set->properties.data;
 31.1902 -	pi->start = ts->set->properties.data;
 31.1903 -	pi->end = ts->set->properties.data + ts->set->properties.size;
 31.1904 -	pi->pool = ts->set->string_pool.data;
 31.1905 -	pi->present = ts->properties;
 31.1906 -}
 31.1907 -
 31.1908 -static int
 31.1909 -prop_iter_next(struct prop_iter *pi,
 31.1910 -	       enum razor_property_type type, struct razor_property **p)
 31.1911 -{
 31.1912 -	while (pi->p < pi->end) {
 31.1913 -		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
 31.1914 -		    pi->p->type == type) {
 31.1915 -			*p = pi->p++;
 31.1916 -			return 1;
 31.1917 -		}
 31.1918 -		pi->p++;
 31.1919 -	}
 31.1920 -
 31.1921 -	return 0;
 31.1922 -}
 31.1923 -
 31.1924 -static struct razor_property *
 31.1925 -prop_iter_seek_to(struct prop_iter *pi,
 31.1926 -		  enum razor_property_type type, const char *match)
 31.1927 -{
 31.1928 -	uint32_t name;
 31.1929 -
 31.1930 -	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
 31.1931 -		pi->p++;
 31.1932 -
 31.1933 -	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
 31.1934 -		return NULL;
 31.1935 -
 31.1936 -	name = pi->p->name;
 31.1937 -	while (pi->p < pi->end &&
 31.1938 -	       pi->p->name == name &&
 31.1939 -	       pi->p->type != type)
 31.1940 -		pi->p++;
 31.1941 -
 31.1942 -	if (pi->p == pi->end || pi->p->name != name)
 31.1943 -		return NULL;
 31.1944 -
 31.1945 -	return pi->p;
 31.1946 -}
 31.1947 -
 31.1948 -/* Remove packages from set that provide any of the matching (same
 31.1949 - * name and type) providers from ppi onwards that match the
 31.1950 - * requirement that rpi points to. */
 31.1951 -static void
 31.1952 -remove_matching_providers(struct razor_transaction *trans,
 31.1953 -			  struct prop_iter *ppi,
 31.1954 -			  enum razor_version_relation relation,
 31.1955 -			  const char *version)
 31.1956 -{
 31.1957 -	struct razor_property *p;
 31.1958 -	struct razor_package *pkg, *pkgs;
 31.1959 -	struct razor_package_iterator pkg_iter;
 31.1960 -	struct razor_set *set;
 31.1961 -	const char *n, *v, *a;
 31.1962 -
 31.1963 -	if (ppi->present == trans->system.properties)
 31.1964 -		set = trans->system.set;
 31.1965 -	else
 31.1966 -		set = trans->upstream.set;
 31.1967 -   
 31.1968 -	pkgs = (struct razor_package *) set->packages.data;
 31.1969 -	for (p = ppi->p; 
 31.1970 -	     p < ppi->end && 
 31.1971 -	     p->name == ppi->p->name &&
 31.1972 -	     p->type == ppi->p->type;
 31.1973 -	     p++) {
 31.1974 -		if (!ppi->present[p - ppi->start])
 31.1975 -			continue;
 31.1976 -		if (!provider_satisfies_requirement(p, ppi->pool,
 31.1977 -						    relation, version))
 31.1978 -			continue;
 31.1979 -		    
 31.1980 -		razor_package_iterator_init_for_property(&pkg_iter, set, p);
 31.1981 -		while (razor_package_iterator_next(&pkg_iter,
 31.1982 -						   &pkg, &n, &v, &a)) {
 31.1983 -			fprintf(stderr, "removing %s-%s\n", n, v);
 31.1984 -			razor_transaction_remove_package(trans, pkg);
 31.1985 -		}
 31.1986 -	}
 31.1987 -}
 31.1988 -
 31.1989 -static void
 31.1990 -flag_matching_providers(struct razor_transaction *trans,
 31.1991 -			struct prop_iter *ppi,
 31.1992 -			struct razor_property *r,
 31.1993 -			struct prop_iter *rpi,
 31.1994 -			unsigned int flag)
 31.1995 -{
 31.1996 -	struct razor_property *p;
 31.1997 -	struct razor_package *pkg, *pkgs;
 31.1998 -	struct razor_package_iterator pkg_iter;
 31.1999 -	struct razor_set *set;
 31.2000 -	const char *name, *version, *arch;
 31.2001 -	uint32_t *flags;
 31.2002 -
 31.2003 -	if (ppi->present == trans->system.properties) {
 31.2004 -		set = trans->system.set;
 31.2005 -		flags = trans->system.packages;
 31.2006 -	} else {
 31.2007 -		set = trans->upstream.set;
 31.2008 -		flags = trans->upstream.packages;
 31.2009 -	}
 31.2010 -   
 31.2011 -	pkgs = (struct razor_package *) set->packages.data;
 31.2012 -	for (p = ppi->p; 
 31.2013 -	     p < ppi->end && 
 31.2014 -		     p->name == ppi->p->name &&
 31.2015 -		     p->type == ppi->p->type;
 31.2016 -	     p++) {
 31.2017 -		if (!ppi->present[p - ppi->start])
 31.2018 -			continue;
 31.2019 -		if (!provider_satisfies_requirement(p, ppi->pool,
 31.2020 -						    r->relation,
 31.2021 -						    &rpi->pool[r->version]))
 31.2022 -			continue;
 31.2023 -		    
 31.2024 -		razor_package_iterator_init_for_property(&pkg_iter, set, p);
 31.2025 -		while (razor_package_iterator_next(&pkg_iter, &pkg,
 31.2026 -						   &name, &version, &arch)) {
 31.2027 -
 31.2028 -			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
 31.2029 -				name, version,
 31.2030 -				ppi->pool + p->name,
 31.2031 -				rpi->pool + r->name,
 31.2032 -				rpi->pool + r->version);
 31.2033 -			flags[pkg - pkgs] |= flag;
 31.2034 -		}
 31.2035 -	}
 31.2036 -}
 31.2037 -
 31.2038 -static struct razor_package *
 31.2039 -pick_matching_provider(struct razor_set *set,
 31.2040 -		       struct prop_iter *ppi,
 31.2041 -		       enum razor_version_relation relation,
 31.2042 -		       const char *version)
 31.2043 -{
 31.2044 -	struct razor_property *p;
 31.2045 -	struct razor_package *pkgs;
 31.2046 -	struct list *i;
 31.2047 -
 31.2048 -	/* This is where we decide which pkgs to pull in to satisfy a
 31.2049 -	 * requirement.  There may be several different providers
 31.2050 -	 * (different versions) and each version of a provider may
 31.2051 -	 * come from a number of packages.  We pick the first package
 31.2052 -	 * from the first provider that matches. */
 31.2053 -
 31.2054 -	pkgs = set->packages.data;
 31.2055 -	for (p = ppi->p;
 31.2056 -	     p < ppi->end &&
 31.2057 -		     p->name == ppi->p->name &&
 31.2058 -		     p->type == ppi->p->type &&
 31.2059 -		     ppi->present[p - ppi->start] == 0;
 31.2060 -	     p++) {
 31.2061 -		if (!provider_satisfies_requirement(p, ppi->pool,
 31.2062 -						    relation, version))
 31.2063 -			continue;
 31.2064 -
 31.2065 -		i = list_first(&p->packages, &set->package_pool);
 31.2066 -
 31.2067 -		return &pkgs[i->data];
 31.2068 -	}
 31.2069 -
 31.2070 -	return NULL;
 31.2071 -}
 31.2072 -
 31.2073 -static void
 31.2074 -remove_obsoleted_packages(struct razor_transaction *trans)
 31.2075 -{
 31.2076 -	struct razor_property *up;
 31.2077 -	struct razor_package *spkgs;
 31.2078 -	struct prop_iter spi, upi;
 31.2079 -
 31.2080 -	spkgs = trans->system.set->packages.data;
 31.2081 -	prop_iter_init(&spi, &trans->system);
 31.2082 -	prop_iter_init(&upi, &trans->upstream);
 31.2083 -	
 31.2084 -	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
 31.2085 -		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
 31.2086 -				       &upi.pool[up->name]))
 31.2087 -			continue;
 31.2088 -		remove_matching_providers(trans, &spi, up->relation,
 31.2089 -					  &upi.pool[up->version]);
 31.2090 -	}
 31.2091 -}
 31.2092 -
 31.2093 -static int
 31.2094 -any_provider_satisfies_requirement(struct prop_iter *ppi,
 31.2095 -				   enum razor_version_relation relation,
 31.2096 -				   const char *version)
 31.2097 -{
 31.2098 -	struct razor_property *p;
 31.2099 -
 31.2100 -	for (p = ppi->p;
 31.2101 -	     p < ppi->end &&
 31.2102 -		     p->name == ppi->p->name &&
 31.2103 -		     p->type == ppi->p->type;
 31.2104 -	     p++) {
 31.2105 -		if (ppi->present[p - ppi->start] > 0 &&
 31.2106 -		    provider_satisfies_requirement(p, ppi->pool,
 31.2107 -						   relation, version))
 31.2108 -			return 1;
 31.2109 -	}
 31.2110 -
 31.2111 -	return 0;
 31.2112 -}
 31.2113 -
 31.2114 -static void
 31.2115 -clear_requires_flags(struct transaction_set *ts)
 31.2116 -{
 31.2117 -	struct razor_property *p;
 31.2118 -	const char *pool;
 31.2119 -	int i, count;
 31.2120 -
 31.2121 -	count = ts->set->properties.size / sizeof *p;
 31.2122 -	p = ts->set->properties.data;
 31.2123 -	pool = ts->set->string_pool.data;
 31.2124 -	for (i = 0; i < count; i++) {
 31.2125 -		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
 31.2126 -		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
 31.2127 -			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
 31.2128 -	}
 31.2129 -}
 31.2130 -
 31.2131 -static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
 31.2132 -
 31.2133 -static void
 31.2134 -mark_satisfied_requires(struct razor_transaction *trans,
 31.2135 -			struct transaction_set *rts,
 31.2136 -			struct transaction_set *pts)
 31.2137 -{
 31.2138 -	struct prop_iter rpi, ppi;
 31.2139 -	struct razor_property *rp;
 31.2140 -
 31.2141 -	prop_iter_init(&rpi, rts);
 31.2142 -	prop_iter_init(&ppi, pts);
 31.2143 -
 31.2144 -	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 31.2145 -		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
 31.2146 -				       &rpi.pool[rp->name]))
 31.2147 -			continue;
 31.2148 -
 31.2149 -		if (any_provider_satisfies_requirement(&ppi, rp->relation,
 31.2150 -						       &rpi.pool[rp->version]))
 31.2151 -			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
 31.2152 -	}
 31.2153 -}
 31.2154 -
 31.2155 -static void
 31.2156 -mark_all_satisfied_requires(struct razor_transaction *trans)
 31.2157 -{
 31.2158 -	clear_requires_flags(&trans->system);
 31.2159 -	clear_requires_flags(&trans->upstream);
 31.2160 -	mark_satisfied_requires(trans, &trans->system, &trans->system);
 31.2161 -	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
 31.2162 -	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
 31.2163 -	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
 31.2164 -}
 31.2165 -
 31.2166 -static void
 31.2167 -update_unsatisfied_packages(struct razor_transaction *trans)
 31.2168 -{
 31.2169 -	struct razor_package *spkgs, *pkg;
 31.2170 -	struct razor_property *sp;
 31.2171 -	struct prop_iter spi;
 31.2172 -	struct razor_package_iterator pkg_iter;
 31.2173 -	const char *name, *version, *arch;
 31.2174 -
 31.2175 -	spkgs = trans->system.set->packages.data;
 31.2176 -	prop_iter_init(&spi, &trans->system);
 31.2177 -	
 31.2178 -	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
 31.2179 -		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
 31.2180 -			continue;
 31.2181 -		
 31.2182 -		razor_package_iterator_init_for_property(&pkg_iter,
 31.2183 -							 trans->system.set,
 31.2184 -							 sp);
 31.2185 -		while (razor_package_iterator_next(&pkg_iter, &pkg,
 31.2186 -						   &name, &version, &arch)) {
 31.2187 -			fprintf(stderr, "updating %s because %s %s %s "
 31.2188 -				"isn't satisfied\n",
 31.2189 -				name, spi.pool + sp->name,
 31.2190 -				relation_string[sp->relation],
 31.2191 -				spi.pool + sp->version);
 31.2192 -			trans->system.packages[pkg - spkgs] |=
 31.2193 -				TRANS_PACKAGE_UPDATE;
 31.2194 -		}
 31.2195 -	}
 31.2196 -}
 31.2197 -
 31.2198 -void
 31.2199 -razor_transaction_update_all(struct razor_transaction *trans)
 31.2200 -{
 31.2201 -	struct razor_package *p;
 31.2202 -	int i, count;
 31.2203 -
 31.2204 -	count = trans->system.set->packages.size / sizeof *p;
 31.2205 -	for (i = 0; i < count; i++)
 31.2206 -		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
 31.2207 -}
 31.2208 -
 31.2209 -static void
 31.2210 -update_conflicted_packages(struct razor_transaction *trans)
 31.2211 -{
 31.2212 -	struct razor_package *pkg, *spkgs;
 31.2213 -	struct razor_property *up, *sp;
 31.2214 -	struct prop_iter spi, upi;
 31.2215 -	struct razor_package_iterator pkg_iter;
 31.2216 -	const char *name, *version, *arch;
 31.2217 -
 31.2218 -	spkgs = trans->system.set->packages.data;
 31.2219 -	prop_iter_init(&spi, &trans->system);
 31.2220 -	prop_iter_init(&upi, &trans->upstream);
 31.2221 -
 31.2222 -	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
 31.2223 -		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
 31.2224 -				       &spi.pool[sp->name]))
 31.2225 -			continue;
 31.2226 -
 31.2227 -		if (!any_provider_satisfies_requirement(&upi, sp->relation,
 31.2228 -							&spi.pool[sp->version]))
 31.2229 -			continue;
 31.2230 -
 31.2231 -		razor_package_iterator_init_for_property(&pkg_iter,
 31.2232 -							 trans->system.set,
 31.2233 -							 sp);
 31.2234 -		while (razor_package_iterator_next(&pkg_iter, &pkg,
 31.2235 -						   &name, &version, &arch)) {
 31.2236 -			fprintf(stderr, "updating %s %s because it conflicts with %s",
 31.2237 -				name, version, spi.pool + sp->name);
 31.2238 -			trans->system.packages[pkg - spkgs] |=
 31.2239 -				TRANS_PACKAGE_UPDATE;
 31.2240 -		}
 31.2241 -	}
 31.2242 -
 31.2243 -	prop_iter_init(&spi, &trans->system);
 31.2244 -	prop_iter_init(&upi, &trans->upstream);
 31.2245 -
 31.2246 -	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
 31.2247 -		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
 31.2248 -				       &upi.pool[upi.p->name]);
 31.2249 -
 31.2250 -		if (sp)
 31.2251 -			flag_matching_providers(trans, &spi, up, &upi,
 31.2252 -						TRANS_PACKAGE_UPDATE);
 31.2253 -	}
 31.2254 -}
 31.2255 -
 31.2256 -static void
 31.2257 -pull_in_requirements(struct razor_transaction *trans,
 31.2258 -		     struct prop_iter *rpi, struct prop_iter *ppi)
 31.2259 -{
 31.2260 -	struct razor_property *rp, *pp;
 31.2261 -	struct razor_package *pkg, *upkgs;
 31.2262 -
 31.2263 -	upkgs = trans->upstream.set->packages.data;
 31.2264 -	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 31.2265 -		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
 31.2266 -			continue;
 31.2267 -
 31.2268 -		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
 31.2269 -				       &rpi->pool[rp->name]);
 31.2270 -		if (pp == NULL)
 31.2271 -			continue;
 31.2272 -		pkg = pick_matching_provider(trans->upstream.set,
 31.2273 -					     ppi, rp->relation,
 31.2274 -					     &rpi->pool[rp->version]);
 31.2275 -		if (pkg == NULL)
 31.2276 -			continue;
 31.2277 -
 31.2278 -		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
 31.2279 -
 31.2280 -		fprintf(stderr, "pulling in %s which provides %s %s %s "
 31.2281 -			"to satisfy %s %s %s\n",
 31.2282 -			ppi->pool + pkg->name,
 31.2283 -			ppi->pool + pp->name, 
 31.2284 -			relation_string[pp->relation],
 31.2285 -			ppi->pool + pp->version, 
 31.2286 -			&rpi->pool[rp->name],
 31.2287 -			relation_string[rp->relation],
 31.2288 -			&rpi->pool[rp->version]);
 31.2289 -
 31.2290 -		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
 31.2291 -	}
 31.2292 -}
 31.2293 -
 31.2294 -static void
 31.2295 -pull_in_all_requirements(struct razor_transaction *trans)
 31.2296 -{
 31.2297 -	struct prop_iter rpi, ppi;
 31.2298 -
 31.2299 -	prop_iter_init(&rpi, &trans->system);
 31.2300 -	prop_iter_init(&ppi, &trans->upstream);
 31.2301 -	pull_in_requirements(trans, &rpi, &ppi);
 31.2302 -	
 31.2303 -	prop_iter_init(&rpi, &trans->upstream);
 31.2304 -	prop_iter_init(&ppi, &trans->upstream);
 31.2305 -	pull_in_requirements(trans, &rpi, &ppi);
 31.2306 -}
 31.2307 -
 31.2308 -static void
 31.2309 -flush_scheduled_system_updates(struct razor_transaction *trans)
 31.2310 -{
 31.2311 - 	struct razor_package_iterator *pi;
 31.2312 - 	struct razor_package *p, *pkg, *spkgs;
 31.2313 -	struct prop_iter ppi;
 31.2314 -	const char *name, *version, *arch;
 31.2315 -
 31.2316 -	spkgs = trans->system.set->packages.data;
 31.2317 -	pi = razor_package_iterator_create(trans->system.set);
 31.2318 -	prop_iter_init(&ppi, &trans->upstream);
 31.2319 -
 31.2320 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 31.2321 -		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
 31.2322 -			continue;
 31.2323 -
 31.2324 -		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
 31.2325 -			continue;
 31.2326 -
 31.2327 -		pkg = pick_matching_provider(trans->upstream.set, &ppi,
 31.2328 -					     RAZOR_VERSION_GREATER, version);
 31.2329 -		if (pkg == NULL)
 31.2330 -			continue;
 31.2331 -		
 31.2332 -		fprintf(stderr, "updating %s-%s to %s-%s\n",
 31.2333 -			name, version,
 31.2334 -			&ppi.pool[pkg->name], &ppi.pool[pkg->version]);
 31.2335 -
 31.2336 -		razor_transaction_remove_package(trans, p);
 31.2337 -		razor_transaction_install_package(trans, pkg);
 31.2338 -	}
 31.2339 -
 31.2340 -	razor_package_iterator_destroy(pi);
 31.2341 -}
 31.2342 -
 31.2343 -static void
 31.2344 -flush_scheduled_upstream_updates(struct razor_transaction *trans)
 31.2345 -{
 31.2346 - 	struct razor_package_iterator *pi;
 31.2347 - 	struct razor_package *p, *upkgs;
 31.2348 -	struct prop_iter spi;
 31.2349 -	const char *name, *version, *arch;
 31.2350 -
 31.2351 -	upkgs = trans->upstream.set->packages.data;
 31.2352 -	pi = razor_package_iterator_create(trans->upstream.set);
 31.2353 -	prop_iter_init(&spi, &trans->system);
 31.2354 -
 31.2355 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 31.2356 -		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
 31.2357 -			continue;
 31.2358 -
 31.2359 -		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
 31.2360 -			continue;
 31.2361 -		remove_matching_providers(trans, &spi,
 31.2362 -					  RAZOR_VERSION_LESS, version);
 31.2363 -		razor_transaction_install_package(trans, p);
 31.2364 -		fprintf(stderr, "installing %s-%s\n", name, version);
 31.2365 -	}
 31.2366 -}
 31.2367 -
 31.2368 -int
 31.2369 -razor_transaction_resolve(struct razor_transaction *trans)
 31.2370 -{
 31.2371 -	int last = 0;
 31.2372 -
 31.2373 -	flush_scheduled_system_updates(trans);
 31.2374 -
 31.2375 -	while (last < trans->changes) {
 31.2376 -		last = trans->changes;
 31.2377 -		remove_obsoleted_packages(trans);
 31.2378 -		mark_all_satisfied_requires(trans);
 31.2379 -		update_unsatisfied_packages(trans);
 31.2380 -		update_conflicted_packages(trans);
 31.2381 -		pull_in_all_requirements(trans);
 31.2382 -		flush_scheduled_system_updates(trans);
 31.2383 -		flush_scheduled_upstream_updates(trans);
 31.2384 -	}
 31.2385 -
 31.2386 -	return trans->changes;
 31.2387 -}
 31.2388 -
 31.2389 -static void
 31.2390 -describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
 31.2391 -{
 31.2392 -	struct razor_package_iterator pi;
 31.2393 -	struct razor_package *pkg;
 31.2394 -	const char *name, *version, *arch, *pool;
 31.2395 -
 31.2396 -	pool = set->string_pool.data;
 31.2397 -	if (pool[rp->version] == '\0') {
 31.2398 -		razor_package_iterator_init_for_property(&pi, set, rp);
 31.2399 -		while (razor_package_iterator_next(&pi, &pkg,
 31.2400 -						   &name, &version, &arch))
 31.2401 -			fprintf(stderr, "%s is needed by %s-%s.%s\n",
 31.2402 -				&pool[rp->name],
 31.2403 -				name, version, arch);
 31.2404 -	} else {
 31.2405 -		razor_package_iterator_init_for_property(&pi, set, rp);
 31.2406 -		while (razor_package_iterator_next(&pi, &pkg,
 31.2407 -						   &name, &version, &arch))
 31.2408 -			fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
 31.2409 -				&pool[rp->name],
 31.2410 -				relation_string[rp->relation],
 31.2411 -				&pool[rp->version],
 31.2412 -				name, version, arch);
 31.2413 -	}
 31.2414 -}
 31.2415 -
 31.2416 -int
 31.2417 -razor_transaction_describe(struct razor_transaction *trans)
 31.2418 -{
 31.2419 -	struct prop_iter rpi;
 31.2420 -	struct razor_property *rp;
 31.2421 -	int unsatisfied;
 31.2422 -
 31.2423 -	flush_scheduled_system_updates(trans);
 31.2424 -	flush_scheduled_upstream_updates(trans);
 31.2425 -	mark_all_satisfied_requires(trans);
 31.2426 -
 31.2427 -	unsatisfied = 0;
 31.2428 -	prop_iter_init(&rpi, &trans->system);
 31.2429 -	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 31.2430 -		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
 31.2431 -			describe_unsatisfied(trans->system.set, rp);
 31.2432 -		        unsatisfied++;
 31.2433 -		}
 31.2434 -	}
 31.2435 -
 31.2436 -	prop_iter_init(&rpi, &trans->upstream);
 31.2437 -	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
 31.2438 -		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
 31.2439 -			describe_unsatisfied(trans->upstream.set, rp);
 31.2440 -			unsatisfied++;
 31.2441 -		}
 31.2442 -	}
 31.2443 -
 31.2444 -	return unsatisfied;
 31.2445 -}
 31.2446 -
 31.2447 -int
 31.2448 -razor_transaction_unsatisfied_property(struct razor_transaction *trans,
 31.2449 -				       const char *name,
 31.2450 -				       enum razor_version_relation rel,
 31.2451 -				       const char *version,
 31.2452 -				       enum razor_property_type type)
 31.2453 -{
 31.2454 -	struct prop_iter pi;
 31.2455 -	struct razor_property *p;
 31.2456 -
 31.2457 -	prop_iter_init(&pi, &trans->system);
 31.2458 -	while (prop_iter_next(&pi, type, &p)) {
 31.2459 -		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
 31.2460 -		    p->relation == rel &&
 31.2461 -		    strcmp(&pi.pool[p->name], name) == 0 &&
 31.2462 -		    strcmp(&pi.pool[p->version], version) == 0)
 31.2463 -		    
 31.2464 -			return 1;
 31.2465 -	}
 31.2466 -
 31.2467 -	prop_iter_init(&pi, &trans->upstream);
 31.2468 -	while (prop_iter_next(&pi, type, &p)) {
 31.2469 -		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
 31.2470 -		    p->relation == rel &&
 31.2471 -		    strcmp(&pi.pool[p->name], name) == 0 &&
 31.2472 -		    strcmp(&pi.pool[p->version], version) == 0)
 31.2473 -		    
 31.2474 -			return 1;
 31.2475 -	}
 31.2476 -
 31.2477 -	return 0;
 31.2478 -}
 31.2479 -
 31.2480 -struct razor_set *
 31.2481 -razor_transaction_finish(struct razor_transaction *trans)
 31.2482 -{
 31.2483 -	struct razor_merger *merger;
 31.2484 -	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
 31.2485 -	char *upool, *spool;
 31.2486 -	int cmp;
 31.2487 -
 31.2488 -	s = trans->system.set->packages.data;
 31.2489 -	spkgs = trans->system.set->packages.data;
 31.2490 -	send = trans->system.set->packages.data +
 31.2491 -		trans->system.set->packages.size;
 31.2492 -	spool = trans->system.set->string_pool.data;
 31.2493 -
 31.2494 -	u = trans->upstream.set->packages.data;
 31.2495 -	upkgs = trans->upstream.set->packages.data;
 31.2496 -	uend = trans->upstream.set->packages.data +
 31.2497 -		trans->upstream.set->packages.size;
 31.2498 -	upool = trans->upstream.set->string_pool.data;
 31.2499 -
 31.2500 -	merger = razor_merger_create(trans->system.set, trans->upstream.set);
 31.2501 -	while (s < send || u < uend) {
 31.2502 -		if (s < send && u < uend)
 31.2503 -			cmp = strcmp(&spool[s->name], &upool[u->name]);
 31.2504 -		else if (s < send)
 31.2505 -			cmp = -1;
 31.2506 -		else
 31.2507 -			cmp = 1;
 31.2508 -
 31.2509 -		if (cmp < 0) {
 31.2510 -			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
 31.2511 -				razor_merger_add_package(merger, s);
 31.2512 -			s++;
 31.2513 -		} else if (cmp == 0) {
 31.2514 -			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
 31.2515 -				razor_merger_add_package(merger, s);
 31.2516 -			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
 31.2517 -				razor_merger_add_package(merger, u);
 31.2518 -
 31.2519 -			s++;
 31.2520 -			u++;
 31.2521 -		} else {
 31.2522 -			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
 31.2523 -				razor_merger_add_package(merger, u);
 31.2524 -			u++;
 31.2525 -		}
 31.2526 -	}
 31.2527 -
 31.2528 -	razor_transaction_destroy(trans);
 31.2529 -
 31.2530 -	return razor_merger_finish(merger);
 31.2531 -}
 31.2532 -
 31.2533 -void
 31.2534 -razor_transaction_destroy(struct razor_transaction *trans)
 31.2535 -{
 31.2536 -	transaction_set_release(&trans->system);
 31.2537 -	transaction_set_release(&trans->upstream);
 31.2538 -	free(trans);
 31.2539 -}
 31.2540 -
 31.2541 -struct razor_package_query {
 31.2542 -	struct razor_set *set;
 31.2543 -	char *vector;
 31.2544 -	int count;
 31.2545 -};
 31.2546 -
 31.2547 -struct razor_package_query *
 31.2548 -razor_package_query_create(struct razor_set *set)
 31.2549 -{
 31.2550 -	struct razor_package_query *pq;
 31.2551 -	int count;
 31.2552 -
 31.2553 -	pq = zalloc(sizeof *pq);
 31.2554 -	pq->set = set;
 31.2555 -	count = set->packages.size / sizeof(struct razor_package);
 31.2556 -	pq->vector = zalloc(count * sizeof(char));
 31.2557 -
 31.2558 -	return pq;
 31.2559 -}
 31.2560 -
 31.2561 -void
 31.2562 -razor_package_query_add_package(struct razor_package_query *pq,
 31.2563 -				struct razor_package *p)
 31.2564 -{
 31.2565 -	struct razor_package *packages;
 31.2566 -
 31.2567 -	packages = pq->set->packages.data;
 31.2568 -	pq->count += pq->vector[p - packages] ^ 1;
 31.2569 -	pq->vector[p - packages] = 1;
 31.2570 -}
 31.2571 -
 31.2572 -void
 31.2573 -razor_package_query_add_iterator(struct razor_package_query *pq,
 31.2574 -				 struct razor_package_iterator *pi)
 31.2575 -{
 31.2576 -	struct razor_package *packages, *p;
 31.2577 -	const char *name, *version, *arch;
 31.2578 -
 31.2579 -	packages = pq->set->packages.data;
 31.2580 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 31.2581 -		pq->count += pq->vector[p - packages] ^ 1;
 31.2582 -		pq->vector[p - packages] = 1;
 31.2583 -	}
 31.2584 -}
 31.2585 -
 31.2586 -struct razor_package_iterator *
 31.2587 -razor_package_query_finish(struct razor_package_query *pq)
 31.2588 -{
 31.2589 -	struct razor_package_iterator *pi;
 31.2590 -	struct razor_set *set;
 31.2591 -	struct list *index;
 31.2592 -	int i, j, count;
 31.2593 -
 31.2594 -	set = pq->set;
 31.2595 -	count = set->packages.size / sizeof(struct razor_package);
 31.2596 -	index = zalloc(pq->count * sizeof *index);
 31.2597 -
 31.2598 -	for (i = 0, j = 0; i < count; i++) {
 31.2599 -		if (!pq->vector[i])
 31.2600 -			continue;
 31.2601 -
 31.2602 -		index[j].data = i;
 31.2603 -		if (j == pq->count - 1)
 31.2604 -			index[j].flags = 0x80;
 31.2605 -		j++;
 31.2606 -	}
 31.2607 -
 31.2608 -	free(pq);
 31.2609 -
 31.2610 -	pi = razor_package_iterator_create_with_index(set, index);
 31.2611 -	pi->free_index = 1;
 31.2612 -
 31.2613 -	return pi;
 31.2614 -}
    32.1 --- a/razor.h	Sun Jun 15 23:15:59 2008 -0400
    32.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.3 @@ -1,189 +0,0 @@
    32.4 -/*
    32.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    32.6 - * Copyright (C) 2008  Red Hat, Inc
    32.7 - *
    32.8 - * This program is free software; you can redistribute it and/or modify
    32.9 - * it under the terms of the GNU General Public License as published by
   32.10 - * the Free Software Foundation; either version 2 of the License, or
   32.11 - * (at your option) any later version.
   32.12 - *
   32.13 - * This program is distributed in the hope that it will be useful,
   32.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   32.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   32.16 - * GNU General Public License for more details.
   32.17 - *
   32.18 - * You should have received a copy of the GNU General Public License along
   32.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   32.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   32.21 - */
   32.22 -
   32.23 -#ifndef _RAZOR_H_
   32.24 -#define _RAZOR_H_
   32.25 -
   32.26 -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
   32.27 -
   32.28 -struct razor_set;
   32.29 -struct razor_package;
   32.30 -struct razor_property;
   32.31 -
   32.32 -enum razor_property_type {
   32.33 -	RAZOR_PROPERTY_REQUIRES,
   32.34 -	RAZOR_PROPERTY_PROVIDES,
   32.35 -	RAZOR_PROPERTY_CONFLICTS,
   32.36 -	RAZOR_PROPERTY_OBSOLETES
   32.37 -};
   32.38 -
   32.39 -enum razor_version_relation {
   32.40 -	RAZOR_VERSION_LESS,
   32.41 -	RAZOR_VERSION_LESS_OR_EQUAL,
   32.42 -	RAZOR_VERSION_EQUAL,
   32.43 -	RAZOR_VERSION_GREATER_OR_EQUAL,
   32.44 -	RAZOR_VERSION_GREATER
   32.45 -};
   32.46 -extern const char * const razor_version_relations[];
   32.47 -
   32.48 -struct razor_set *razor_set_create(void);
   32.49 -struct razor_set *razor_set_open(const char *filename);
   32.50 -void razor_set_destroy(struct razor_set *set);
   32.51 -int razor_set_write_to_fd(struct razor_set *set, int fd);
   32.52 -int razor_set_write(struct razor_set *set, const char *filename);
   32.53 -
   32.54 -struct razor_package *
   32.55 -razor_set_get_package(struct razor_set *set, const char *package);
   32.56 -
   32.57 -struct razor_package_iterator;
   32.58 -struct razor_package_iterator *
   32.59 -razor_package_iterator_create(struct razor_set *set);
   32.60 -struct razor_package_iterator *
   32.61 -razor_package_iterator_create_for_property(struct razor_set *set,
   32.62 -					   struct razor_property *property);
   32.63 -struct razor_package_iterator *
   32.64 -razor_package_iterator_create_for_file(struct razor_set *set,
   32.65 -				       const char *filename);
   32.66 -
   32.67 -int razor_package_iterator_next(struct razor_package_iterator *pi,
   32.68 -				struct razor_package **package,
   32.69 -				const char **name,
   32.70 -				const char **version,
   32.71 -				const char **arch);
   32.72 -void razor_package_iterator_destroy(struct razor_package_iterator *pi);
   32.73 -
   32.74 -struct razor_package_query *
   32.75 -razor_package_query_create(struct razor_set *set);
   32.76 -void
   32.77 -razor_package_query_add_package(struct razor_package_query *pq,
   32.78 -				struct razor_package *p);
   32.79 -void
   32.80 -razor_package_query_add_iterator(struct razor_package_query *pq,
   32.81 -				 struct razor_package_iterator *pi);
   32.82 -struct razor_package_iterator *
   32.83 -razor_package_query_finish(struct razor_package_query *pq);
   32.84 -
   32.85 -struct razor_property_iterator;
   32.86 -struct razor_property_iterator *
   32.87 -razor_property_iterator_create(struct razor_set *set,
   32.88 -			       struct razor_package *package);
   32.89 -int razor_property_iterator_next(struct razor_property_iterator *pi,
   32.90 -				 struct razor_property **property,
   32.91 -				 const char **name,
   32.92 -				 enum razor_version_relation *relation,
   32.93 -				 const char **version,
   32.94 -				 enum razor_property_type *type);
   32.95 -void
   32.96 -razor_property_iterator_destroy(struct razor_property_iterator *pi);
   32.97 -
   32.98 -void razor_set_list_files(struct razor_set *set, const char *prefix);
   32.99 -void razor_set_list_package_files(struct razor_set *set, const char *name);
  32.100 -
  32.101 -void razor_set_list_unsatisfied(struct razor_set *set);
  32.102 -
  32.103 -typedef void (*razor_package_callback_t)(const char *name,
  32.104 -					 const char *old_version,
  32.105 -					 const char *new_version,
  32.106 -					 const char *arch,
  32.107 -					 void *data);
  32.108 -void
  32.109 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
  32.110 -	       razor_package_callback_t callback, void *data);
  32.111 -
  32.112 -/* Package transactions */
  32.113 -
  32.114 -struct razor_transaction *
  32.115 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream);
  32.116 -void razor_transaction_install_package(struct razor_transaction *transaction,
  32.117 -				       struct razor_package *package);
  32.118 -void razor_transaction_remove_package(struct razor_transaction *transaction,
  32.119 -				      struct razor_package *package);
  32.120 -void razor_transaction_update_package(struct razor_transaction *trans,
  32.121 -				      struct razor_package *package);
  32.122 -void razor_transaction_update_all(struct razor_transaction *transaction);
  32.123 -int razor_transaction_resolve(struct razor_transaction *trans);
  32.124 -int razor_transaction_describe(struct razor_transaction *trans);
  32.125 -struct razor_set *razor_transaction_finish(struct razor_transaction *trans);
  32.126 -void razor_transaction_destroy(struct razor_transaction *trans);
  32.127 -
  32.128 -/* Temporary helper for test suite. */
  32.129 -int razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  32.130 -					   const char *name,
  32.131 -					   enum razor_version_relation rel,
  32.132 -					   const char *version,
  32.133 -					   enum razor_property_type type);
  32.134 -
  32.135 -/* Importer interface; for building a razor set from external sources,
  32.136 - * like yum, rpmdb or razor package files. */
  32.137 -
  32.138 -struct razor_importer;
  32.139 -struct razor_rpm;
  32.140 -
  32.141 -struct razor_importer *razor_importer_new(void);
  32.142 -void razor_importer_destroy(struct razor_importer *importer);
  32.143 -void razor_importer_begin_package(struct razor_importer *importer,
  32.144 -				  const char *name,
  32.145 -				  const char *version,
  32.146 -				  const char *arch);
  32.147 -void razor_importer_add_property(struct razor_importer *importer,
  32.148 -				 const char *name,
  32.149 -				 enum razor_version_relation relation,
  32.150 -				 const char *version,
  32.151 -				 enum razor_property_type type);
  32.152 -void razor_importer_add_file(struct razor_importer *importer,
  32.153 -			     const char *name);
  32.154 -void razor_importer_finish_package(struct razor_importer *importer);
  32.155 -
  32.156 -int razor_importer_add_rpm(struct razor_importer *importer,
  32.157 -			   struct razor_rpm *rpm);
  32.158 -
  32.159 -struct razor_set *razor_importer_finish(struct razor_importer *importer);
  32.160 -
  32.161 -void razor_build_evr(char *evr_buf, int size, const char *epoch,
  32.162 -		     const char *version, const char *release);
  32.163 -
  32.164 -struct razor_set *razor_set_create_from_yum(void);
  32.165 -struct razor_set *razor_set_create_from_rpmdb(void);
  32.166 -
  32.167 -/* RPM functions */
  32.168 -
  32.169 -struct razor_rpm *razor_rpm_open(const char *filename);
  32.170 -int razor_rpm_install(struct razor_rpm *rpm, const char *root);
  32.171 -int razor_rpm_close(struct razor_rpm *rpm);
  32.172 -
  32.173 -
  32.174 -/* Razor root functions. The root data struct encapsulates filesystem
  32.175 - * conventions and the locking protocol. */
  32.176 -
  32.177 -struct razor_root;
  32.178 -#define RAZOR_ROOT_OPEN_WRITE 0x01
  32.179 -
  32.180 -int razor_root_create(const char *root);
  32.181 -struct razor_root *razor_root_open(const char *root, int flags);
  32.182 -struct razor_set *razor_root_open_read_only(const char *root);
  32.183 -struct razor_transaction *
  32.184 -razor_root_create_transaction(struct razor_root *image,
  32.185 -			      struct razor_set *upstream);
  32.186 -int razor_root_close(struct razor_root *image);
  32.187 -void razor_root_update(struct razor_root *image, struct razor_set *next);
  32.188 -int razor_root_commit(struct razor_root *image);
  32.189 -void razor_root_diff(struct razor_root *root,
  32.190 -		     razor_package_callback_t callback, void *data);
  32.191 -
  32.192 -#endif /* _RAZOR_H_ */
    33.1 --- a/rpm-razor.c	Sun Jun 15 23:15:59 2008 -0400
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,897 +0,0 @@
    33.4 -/*
    33.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    33.6 - * Copyright (C) 2008  Red Hat, Inc
    33.7 - *
    33.8 - * This program is free software; you can redistribute it and/or modify
    33.9 - * it under the terms of the GNU General Public License as published by
   33.10 - * the Free Software Foundation; either version 2 of the License, or
   33.11 - * (at your option) any later version.
   33.12 - *
   33.13 - * This program is distributed in the hope that it will be useful,
   33.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.16 - * GNU General Public License for more details.
   33.17 - *
   33.18 - * You should have received a copy of the GNU General Public License along
   33.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   33.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   33.21 - */
   33.22 -
   33.23 -#include <stdlib.h>
   33.24 -#include <string.h>
   33.25 -#include <stdio.h>
   33.26 -#include <dirent.h>
   33.27 -#include "razor.h"
   33.28 -
   33.29 -enum option_type {
   33.30 -	OPTION_LAST,
   33.31 -	OPTION_GROUP,
   33.32 -	OPTION_BOOL,
   33.33 -	OPTION_STRING
   33.34 -};
   33.35 -
   33.36 -struct option {
   33.37 -	enum option_type type;
   33.38 -	const char *name;
   33.39 -	char short_name;
   33.40 -	const char *arg_name;
   33.41 -	const char *description;
   33.42 -	void *data;
   33.43 -};
   33.44 -
   33.45 -/* A note about all these options: rpm allows options to mean
   33.46 - * different things depending on what other options are present on the
   33.47 - * command line.  For example, if -q or --query is present, -i no
   33.48 - * longer means install, but info.  The way we handle this is by
   33.49 - * setting all the options that may match (ie if -i is given we set
   33.50 - * install and info), and then look at the relevent one depending on
   33.51 - * what else in on the command line. */
   33.52 -
   33.53 -static int option_all, option_whatrequires, option_whatprovides;
   33.54 -static int option_package;
   33.55 -
   33.56 -static const struct option query_options[] = {
   33.57 -	{ OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
   33.58 -	{ OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
   33.59 -	{ OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
   33.60 -	{ OPTION_BOOL, "list", 0, NULL, "list files in package", NULL },
   33.61 -	{ OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
   33.62 -	{ OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
   33.63 -	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   33.64 -	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   33.65 -	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   33.66 -	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   33.67 -	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   33.68 -	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   33.69 -	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   33.70 -	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   33.71 -	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
   33.72 -	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   33.73 -	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   33.74 -	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   33.75 -	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
   33.76 -	{ }
   33.77 -};
   33.78 -
   33.79 -static int option_nodeps;
   33.80 -
   33.81 -static const struct option verify_options[] = {
   33.82 -	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
   33.83 -	{ OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
   33.84 -	{ OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", &option_nodeps },
   33.85 -	{ OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
   33.86 -	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   33.87 -	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   33.88 -	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   33.89 -	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   33.90 -	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   33.91 -	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   33.92 -	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   33.93 -	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   33.94 -	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
   33.95 -	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   33.96 -	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   33.97 -	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   33.98 -	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
   33.99 -	{ }
  33.100 -};
  33.101 -
  33.102 -static const struct option ftw_options[] = {
  33.103 -	{ OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
  33.104 -	{ OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
  33.105 -	{ OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
  33.106 -	{ OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
  33.107 -	{ OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
  33.108 -	{ OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
  33.109 -	{ OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
  33.110 -	{ OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
  33.111 -	{ }
  33.112 -};
  33.113 -
  33.114 -static const struct option signature_options[] = {
  33.115 -	{ OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
  33.116 -	{ OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
  33.117 -	{ OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
  33.118 -	{ OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
  33.119 -	{ OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
  33.120 -	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  33.121 -	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
  33.122 -	{ }
  33.123 -};
  33.124 -
  33.125 -static int option_initdb;
  33.126 -
  33.127 -static const struct option database_options[] = {
  33.128 -	{ OPTION_BOOL, "initdb", 0, NULL, "initialize database", &option_initdb },
  33.129 -	{ OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
  33.130 -	{ }
  33.131 -};
  33.132 -
  33.133 -static int option_erase, option_install, option_upgrade, option_justdb;
  33.134 -static int option_test;
  33.135 -
  33.136 -static const struct option install_options[] = {
  33.137 -	{ OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
  33.138 -	{ OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
  33.139 -	{ OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
  33.140 -	{ OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
  33.141 -	{ OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
  33.142 -	{ OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
  33.143 -	{ OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
  33.144 -	{ OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
  33.145 -	{ OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
  33.146 -	{ OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
  33.147 -	{ OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
  33.148 -	{ OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
  33.149 -	{ OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
  33.150 -	{ OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
  33.151 -	{ OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
  33.152 -	{ OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", &option_justdb, },
  33.153 -	{ OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", &option_nodeps, },
  33.154 -	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
  33.155 -	{ OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
  33.156 -	{ OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
  33.157 -	{ OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
  33.158 -	{ OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
  33.159 -	{ OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
  33.160 -	{ OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
  33.161 -	{ OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
  33.162 -	{ OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
  33.163 -	{ OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
  33.164 -	{ OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
  33.165 -	{ OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
  33.166 -	{ OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
  33.167 -	{ OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", &option_test },
  33.168 -	{ OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
  33.169 -	{ }
  33.170 -};
  33.171 -
  33.172 -static int option_version;
  33.173 -static const char *option_root = "install";
  33.174 -
  33.175 -static const struct option common_options[] = {
  33.176 -	{ OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
  33.177 -	{ OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
  33.178 -	{ OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  33.179 -	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  33.180 -	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
  33.181 -	{ OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  33.182 -	{ OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", &option_root },
  33.183 -	{ OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
  33.184 -	{ OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
  33.185 -	{ OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
  33.186 -	{ OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
  33.187 -	{ OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
  33.188 -	{ }
  33.189 -};
  33.190 -
  33.191 -static int option_conflicts, option_obsoletes, option_requires;
  33.192 -static int option_provides, option_info, option_changelog;
  33.193 -
  33.194 -static const struct option alias_options[] = {
  33.195 -	{ OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
  33.196 -	{ OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
  33.197 -	{ OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
  33.198 -	{ OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
  33.199 -	{ OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
  33.200 -	{ OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
  33.201 -	{ OPTION_BOOL, "requires", 0, NULL, "list capabilities required by package(s)", &option_requires, },
  33.202 -	{ OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
  33.203 -	{ OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
  33.204 -	{ OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
  33.205 -	{ OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
  33.206 -	{ OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
  33.207 -	{ OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
  33.208 -	{ OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
  33.209 -	{ OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
  33.210 -	{ OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
  33.211 -	{ OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
  33.212 -	{ OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
  33.213 -	{ OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
  33.214 -	{ OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
  33.215 -	{ OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
  33.216 -	{ OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
  33.217 -	{ OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
  33.218 -	{ OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
  33.219 -	{ OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
  33.220 -	{ OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
  33.221 -	{ }
  33.222 -};
  33.223 -
  33.224 -static int option_help, option_usage;
  33.225 -
  33.226 -static const struct option help_options[] = {
  33.227 -	{ OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
  33.228 -	{ OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
  33.229 -	{ }
  33.230 -};
  33.231 -
  33.232 -static int option_query, option_verify;
  33.233 -
  33.234 -static const struct option rpm_options[] = {
  33.235 -	{ OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
  33.236 -	{ OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
  33.237 -	{ OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
  33.238 -	{ OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
  33.239 -	{ OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
  33.240 -	{ OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
  33.241 -	{ OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
  33.242 -	{ OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
  33.243 -	{ OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
  33.244 -	{ OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
  33.245 -	{ OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
  33.246 -	{ }
  33.247 -};
  33.248 -
  33.249 -static const char system_repo_filename[] = "system.repo";
  33.250 -static const char *repo_filename = system_repo_filename;
  33.251 -
  33.252 -static void
  33.253 -command_initdb(int argc, const char *argv[])
  33.254 -{
  33.255 -	razor_root_create(option_root);
  33.256 -}
  33.257 -
  33.258 -static struct razor_property *
  33.259 -add_property_packages(struct razor_set *set, 
  33.260 -		      struct razor_package_query *query,
  33.261 -		      const char *ref_name,
  33.262 -		      const char *ref_version,
  33.263 -		      enum razor_property_type ref_type)
  33.264 -{
  33.265 -	struct razor_property *property;
  33.266 -	struct razor_property_iterator *pi;
  33.267 -	struct razor_package_iterator *pkgi;
  33.268 -	const char *name, *version;
  33.269 -	enum razor_property_type type;
  33.270 -	enum razor_version_relation relation;
  33.271 -
  33.272 -	pi = razor_property_iterator_create(set, NULL);
  33.273 -	while (razor_property_iterator_next(pi, &property, &name,
  33.274 -					    &relation, &version, &type)) {
  33.275 -		if (strcmp(ref_name, name) != 0)
  33.276 -			continue;
  33.277 -		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
  33.278 -		    strcmp(ref_version, version) != 0)
  33.279 -			continue;
  33.280 -		if (ref_type != type)
  33.281 -			continue;
  33.282 -
  33.283 -		pkgi = razor_package_iterator_create_for_property(set,
  33.284 -								  property);
  33.285 -		razor_package_query_add_iterator(query, pkgi);
  33.286 -		razor_package_iterator_destroy(pkgi);
  33.287 -	}
  33.288 -	razor_property_iterator_destroy(pi);
  33.289 -
  33.290 -	return property;
  33.291 -}
  33.292 -
  33.293 -static int
  33.294 -strcmpp(const void *p1, const void *p2)
  33.295 -{
  33.296 -	return strcmp(*(char * const *) p1, *(char * const *) p2);
  33.297 -}
  33.298 -
  33.299 -static void
  33.300 -add_command_line_packages(struct razor_set *set,
  33.301 -			  struct razor_package_query *query,
  33.302 -			  int argc, const char **argv)
  33.303 -{
  33.304 -	struct razor_package *package;
  33.305 -	struct razor_package_iterator *pi;
  33.306 -	const char *name, *version, *arch;
  33.307 -	int i, cmp, errors;
  33.308 -
  33.309 -	qsort(argv, argc, sizeof(*argv), strcmpp);
  33.310 -	i = 0;
  33.311 -	errors = 0;
  33.312 -
  33.313 -	pi = razor_package_iterator_create(set);
  33.314 -
  33.315 -	while (razor_package_iterator_next(pi, &package,
  33.316 -					   &name, &version, &arch)) {
  33.317 -		while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
  33.318 -			fprintf(stderr, "error: package %s is not installed\n",
  33.319 -				argv[i]);
  33.320 -			errors++;
  33.321 -			i++;
  33.322 -		}
  33.323 -
  33.324 -		if (cmp == 0) {
  33.325 -			razor_package_query_add_package(query, package);
  33.326 -			i++;
  33.327 -		}
  33.328 -	}
  33.329 -
  33.330 -	razor_package_iterator_destroy(pi);
  33.331 -
  33.332 -	if (errors)
  33.333 -		exit(1);
  33.334 -}
  33.335 -
  33.336 -static struct razor_package_iterator *
  33.337 -get_query_packages(struct razor_set *set, int argc, const char *argv[])
  33.338 -{
  33.339 -	struct razor_package_query *query;
  33.340 -	struct razor_package_iterator *pi;
  33.341 -	int i;
  33.342 -
  33.343 -	if (option_all + option_whatprovides + option_whatrequires > 1) {
  33.344 -		printf("only one type of query/verify "
  33.345 -		       "may be performed at a time\n");
  33.346 -		exit(1);
  33.347 -	}
  33.348 -
  33.349 -	query = razor_package_query_create(set);
  33.350 -
  33.351 -	if (option_all) {
  33.352 -		pi = razor_package_iterator_create(set);
  33.353 -		razor_package_query_add_iterator(query, pi);
  33.354 -		razor_package_iterator_destroy(pi);
  33.355 -	} else if (option_whatrequires) {
  33.356 -		for (i = 0; i < argc; i++)
  33.357 -			add_property_packages(set, query,
  33.358 -					      argv[i], NULL,
  33.359 -					      RAZOR_PROPERTY_REQUIRES);
  33.360 -	} else if (option_whatprovides) {
  33.361 -		for (i = 0; i < argc; i++)
  33.362 -			add_property_packages(set, query,
  33.363 -					      argv[i], NULL,
  33.364 -					      RAZOR_PROPERTY_PROVIDES);
  33.365 -	} else if (argc > 0) {
  33.366 -		add_command_line_packages(set, query, argc, argv);
  33.367 -	} else {
  33.368 -		printf("no arguments given for query/verify\n");
  33.369 -		exit(1);
  33.370 -	}
  33.371 -
  33.372 -	return razor_package_query_finish(query);
  33.373 -}
  33.374 -
  33.375 -static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  33.376 -
  33.377 -static void
  33.378 -print_package_properties(struct razor_set *set,
  33.379 -			 struct razor_package *package,
  33.380 -			 enum razor_property_type ref_type)
  33.381 -{
  33.382 -	struct razor_property *property;
  33.383 -	struct razor_property_iterator *pi;
  33.384 -	const char *name, *version;
  33.385 -	enum razor_property_type type;
  33.386 -	enum razor_version_relation relation;
  33.387 -
  33.388 -	pi = razor_property_iterator_create(set, package);
  33.389 -	while (razor_property_iterator_next(pi, &property,
  33.390 -					    &name, &relation, &version,
  33.391 -					    &type)) {
  33.392 -		if (type != ref_type)
  33.393 -			continue;
  33.394 -		if (version[0] == '\0')
  33.395 -			printf("%s\n", name);
  33.396 -		else
  33.397 -			printf("%s %s %s\n", name,
  33.398 -			       relation_string[relation], version);
  33.399 -	}
  33.400 -	razor_property_iterator_destroy(pi);
  33.401 -}
  33.402 -
  33.403 -static void
  33.404 -print_package_info(struct razor_set *set, struct razor_package *package)
  33.405 -{
  33.406 -	printf("FIXME: Package info not tracked.\n");
  33.407 -}
  33.408 -
  33.409 -static void
  33.410 -print_package_changelog(struct razor_set *set, struct razor_package *package)
  33.411 -{
  33.412 -	printf("FIXME: Package changelog not tracked.\n");
  33.413 -}
  33.414 -
  33.415 -static struct razor_set *
  33.416 -create_set_from_command_line(int argc, const char *argv[])
  33.417 -{
  33.418 -	struct razor_importer *importer;
  33.419 -	struct razor_rpm *rpm;
  33.420 -	int i;
  33.421 -
  33.422 -	importer = razor_importer_new();
  33.423 -
  33.424 -	for (i = 0; i < argc; i++) {
  33.425 -		rpm = razor_rpm_open(argv[i]);
  33.426 -		if (rpm == NULL)
  33.427 -			continue;
  33.428 -		if (razor_importer_add_rpm(importer, rpm))
  33.429 -			printf("couldn't import %s\n", argv[i]);
  33.430 -
  33.431 -		razor_rpm_close(rpm);
  33.432 -	}
  33.433 -
  33.434 -	return razor_importer_finish(importer);
  33.435 -}
  33.436 -
  33.437 -static void
  33.438 -command_query(int argc, const char *argv[])
  33.439 -{
  33.440 -	struct razor_set *set;
  33.441 -	struct razor_package_iterator *pi;
  33.442 -	struct razor_package *package;
  33.443 -	const char *name, *version, *arch;
  33.444 -
  33.445 -	if (option_package) {
  33.446 -		set = create_set_from_command_line(argc, argv);
  33.447 -		argc = 0;
  33.448 -		option_all = 1;
  33.449 -	} else {
  33.450 -		set = razor_root_open_read_only(option_root);
  33.451 -	}
  33.452 -
  33.453 -	pi = get_query_packages(set, argc, argv);
  33.454 -
  33.455 -	while (razor_package_iterator_next(pi, &package,
  33.456 -					   &name, &version, &arch)) {
  33.457 -		if (option_conflicts)
  33.458 -			print_package_properties(set, package,
  33.459 -						 RAZOR_PROPERTY_CONFLICTS);
  33.460 -		if (option_obsoletes)
  33.461 -			print_package_properties(set, package,
  33.462 -						 RAZOR_PROPERTY_OBSOLETES);
  33.463 -		if (option_requires)
  33.464 -			print_package_properties(set, package,
  33.465 -						 RAZOR_PROPERTY_REQUIRES);
  33.466 -		if (option_provides)
  33.467 -			print_package_properties(set, package,
  33.468 -						 RAZOR_PROPERTY_PROVIDES);
  33.469 -		if (option_info)
  33.470 -			print_package_info(set, package);
  33.471 -		if (option_changelog)
  33.472 -			print_package_changelog(set, package);
  33.473 -
  33.474 -		if (option_conflicts + option_obsoletes +
  33.475 -		    option_requires + option_provides +
  33.476 -		    option_info + option_changelog == 0)
  33.477 -			printf("%s-%s.%s\n", name, version, arch);
  33.478 -	}
  33.479 -
  33.480 -	razor_package_iterator_destroy(pi);
  33.481 -
  33.482 -	razor_set_destroy(set);
  33.483 -
  33.484 -	return;
  33.485 -}
  33.486 -
  33.487 -static void
  33.488 -command_verify(int argc, const char *argv[])
  33.489 -{
  33.490 -	struct razor_set *set;
  33.491 -	struct razor_package_iterator *pi;
  33.492 -	struct razor_package *package;
  33.493 -	const char *name, *version, *arch;
  33.494 -
  33.495 -	if (option_package) {
  33.496 -		set = create_set_from_command_line(argc, argv);
  33.497 -		argc = 0;
  33.498 -		option_all = 1;
  33.499 -	} else {
  33.500 -		set = razor_root_open_read_only(option_root);
  33.501 -	}
  33.502 -
  33.503 -	pi = get_query_packages(set, argc, argv);
  33.504 -
  33.505 -	while (razor_package_iterator_next(pi, &package,
  33.506 -					   &name, &version, &arch)) {
  33.507 -		printf("verify %s-%s.%s - not implemented\n",
  33.508 -		       name, version, arch);
  33.509 -	}
  33.510 -
  33.511 -	razor_package_iterator_destroy(pi);
  33.512 -}
  33.513 -
  33.514 -static void
  33.515 -remove_package(const char *name,
  33.516 -	       const char *old_version, const char *new_version,
  33.517 -	       const char *arch, void *data)
  33.518 -{
  33.519 -	if (old_version)
  33.520 -		printf("remove %s-%s.%s\n", name, old_version, arch);
  33.521 -}
  33.522 -
  33.523 -static void
  33.524 -command_erase(int argc, const char *argv[])
  33.525 -{
  33.526 -	struct razor_set *set, *upstream, *next;
  33.527 -	struct razor_transaction *trans;
  33.528 -	struct razor_package_query *query;
  33.529 -	struct razor_package_iterator *pi;
  33.530 -	struct razor_package *package;
  33.531 -	const char *name, *version, *arch;
  33.532 -
  33.533 -	if (argc == 0) {
  33.534 -		printf("no packages given for erase\n");
  33.535 -		exit(1);
  33.536 -	}
  33.537 -
  33.538 -	set = razor_set_open(repo_filename);
  33.539 -	upstream = razor_set_create();
  33.540 -
  33.541 -	trans = razor_transaction_create(set, upstream);
  33.542 -
  33.543 -	query = razor_package_query_create(set);
  33.544 -	add_command_line_packages(set, query, argc, argv);
  33.545 -
  33.546 -	pi = razor_package_query_finish(query);
  33.547 -	while (razor_package_iterator_next(pi, &package,
  33.548 -					   &name, &version, &arch))
  33.549 -		razor_transaction_remove_package(trans, package);
  33.550 -	razor_package_iterator_destroy(pi);
  33.551 -
  33.552 -	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  33.553 -		printf("unsatisfied dependencies.\n");
  33.554 -		exit(1);
  33.555 -	}
  33.556 -
  33.557 -	if (option_test)
  33.558 -		exit(0);
  33.559 -
  33.560 -	next = razor_transaction_finish(trans);
  33.561 -
  33.562 -	if (!option_justdb)
  33.563 -		razor_set_diff(set, next, remove_package, NULL);
  33.564 -
  33.565 -	razor_set_destroy(set);
  33.566 -	razor_set_destroy(upstream);
  33.567 -
  33.568 -	razor_set_destroy(next);
  33.569 -}
  33.570 -
  33.571 -static void
  33.572 -install_package(const char *name,
  33.573 -		const char *old_version, const char *new_version,
  33.574 -		const char *arch, void *data)
  33.575 -{
  33.576 -	if (new_version)
  33.577 -		printf("install %s-%s.%s\n", name, new_version, arch);
  33.578 -}
  33.579 -
  33.580 -static void
  33.581 -command_install(int argc, const char *argv[])
  33.582 -{
  33.583 -	struct razor_set *set, *upstream, *next;
  33.584 -	struct razor_transaction *trans;
  33.585 -	struct razor_package_iterator *pi;
  33.586 -	struct razor_package *package;
  33.587 -	const char *name, *version, *arch;
  33.588 -
  33.589 -	if (argc == 0) {
  33.590 -		printf("no packages given for install\n");
  33.591 -		exit(1);
  33.592 -	}
  33.593 -
  33.594 -	set = razor_set_open(repo_filename);
  33.595 -	upstream = create_set_from_command_line(argc, argv);
  33.596 -
  33.597 -	trans = razor_transaction_create(set, upstream);
  33.598 -
  33.599 -	pi = razor_package_iterator_create(upstream);
  33.600 -	while (razor_package_iterator_next(pi, &package,
  33.601 -					   &name, &version, &arch))
  33.602 -		razor_transaction_install_package(trans, package);
  33.603 -	razor_package_iterator_destroy(pi);
  33.604 -
  33.605 -	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  33.606 -		printf("unsatisfied dependencies.\n");
  33.607 -		exit(1);
  33.608 -	}
  33.609 -
  33.610 -	if (option_test)
  33.611 -		exit(0);
  33.612 -
  33.613 -	next = razor_transaction_finish(trans);
  33.614 -
  33.615 -	if (!option_justdb)
  33.616 -		razor_set_diff(set, next, install_package, NULL);
  33.617 -
  33.618 -	razor_set_destroy(set);
  33.619 -	razor_set_destroy(upstream);
  33.620 -
  33.621 -	razor_set_destroy(next);
  33.622 -}
  33.623 -
  33.624 -static void
  33.625 -update_package(const char *name,
  33.626 -	       const char *old_version, const char *new_version,
  33.627 -	       const char *arch, void *data)
  33.628 -{
  33.629 -	if (old_version)
  33.630 -		printf("remove %s-%s.%s\n", name, old_version, arch);
  33.631 -	if (new_version)
  33.632 -		printf("install %s-%s.%s\n", name, new_version, arch);
  33.633 -}
  33.634 -
  33.635 -static void
  33.636 -command_update(int argc, const char *argv[])
  33.637 -{
  33.638 -	struct razor_set *set, *upstream, *next;
  33.639 -	struct razor_transaction *trans;
  33.640 -	struct razor_package_iterator *pi;
  33.641 -	struct razor_package *package;
  33.642 -	const char *name, *version, *arch;
  33.643 -
  33.644 -	if (argc == 0) {
  33.645 -		printf("no packages given for update\n");
  33.646 -		exit(1);
  33.647 -	}
  33.648 -
  33.649 -	set = razor_set_open(repo_filename);
  33.650 -	upstream = create_set_from_command_line(argc, argv);
  33.651 -
  33.652 -	trans = razor_transaction_create(set, upstream);
  33.653 -
  33.654 -	pi = razor_package_iterator_create(upstream);
  33.655 -	while (razor_package_iterator_next(pi, &package,
  33.656 -					   &name, &version, &arch))
  33.657 -		razor_transaction_update_package(trans, package);
  33.658 -	razor_package_iterator_destroy(pi);
  33.659 -
  33.660 -	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  33.661 -		printf("unsatisfied dependencies.\n");
  33.662 -		exit(1);
  33.663 -	}
  33.664 -
  33.665 -	if (option_test)
  33.666 -		exit(0);
  33.667 -
  33.668 -	next = razor_transaction_finish(trans);
  33.669 -
  33.670 -	if (!option_justdb)
  33.671 -		razor_set_diff(set, next, update_package, NULL);
  33.672 -
  33.673 -	razor_set_destroy(set);
  33.674 -	razor_set_destroy(upstream);
  33.675 -
  33.676 -	razor_set_destroy(next);
  33.677 -}
  33.678 -
  33.679 -static int
  33.680 -for_each_option(const struct option *options,
  33.681 -		const char *name, char short_name,
  33.682 -		void (*fn)(const struct option *o,
  33.683 -			   const char *name, char short_name,
  33.684 -			   void *data), void *data)
  33.685 -{
  33.686 -	int i, count = 0;
  33.687 -
  33.688 -	for (i = 0; options[i].type != OPTION_LAST; i++) {
  33.689 -		switch (options[i].type) {
  33.690 -		case OPTION_GROUP:
  33.691 -			count += for_each_option(options[i].data,
  33.692 -						 name, short_name, fn, data);
  33.693 -			break;
  33.694 -
  33.695 -		case OPTION_BOOL:
  33.696 -		case OPTION_STRING:
  33.697 -			if (name && strcmp(options[i].name, name) == 0) {
  33.698 -				fn(&options[i], name, 0, data);
  33.699 -				count++;
  33.700 -				break;
  33.701 -			}
  33.702 -
  33.703 -			if (short_name &&
  33.704 -			    short_name == options[i].short_name) {
  33.705 -				fn(&options[i], NULL, short_name, data);
  33.706 -				count++;
  33.707 -				break;
  33.708 -			}
  33.709 -			break;
  33.710 -
  33.711 -		case OPTION_LAST:
  33.712 -			break;
  33.713 -		}
  33.714 -	}
  33.715 -
  33.716 -	return count;
  33.717 -}
  33.718 -
  33.719 -static void
  33.720 -handle_option(const struct option *o,
  33.721 -	      const char *name, char short_name, void *data)
  33.722 -{
  33.723 -	if (o->data == NULL) {
  33.724 -		if (name)
  33.725 -			printf("option --%s not supported\n", name);
  33.726 -		else
  33.727 -			printf("option -%c not supported\n", short_name);
  33.728 -		return;
  33.729 -	}
  33.730 -
  33.731 -	switch (o->type) {
  33.732 -	case OPTION_BOOL:
  33.733 -		*(int *) o->data = 1;
  33.734 -		break;
  33.735 -
  33.736 -	case OPTION_STRING:
  33.737 -		*(const char **) o->data = name + strlen(o->name) + 1;
  33.738 -		break;
  33.739 -
  33.740 -	case OPTION_LAST:
  33.741 -	case OPTION_GROUP:
  33.742 -		/* Shouldn't happen. */
  33.743 -		break;
  33.744 -	}
  33.745 -}
  33.746 -
  33.747 -static int
  33.748 -parse_options(const struct option *options, int argc, const char **argv)
  33.749 -{
  33.750 -	int i, j, k;
  33.751 -
  33.752 -	for (i = 1, j = 0; i < argc; i++) {
  33.753 -		if (argv[i][0] != '-') {
  33.754 -			argv[j++] = argv[i];
  33.755 -			continue;
  33.756 -		}
  33.757 -
  33.758 -		if (argv[i][1] == '-') {
  33.759 -			if (for_each_option(options, &argv[i][2], 0,
  33.760 -					    handle_option, NULL) == 0) {
  33.761 -				printf("unknown option: %s\n", argv[i]);
  33.762 -				exit(1);
  33.763 -			}
  33.764 -			continue;
  33.765 -		}
  33.766 -
  33.767 -		for (k = 1; argv[i][k]; k++) {
  33.768 -			if (for_each_option(options, NULL, argv[i][k],
  33.769 -					    handle_option, NULL) == 0) {
  33.770 -				printf("unknown option: -%c\n", argv[i][k]);
  33.771 -				exit(1);
  33.772 -			}
  33.773 -		}
  33.774 -	}
  33.775 -
  33.776 -	return j;
  33.777 -}
  33.778 -
  33.779 -static void
  33.780 -print_options_help(const struct option *options)
  33.781 -{
  33.782 -	int i;
  33.783 -
  33.784 -	for (i = 0; options[i].type != OPTION_LAST; i++) {
  33.785 -		switch (options[i].type) {
  33.786 -		case OPTION_GROUP:
  33.787 -			printf("%s\n", options[i].description);
  33.788 -			print_options_help(options[i].data);
  33.789 -			printf("\n");
  33.790 -			break;
  33.791 -
  33.792 -		case OPTION_BOOL:
  33.793 -		case OPTION_STRING:
  33.794 -			printf("  ");
  33.795 -			if (options[i].short_name)
  33.796 -				printf("-%c", options[i].short_name);
  33.797 -			if (options[i].short_name && options[i].name)
  33.798 -				printf(", ");
  33.799 -			if (options[i].name)
  33.800 -				printf("--%s", options[i].name);
  33.801 -			if (options[i].arg_name)
  33.802 -				printf("=%s", options[i].arg_name);
  33.803 -			if (options[i].description)
  33.804 -				printf("\t\t%s", options[i].description);
  33.805 -			printf("\n");
  33.806 -			break;
  33.807 -
  33.808 -		case OPTION_LAST:
  33.809 -			break;
  33.810 -		}
  33.811 -	}
  33.812 -}
  33.813 -
  33.814 -static void
  33.815 -print_options_usage(const struct option *options)
  33.816 -{
  33.817 -	int i;
  33.818 -
  33.819 -	for (i = 0; options[i].type != OPTION_LAST; i++) {
  33.820 -		switch (options[i].type) {
  33.821 -		case OPTION_GROUP:
  33.822 -			print_options_usage(options[i].data);
  33.823 -			break;
  33.824 -
  33.825 -		case OPTION_BOOL:
  33.826 -			printf("[");
  33.827 -			if (options[i].short_name)
  33.828 -				printf("-%c", options[i].short_name);
  33.829 -			if (options[i].short_name && options[i].name)
  33.830 -				printf("|");
  33.831 -			if (options[i].name)
  33.832 -				printf("--%s", options[i].name);
  33.833 -			printf("] ");
  33.834 -			break;
  33.835 -
  33.836 -		case OPTION_STRING:
  33.837 -			printf("[");
  33.838 -			if (options[i].short_name)
  33.839 -				printf("-%c", options[i].short_name);
  33.840 -			if (options[i].short_name && options[i].name)
  33.841 -				printf("|");
  33.842 -			if (options[i].name)
  33.843 -				printf("--%s", options[i].name);
  33.844 -			if (options[i].arg_name)
  33.845 -				printf("=%s", options[i].arg_name);
  33.846 -			printf("] ");
  33.847 -			break;
  33.848 -
  33.849 -
  33.850 -			break;
  33.851 -
  33.852 -		case OPTION_LAST:
  33.853 -			break;
  33.854 -		}
  33.855 -	}
  33.856 -}
  33.857 -
  33.858 -int
  33.859 -main(int argc, const char *argv[])
  33.860 -{
  33.861 -	argc = parse_options(rpm_options, argc, argv);
  33.862 -
  33.863 -	if (option_version) {
  33.864 -		printf("razor rpm version hoopla.\n");
  33.865 -		exit(0);
  33.866 -	}
  33.867 -
  33.868 -	if (option_help) {
  33.869 -		printf("Usage: rpm [OPTION...]\n");
  33.870 -		print_options_help(rpm_options);
  33.871 -		exit(0);
  33.872 -	}
  33.873 -
  33.874 -	if (option_usage) {
  33.875 -		printf("Usage: rpm [OPTION...]\n");
  33.876 -		print_options_usage(rpm_options);
  33.877 -		printf("\n");
  33.878 -		exit(0);
  33.879 -	}
  33.880 -
  33.881 -	if (option_initdb) {
  33.882 -		command_initdb(argc, argv);
  33.883 -	} else if (option_verify) {
  33.884 -		command_verify(argc, argv);
  33.885 -	} else if (option_query) {
  33.886 -		command_query(argc, argv);
  33.887 -	} else if (option_install) {
  33.888 -		command_install(argc, argv);
  33.889 -	} else if (option_upgrade) {
  33.890 -		command_update(argc, argv);
  33.891 -	} else if (option_erase) {
  33.892 -		command_erase(argc, argv);
  33.893 -	} else {
  33.894 -		print_options_usage(rpm_options);
  33.895 -		printf("\n");
  33.896 -		exit(0);
  33.897 -	}
  33.898 -
  33.899 -	return 0;
  33.900 -}
    34.1 --- a/rpm.c	Sun Jun 15 23:15:59 2008 -0400
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,748 +0,0 @@
    34.4 -/*
    34.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    34.6 - * Copyright (C) 2008  Red Hat, Inc
    34.7 - *
    34.8 - * This program is free software; you can redistribute it and/or modify
    34.9 - * it under the terms of the GNU General Public License as published by
   34.10 - * the Free Software Foundation; either version 2 of the License, or
   34.11 - * (at your option) any later version.
   34.12 - *
   34.13 - * This program is distributed in the hope that it will be useful,
   34.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.16 - * GNU General Public License for more details.
   34.17 - *
   34.18 - * You should have received a copy of the GNU General Public License along
   34.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   34.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   34.21 - */
   34.22 -
   34.23 -#include <stdio.h>
   34.24 -#include <stddef.h>
   34.25 -#include <string.h>
   34.26 -#include <errno.h>
   34.27 -#include <sys/stat.h>
   34.28 -#include <sys/mman.h>
   34.29 -#include <sys/types.h>
   34.30 -#include <sys/wait.h>
   34.31 -#include <fcntl.h>
   34.32 -#include <unistd.h>
   34.33 -#include <arpa/inet.h>
   34.34 -#include <rpm/rpmlib.h>
   34.35 -#include <rpm/rpmdb.h>
   34.36 -#include <zlib.h>
   34.37 -
   34.38 -#include "razor.h"
   34.39 -#include "razor-internal.h"
   34.40 -
   34.41 -#define	RPM_LEAD_SIZE 96
   34.42 -
   34.43 -struct rpm_header {
   34.44 -	unsigned char magic[4];
   34.45 -	unsigned char reserved[4];
   34.46 -	int nindex;
   34.47 -	int hsize;
   34.48 -};
   34.49 -
   34.50 -struct rpm_header_index {
   34.51 -	int tag;
   34.52 -	int type;
   34.53 -	int offset;
   34.54 -	int count;
   34.55 -};
   34.56 -
   34.57 -struct razor_rpm {
   34.58 -	struct rpm_header *signature;
   34.59 -	struct rpm_header *header;
   34.60 -	const char **dirs;
   34.61 -	const char *pool;
   34.62 -	void *map;
   34.63 -	size_t size;
   34.64 -	void *payload;
   34.65 -};
   34.66 -
   34.67 -static struct rpm_header_index *
   34.68 -razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
   34.69 -{
   34.70 -	struct rpm_header_index *index, *end;
   34.71 -
   34.72 -	index = (struct rpm_header_index *) (rpm->header + 1);
   34.73 -	end = index + ntohl(rpm->header->nindex);
   34.74 -	while (index < end) {
   34.75 -		if (ntohl(index->tag) == tag)
   34.76 -			return index;
   34.77 -		index++;
   34.78 -	}
   34.79 -
   34.80 -	return NULL;
   34.81 -}
   34.82 -
   34.83 -static const void *
   34.84 -razor_rpm_get_indirect(struct razor_rpm *rpm,
   34.85 -		       unsigned int tag, unsigned int *count)
   34.86 -{
   34.87 -	struct rpm_header_index *index;
   34.88 -
   34.89 -	index = razor_rpm_get_header(rpm, tag);
   34.90 -	if (index != NULL) {
   34.91 -		if (count)
   34.92 -			*count = ntohl(index->count);
   34.93 -
   34.94 -		return rpm->pool + ntohl(index->offset);
   34.95 -	}
   34.96 -
   34.97 -	return NULL;
   34.98 -}
   34.99 -
  34.100 -static enum razor_version_relation
  34.101 -rpm_to_razor_flags (uint_32 flags)
  34.102 -{
  34.103 -	switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
  34.104 -	case RPMSENSE_LESS:
  34.105 -		return RAZOR_VERSION_LESS;
  34.106 -	case RPMSENSE_LESS|RPMSENSE_EQUAL:
  34.107 -		return RAZOR_VERSION_LESS_OR_EQUAL;
  34.108 -	case RPMSENSE_EQUAL:
  34.109 -		return RAZOR_VERSION_EQUAL;
  34.110 -	case RPMSENSE_GREATER|RPMSENSE_EQUAL:
  34.111 -		return RAZOR_VERSION_GREATER_OR_EQUAL;
  34.112 -	case RPMSENSE_GREATER:
  34.113 -		return RAZOR_VERSION_GREATER;
  34.114 -	}
  34.115 -
  34.116 -	/* FIXME? */
  34.117 -	return RAZOR_VERSION_EQUAL;
  34.118 -}
  34.119 -
  34.120 -static void
  34.121 -import_properties(struct razor_importer *importer, unsigned long type,
  34.122 -		  struct razor_rpm *rpm,
  34.123 -		  int name_tag, int version_tag, int flags_tag)
  34.124 -{
  34.125 -	const char *name, *version;
  34.126 -	const uint_32 *flags;
  34.127 -	uint_32 f;
  34.128 -	unsigned int i, count;
  34.129 -
  34.130 -	name = razor_rpm_get_indirect(rpm, name_tag, &count);
  34.131 -	if (name == NULL)
  34.132 -		return;
  34.133 -
  34.134 -	flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
  34.135 -
  34.136 -	version = razor_rpm_get_indirect(rpm, version_tag, &count);
  34.137 -	for (i = 0; i < count; i++) {
  34.138 -		f = rpm_to_razor_flags(ntohl(flags[i]));
  34.139 -		razor_importer_add_property(importer, name, f, version, type);
  34.140 -		name += strlen(name) + 1;
  34.141 -		version += strlen(version) + 1;
  34.142 -	}
  34.143 -}
  34.144 -
  34.145 -static void
  34.146 -import_files(struct razor_importer *importer, struct razor_rpm *rpm)
  34.147 -{
  34.148 -	const char *name;
  34.149 -	const uint32_t *index;
  34.150 -	unsigned int i, count;
  34.151 -	char buffer[256];
  34.152 -
  34.153 -	/* assert: count is the same for all arrays */
  34.154 -
  34.155 -	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
  34.156 -	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
  34.157 -	for (i = 0; i < count; i++) {
  34.158 -		snprintf(buffer, sizeof buffer,
  34.159 -			 "%s%s", rpm->dirs[ntohl(*index)], name);
  34.160 -		razor_importer_add_file(importer, buffer);
  34.161 -		name += strlen(name) + 1;
  34.162 -		index++;
  34.163 -	}
  34.164 -}
  34.165 -
  34.166 -struct razor_rpm *
  34.167 -razor_rpm_open(const char *filename)
  34.168 -{
  34.169 -	struct razor_rpm *rpm;
  34.170 -	struct rpm_header_index *base, *index;
  34.171 -	struct stat buf;
  34.172 -	unsigned int count, i, nindex, hsize;
  34.173 -	const char *name;
  34.174 -	int fd;
  34.175 -
  34.176 -	rpm = malloc(sizeof *rpm);
  34.177 -	memset(rpm, 0, sizeof *rpm);
  34.178 -
  34.179 -	fd = open(filename, O_RDONLY);
  34.180 -	if (fd < 0) {
  34.181 -		fprintf(stderr, "couldn't open %s\n", filename);
  34.182 -		return NULL;
  34.183 -	}
  34.184 -
  34.185 -	if (fstat(fd, &buf) < 0) {
  34.186 -		fprintf(stderr, "failed to stat %s (%m)\n", filename);
  34.187 -		return NULL;
  34.188 -	}
  34.189 -
  34.190 -	rpm->size = buf.st_size;
  34.191 -	rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
  34.192 -	if (rpm->map == MAP_FAILED) {
  34.193 -		fprintf(stderr, "couldn't mmap %s\n", filename);
  34.194 -		return NULL;
  34.195 -	}
  34.196 -	close(fd);
  34.197 -
  34.198 -	rpm->signature = rpm->map + RPM_LEAD_SIZE;
  34.199 -	nindex = ntohl(rpm->signature->nindex);
  34.200 -	hsize = ntohl(rpm->signature->hsize);
  34.201 -	rpm->header = (void *) (rpm->signature + 1) +
  34.202 -		ALIGN(nindex * sizeof *index + hsize, 8);
  34.203 -	nindex = ntohl(rpm->header->nindex);
  34.204 -	hsize = ntohl(rpm->header->hsize);
  34.205 -	rpm->payload = (void *) (rpm->header + 1) +
  34.206 -		nindex * sizeof *index + hsize;
  34.207 -
  34.208 -	base = (struct rpm_header_index *) (rpm->header + 1);
  34.209 -	rpm->pool = (void *) base + nindex * sizeof *index;
  34.210 -
  34.211 -	/* Look up dir names now so we can index them directly. */
  34.212 -	name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
  34.213 -	if (name) {
  34.214 -		rpm->dirs = calloc(count, sizeof *rpm->dirs);
  34.215 -		for (i = 0; i < count; i++) {
  34.216 -			rpm->dirs[i] = name;
  34.217 -			name += strlen(name) + 1;
  34.218 -		}
  34.219 -	} else {
  34.220 -		name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
  34.221 -					      &count);
  34.222 -		if (name) {
  34.223 -			fprintf(stderr, "old filenames not supported\n");
  34.224 -			return NULL;
  34.225 -		}
  34.226 -	}
  34.227 -
  34.228 -	return rpm;
  34.229 -}
  34.230 -
  34.231 -struct cpio_file_header {
  34.232 -	char magic[6];
  34.233 -	char inode[8];
  34.234 -	char mode[8];
  34.235 -	char uid[8];
  34.236 -	char gid[8];
  34.237 -	char nlink[8];
  34.238 -	char mtime[8];
  34.239 -	char filesize[8];
  34.240 -	char devmajor[8];
  34.241 -	char devminor[8];
  34.242 -	char rdevmajor[8];
  34.243 -	char rdevminor[8];
  34.244 -	char namesize[8];
  34.245 -	char checksum[8];
  34.246 -	char filename[0];
  34.247 -};
  34.248 -
  34.249 -/* gzip flags */
  34.250 -#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
  34.251 -#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
  34.252 -#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  34.253 -#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  34.254 -#define COMMENT      0x10 /* bit 4 set: file comment present */
  34.255 -#define RESERVED     0xE0 /* bits 5..7: reserved */
  34.256 -
  34.257 -struct installer {
  34.258 -	const char *root;
  34.259 -	struct razor_rpm *rpm;
  34.260 -	z_stream stream;
  34.261 -	unsigned char buffer[32768];
  34.262 -	size_t rest, length;
  34.263 -};
  34.264 -
  34.265 -static int
  34.266 -installer_inflate(struct installer *installer)
  34.267 -{
  34.268 -	size_t length;
  34.269 -	int err;
  34.270 -
  34.271 -	if (installer->rest > sizeof installer->buffer)
  34.272 -		length = sizeof installer->buffer;
  34.273 -	else
  34.274 -		length = installer->rest;
  34.275 -
  34.276 -	installer->stream.next_out = installer->buffer;
  34.277 -	installer->stream.avail_out = length;
  34.278 -	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  34.279 -	if (err != Z_OK && err != Z_STREAM_END) {
  34.280 -		fprintf(stderr, "inflate error: %d (%m)\n", err);
  34.281 -		return -1;
  34.282 -	}
  34.283 -
  34.284 -	installer->rest -= length;
  34.285 -	installer->length = length;
  34.286 -
  34.287 -	return 0;
  34.288 -}
  34.289 -
  34.290 -static int
  34.291 -installer_align(struct installer *installer, size_t size)
  34.292 -{
  34.293 -	unsigned char buffer[4];
  34.294 -	int err;
  34.295 -
  34.296 -	installer->stream.next_out = buffer;
  34.297 -	installer->stream.avail_out =
  34.298 -		(size - installer->stream.total_out) & (size - 1);
  34.299 -
  34.300 -	if (installer->stream.avail_out == 0)
  34.301 -		return 0;
  34.302 -
  34.303 -	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  34.304 -	if (err != Z_OK && err != Z_STREAM_END) {
  34.305 -		fprintf(stderr, "inflate error: %d (%m)\n", err);
  34.306 -		return -1;
  34.307 -	}
  34.308 -
  34.309 -	return 0;
  34.310 -}
  34.311 -
  34.312 -static int
  34.313 -create_path(struct installer *installer, const char *path, unsigned int mode)
  34.314 -{
  34.315 -	char buffer[PATH_MAX];
  34.316 -	struct stat buf;
  34.317 -	int fd, ret;
  34.318 -
  34.319 -	if (razor_create_dir(installer->root, path) < 0)
  34.320 -		return -1;
  34.321 -
  34.322 -	snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
  34.323 -
  34.324 -	switch (mode >> 12) {
  34.325 -	case REG:
  34.326 -		/* FIXME: handle the case where a file is already there. */
  34.327 -		fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, mode & 0x1ff);
  34.328 -		if (fd < 0){
  34.329 -			fprintf(stderr, "failed to create file %s\n", buffer);
  34.330 -			return -1;
  34.331 -		}
  34.332 -		while (installer->rest > 0) {
  34.333 -			if (installer_inflate(installer)) {
  34.334 -				fprintf(stderr, "failed to inflate\n");
  34.335 -				return -1;
  34.336 -			}
  34.337 -			if (razor_write(fd, installer->buffer,
  34.338 -					installer->length)) {
  34.339 -				fprintf(stderr, "failed to write payload\n");
  34.340 -				return -1;
  34.341 -			}
  34.342 -		}
  34.343 -		if (close(fd) < 0) {
  34.344 -			fprintf(stderr, "failed to close %s: %m\n", buffer);
  34.345 -			return -1;
  34.346 -		}
  34.347 -		return 0;
  34.348 -	case XDIR:
  34.349 -		ret = mkdir(buffer, mode & 0x1ff);
  34.350 -		if (ret == 0 || errno != EEXIST)
  34.351 -			return ret;
  34.352 -		if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
  34.353 -			/* FIXME: also check that mode match. */
  34.354 -			fprintf(stderr,
  34.355 -				"%s exists but is not a directory\n", buffer);
  34.356 -			return -1;
  34.357 -		}
  34.358 -		return 0;
  34.359 -	case PIPE:
  34.360 -	case CDEV:
  34.361 -	case BDEV:
  34.362 -	case SOCK:
  34.363 -		printf("%s: unhandled file type %d\n", buffer, mode >> 12);
  34.364 -		return 0;
  34.365 -	case LINK:
  34.366 -		if (installer_inflate(installer)) {
  34.367 -			fprintf(stderr, "failed to inflate\n");
  34.368 -			return -1;
  34.369 -		}
  34.370 -		if (installer->length >= sizeof installer->buffer) {
  34.371 -			fprintf(stderr, "link name too long\n");
  34.372 -			return -1;
  34.373 -		}
  34.374 -		installer->buffer[installer->length] = '\0';
  34.375 -		if (symlink((const char *) installer->buffer, buffer)) {
  34.376 -			fprintf(stderr, "failed to create symlink, %m\n");
  34.377 -			return -1;
  34.378 -		}
  34.379 -		return 0;
  34.380 -	default:
  34.381 -		printf("%s: unknown file type %d\n", buffer, mode >> 12);
  34.382 -		return 0;
  34.383 -	}
  34.384 -}
  34.385 -
  34.386 -static int
  34.387 -run_script(struct installer *installer,
  34.388 -	   unsigned int program_tag, unsigned int script_tag)
  34.389 -{
  34.390 -	int pid, status, fd[2];
  34.391 -	const char *script = NULL, *program = NULL;
  34.392 -
  34.393 -	program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
  34.394 -	script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
  34.395 -	if (program == NULL && script == NULL) {
  34.396 -		return 0;
  34.397 -	} else if (program == NULL) {
  34.398 -		program = "/bin/sh";
  34.399 -	}
  34.400 -
  34.401 -	if (pipe(fd) < 0) {
  34.402 -		fprintf(stderr, "failed to create pipe\n");
  34.403 -		return -1;
  34.404 -	}
  34.405 -	pid = fork();
  34.406 -	if (pid < 0) {
  34.407 -		fprintf(stderr, "failed to fork, %m\n");
  34.408 -	} else if (pid == 0) {
  34.409 -		if (dup2(fd[0], STDIN_FILENO) < 0) {
  34.410 -			fprintf(stderr, "failed redirect stdin, %m\n");
  34.411 -			return -1;
  34.412 -		}
  34.413 -		if (close(fd[0]) < 0 || close(fd[1]) < 0) {
  34.414 -			fprintf(stderr, "failed to close pipe, %m\n");
  34.415 -			return -1;
  34.416 -		}
  34.417 -		if (chroot(installer->root) < 0) {
  34.418 -			fprintf(stderr, "failed to chroot to %s, %m\n",
  34.419 -				installer->root);
  34.420 -			return -1;
  34.421 -		}
  34.422 -		printf("executing program %s in chroot %s\n",
  34.423 -		       program, installer->root);
  34.424 -		if (execl(program, program, NULL)) {
  34.425 -			fprintf(stderr, "failed to exec %s, %m\n", program);
  34.426 -			exit(-1);
  34.427 -		}
  34.428 -	} else {
  34.429 -		if (script && razor_write(fd[1], script, strlen(script)) < 0) {
  34.430 -			fprintf(stderr, "failed to pipe script, %m\n");
  34.431 -			return -1;
  34.432 -		}
  34.433 -		if (close(fd[0]) || close(fd[1])) {
  34.434 -			fprintf(stderr, "failed to close pipe, %m\n");
  34.435 -			return -1;
  34.436 -		}
  34.437 -		if (wait(&status) < 0) {
  34.438 -			fprintf(stderr, "wait for child failed, %m");
  34.439 -			return -1;
  34.440 -		}
  34.441 -		if (status)
  34.442 -			printf("script exited with status %d\n", status);
  34.443 -	}
  34.444 -
  34.445 -	return 0;
  34.446 -}
  34.447 -
  34.448 -static int
  34.449 -installer_init(struct installer *installer)
  34.450 -{
  34.451 -	unsigned char *gz_header;
  34.452 -	int method, flags, err;
  34.453 -
  34.454 -	gz_header = installer->rpm->payload;
  34.455 -	if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
  34.456 -		fprintf(stderr, "payload section doesn't have gz header\n");
  34.457 -		return -1;
  34.458 -	}
  34.459 -
  34.460 -	method = gz_header[2];
  34.461 -	flags = gz_header[3];
  34.462 -
  34.463 -	if (method != Z_DEFLATED || flags != 0) {
  34.464 -		fprintf(stderr,
  34.465 -			"unknown payload compression method or flags set\n");
  34.466 -		return -1;
  34.467 -	}
  34.468 -
  34.469 -	installer->stream.zalloc = NULL;
  34.470 -	installer->stream.zfree = NULL;
  34.471 -	installer->stream.opaque = NULL;
  34.472 -
  34.473 -	installer->stream.next_in  = gz_header + 10;
  34.474 -	installer->stream.avail_in =
  34.475 -		(installer->rpm->map + installer->rpm->size) -
  34.476 -		(void *) installer->stream.next_in;
  34.477 -	installer->stream.next_out = NULL;
  34.478 -	installer->stream.avail_out = 0;
  34.479 -
  34.480 -	err = inflateInit2(&installer->stream, -MAX_WBITS);
  34.481 -	if (err != Z_OK) {
  34.482 -		fprintf(stderr, "inflateInit error: %d\n", err);
  34.483 -		return -1;
  34.484 -	}
  34.485 -
  34.486 -	return 0;
  34.487 -}
  34.488 -
  34.489 -static int
  34.490 -installer_finish(struct installer *installer)
  34.491 -{
  34.492 -	int err;
  34.493 -
  34.494 -	err = inflateEnd(&installer->stream);
  34.495 -
  34.496 -	if (err != Z_OK) {
  34.497 -		fprintf(stderr, "inflateEnd error: %d\n", err);
  34.498 -		return -1;
  34.499 -	}	    
  34.500 -
  34.501 -	return 0;
  34.502 -}
  34.503 -
  34.504 -static unsigned long
  34.505 -fixed_hex_to_ulong(const char *hex, int length)
  34.506 -{
  34.507 -	long l;
  34.508 -	int i;
  34.509 -
  34.510 -	for (i = 0, l = 0; i < length; i++) {
  34.511 -		if (hex[i] < 'a')
  34.512 -			l = l * 16 + hex[i] - '0';
  34.513 -		else
  34.514 -			l = l * 16 + hex[i] - 'a' + 10;
  34.515 -	}
  34.516 -
  34.517 -	return l;
  34.518 -}
  34.519 -
  34.520 -int
  34.521 -razor_rpm_install(struct razor_rpm *rpm, const char *root)
  34.522 -{
  34.523 -	struct installer installer;
  34.524 -	struct cpio_file_header *header;
  34.525 -	struct stat buf;
  34.526 -	unsigned int mode;
  34.527 -	char *path;
  34.528 -	size_t filesize;
  34.529 -
  34.530 -	installer.rpm = rpm;
  34.531 -	installer.root = root;
  34.532 -
  34.533 -	/* FIXME: Only do this before a transaction, not per rpm. */
  34.534 -	if (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
  34.535 -		fprintf(stderr,
  34.536 -			"root installation directory \"%s\" does not exist\n",
  34.537 -			root);
  34.538 -		return -1;
  34.539 -	}
  34.540 -
  34.541 -	if (installer_init(&installer))
  34.542 -		return -1;
  34.543 -
  34.544 -	run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
  34.545 -
  34.546 -	while (installer.stream.avail_in > 0) {
  34.547 -		installer.rest = sizeof *header;
  34.548 -		if (installer_inflate(&installer))
  34.549 -			return -1;
  34.550 -		
  34.551 -		header = (struct cpio_file_header *) installer.buffer;
  34.552 -		mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
  34.553 -		filesize = fixed_hex_to_ulong(header->filesize,
  34.554 -					      sizeof header->filesize);
  34.555 -
  34.556 -		installer.rest = fixed_hex_to_ulong(header->namesize,
  34.557 -						    sizeof header->namesize);
  34.558 -
  34.559 -		if (installer_inflate(&installer) ||
  34.560 -		    installer_align(&installer, 4))
  34.561 -			return -1;
  34.562 -
  34.563 -		path = (char *) installer.buffer;
  34.564 -		/* This convention is so lame... */
  34.565 -		if (strcmp(path, "TRAILER!!!") == 0)
  34.566 -			break;
  34.567 -
  34.568 -		installer.rest = filesize;
  34.569 -		if (create_path(&installer, path + 1, mode) < 0)
  34.570 -			return -1;
  34.571 -		if (installer_align(&installer, 4))
  34.572 -			return -1;
  34.573 -	}
  34.574 -
  34.575 -	if (installer_finish(&installer))
  34.576 -		return -1;
  34.577 -
  34.578 -	run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
  34.579 -
  34.580 -	return 0;
  34.581 -}
  34.582 -
  34.583 -int
  34.584 -razor_rpm_close(struct razor_rpm *rpm)
  34.585 -{
  34.586 -	int err;
  34.587 -
  34.588 -	free(rpm->dirs);
  34.589 -	err = munmap(rpm->map, rpm->size);
  34.590 -	free(rpm);
  34.591 -
  34.592 -	return err;
  34.593 -}
  34.594 -
  34.595 -int
  34.596 -razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
  34.597 -{
  34.598 -	const char *name, *version, *release, *arch;
  34.599 -	const uint_32 *epoch;
  34.600 -	char evr[128], buf[16];
  34.601 -
  34.602 -	name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
  34.603 -	epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
  34.604 -	version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
  34.605 -	release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
  34.606 -	arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
  34.607 -
  34.608 -	if (epoch) {
  34.609 -		snprintf(buf, sizeof buf, "%u", ntohl(*epoch));
  34.610 -		razor_build_evr(evr, sizeof evr, buf, version, release);
  34.611 -	} else {
  34.612 -		razor_build_evr(evr, sizeof evr, NULL, version, release);
  34.613 -	}
  34.614 -	razor_importer_begin_package(importer, name, evr, arch);
  34.615 -
  34.616 -	import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
  34.617 -			  RPMTAG_REQUIRENAME,
  34.618 -			  RPMTAG_REQUIREVERSION,
  34.619 -			  RPMTAG_REQUIREFLAGS);
  34.620 -
  34.621 -	import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
  34.622 -			  RPMTAG_PROVIDENAME,
  34.623 -			  RPMTAG_PROVIDEVERSION,
  34.624 -			  RPMTAG_PROVIDEFLAGS);
  34.625 -
  34.626 -	import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
  34.627 -			  RPMTAG_OBSOLETENAME,
  34.628 -			  RPMTAG_OBSOLETEVERSION,
  34.629 -			  RPMTAG_OBSOLETEFLAGS);
  34.630 -
  34.631 -	import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
  34.632 -			  RPMTAG_CONFLICTNAME,
  34.633 -			  RPMTAG_CONFLICTVERSION,
  34.634 -			  RPMTAG_CONFLICTFLAGS);
  34.635 -
  34.636 -	import_files(importer, rpm);
  34.637 -
  34.638 -	razor_importer_finish_package(importer);
  34.639 -
  34.640 -	return 0;
  34.641 -}
  34.642 -
  34.643 -union rpm_entry {
  34.644 -	void *p;
  34.645 -	char *string;
  34.646 -	char **list;
  34.647 -	uint_32 *flags;
  34.648 -	uint_32 integer;
  34.649 -};
  34.650 -
  34.651 -static void
  34.652 -add_properties(struct razor_importer *importer,
  34.653 -	       enum razor_property_type property_type,
  34.654 -	       Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
  34.655 -{
  34.656 -	union rpm_entry names, versions, flags;
  34.657 -	int_32 i, type, count;
  34.658 -
  34.659 -	headerGetEntry(h, name_tag, &type, &names.p, &count);
  34.660 -	headerGetEntry(h, version_tag, &type, &versions.p, &count);
  34.661 -	headerGetEntry(h, flags_tag, &type, &flags.p, &count);
  34.662 -
  34.663 -	for (i = 0; i < count; i++)
  34.664 -		razor_importer_add_property(importer,
  34.665 -					    names.list[i],
  34.666 -					    rpm_to_razor_flags (flags.flags[i]),
  34.667 -					    versions.list[i],
  34.668 -					    property_type);
  34.669 -}
  34.670 -
  34.671 -struct razor_set *
  34.672 -razor_set_create_from_rpmdb(void)
  34.673 -{
  34.674 -	struct razor_importer *importer;
  34.675 -	rpmdbMatchIterator iter;
  34.676 -	Header h;
  34.677 -	int_32 type, count, i;
  34.678 -	union rpm_entry name, epoch, version, release, arch;
  34.679 -	union rpm_entry basenames, dirnames, dirindexes;
  34.680 -	char filename[PATH_MAX], evr[128], buf[16];
  34.681 -	rpmdb db;
  34.682 -
  34.683 -	rpmReadConfigFiles(NULL, NULL);
  34.684 -
  34.685 -	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
  34.686 -		fprintf(stderr, "cannot open rpm database\n");
  34.687 -		exit(1);
  34.688 -	}
  34.689 -
  34.690 -	importer = razor_importer_new();
  34.691 -
  34.692 -	iter = rpmdbInitIterator(db, 0, NULL, 0);
  34.693 -	while (h = rpmdbNextIterator(iter), h != NULL) {
  34.694 -		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
  34.695 -		headerGetEntry(h, RPMTAG_EPOCH, &type, &epoch.p, &count);
  34.696 -		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
  34.697 -		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
  34.698 -		headerGetEntry(h, RPMTAG_ARCH, &type, &arch.p, &count);
  34.699 -
  34.700 -		if (epoch.flags != NULL) {
  34.701 -			snprintf(buf, sizeof buf, "%u", *epoch.flags);
  34.702 -			razor_build_evr(evr, sizeof evr,
  34.703 -					buf, version.string, release.string);
  34.704 -		} else {
  34.705 -			razor_build_evr(evr, sizeof evr,
  34.706 -					NULL, version.string, release.string);
  34.707 -		}
  34.708 -
  34.709 -		razor_importer_begin_package(importer,
  34.710 -					     name.string, evr, arch.string);
  34.711 -
  34.712 -		add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
  34.713 -			       RPMTAG_REQUIRENAME,
  34.714 -			       RPMTAG_REQUIREVERSION,
  34.715 -			       RPMTAG_REQUIREFLAGS);
  34.716 -
  34.717 -		add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
  34.718 -			       RPMTAG_PROVIDENAME,
  34.719 -			       RPMTAG_PROVIDEVERSION,
  34.720 -			       RPMTAG_PROVIDEFLAGS);
  34.721 -
  34.722 -		add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
  34.723 -			       RPMTAG_OBSOLETENAME,
  34.724 -			       RPMTAG_OBSOLETEVERSION,
  34.725 -			       RPMTAG_OBSOLETEFLAGS);
  34.726 -
  34.727 -		add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
  34.728 -			       RPMTAG_CONFLICTNAME,
  34.729 -			       RPMTAG_CONFLICTVERSION,
  34.730 -			       RPMTAG_CONFLICTFLAGS);
  34.731 -
  34.732 -		headerGetEntry(h, RPMTAG_BASENAMES, &type,
  34.733 -			       &basenames.p, &count);
  34.734 -		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
  34.735 -			       &dirnames.p, &count);
  34.736 -		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
  34.737 -			       &dirindexes.p, &count);
  34.738 -		for (i = 0; i < count; i++) {
  34.739 -			snprintf(filename, sizeof filename, "%s%s",
  34.740 -				 dirnames.list[dirindexes.flags[i]],
  34.741 -				 basenames.list[i]);
  34.742 -			razor_importer_add_file(importer, filename);
  34.743 -		}
  34.744 -
  34.745 -		razor_importer_finish_package(importer);
  34.746 -	}
  34.747 -
  34.748 -	rpmdbClose(db);
  34.749 -
  34.750 -	return razor_importer_finish(importer);
  34.751 -}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/src/.gitignore	Mon Jun 16 15:40:30 2008 -0400
    35.3 @@ -0,0 +1,5 @@
    35.4 +.deps
    35.5 +.libs
    35.6 +razor
    35.7 +rpm-razor
    35.8 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/src/Makefile.am	Mon Jun 16 15:40:30 2008 -0400
    36.3 @@ -0,0 +1,26 @@
    36.4 +## Process this file with automake to produce Makefile.in
    36.5 +
    36.6 +INCLUDES = \
    36.7 +	$(CURL_CFLAGS) \
    36.8 +	$(EXPAT_CFLAGS) \
    36.9 +	$(RPM_CFLAGS) \
   36.10 +	-I$(top_builddir)/src -I$(top_srcdir)/src \
   36.11 +	-I$(top_srcdir)/librazor \
   36.12 +	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
   36.13 +	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
   36.14 +	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
   36.15 +	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
   36.16 +	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
   36.17 +	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\"
   36.18 +
   36.19 +bin_PROGRAMS = razor rpm
   36.20 +
   36.21 +razor_SOURCES = main.c import-rpmdb.c import-yum.c
   36.22 +razor_LDADD = $(RPM_LIBS) $(EXPAT_LIBS) $(CURL_LIBS) $(top_builddir)/librazor/librazor.la
   36.23 +
   36.24 +rpm_SOURCES = rpm.c
   36.25 +rpm_LDADD = $(top_builddir)/librazor/librazor.la
   36.26 +
   36.27 +clean-local :
   36.28 +	rm -f *~
   36.29 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/src/import-rpmdb.c	Mon Jun 16 15:40:30 2008 -0400
    37.3 @@ -0,0 +1,157 @@
    37.4 +/*
    37.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    37.6 + * Copyright (C) 2008  Red Hat, Inc
    37.7 + *
    37.8 + * This program is free software; you can redistribute it and/or modify
    37.9 + * it under the terms of the GNU General Public License as published by
   37.10 + * the Free Software Foundation; either version 2 of the License, or
   37.11 + * (at your option) any later version.
   37.12 + *
   37.13 + * This program is distributed in the hope that it will be useful,
   37.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.16 + * GNU General Public License for more details.
   37.17 + *
   37.18 + * You should have received a copy of the GNU General Public License along
   37.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   37.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   37.21 + */
   37.22 +
   37.23 +#include <stdio.h>
   37.24 +#include <stddef.h>
   37.25 +#include <string.h>
   37.26 +#include <fcntl.h>
   37.27 +#include <rpm/rpmlib.h>
   37.28 +#include <rpm/rpmdb.h>
   37.29 +
   37.30 +#include "razor.h"
   37.31 +
   37.32 +union rpm_entry {
   37.33 +	void *p;
   37.34 +	char *string;
   37.35 +	char **list;
   37.36 +	uint_32 *flags;
   37.37 +	uint_32 integer;
   37.38 +};
   37.39 +
   37.40 +static enum razor_version_relation
   37.41 +rpm_to_razor_flags (uint_32 flags)
   37.42 +{
   37.43 +	switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
   37.44 +	case RPMSENSE_LESS:
   37.45 +		return RAZOR_VERSION_LESS;
   37.46 +	case RPMSENSE_LESS|RPMSENSE_EQUAL:
   37.47 +		return RAZOR_VERSION_LESS_OR_EQUAL;
   37.48 +	case RPMSENSE_EQUAL:
   37.49 +		return RAZOR_VERSION_EQUAL;
   37.50 +	case RPMSENSE_GREATER|RPMSENSE_EQUAL:
   37.51 +		return RAZOR_VERSION_GREATER_OR_EQUAL;
   37.52 +	case RPMSENSE_GREATER:
   37.53 +		return RAZOR_VERSION_GREATER;
   37.54 +	}
   37.55 +
   37.56 +	/* FIXME? */
   37.57 +	return RAZOR_VERSION_EQUAL;
   37.58 +}
   37.59 +
   37.60 +static void
   37.61 +add_properties(struct razor_importer *importer,
   37.62 +	       enum razor_property_type property_type,
   37.63 +	       Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
   37.64 +{
   37.65 +	union rpm_entry names, versions, flags;
   37.66 +	int_32 i, type, count;
   37.67 +
   37.68 +	headerGetEntry(h, name_tag, &type, &names.p, &count);
   37.69 +	headerGetEntry(h, version_tag, &type, &versions.p, &count);
   37.70 +	headerGetEntry(h, flags_tag, &type, &flags.p, &count);
   37.71 +
   37.72 +	for (i = 0; i < count; i++)
   37.73 +		razor_importer_add_property(importer,
   37.74 +					    names.list[i],
   37.75 +					    rpm_to_razor_flags (flags.flags[i]),
   37.76 +					    versions.list[i],
   37.77 +					    property_type);
   37.78 +}
   37.79 +
   37.80 +struct razor_set *
   37.81 +razor_set_create_from_rpmdb(void)
   37.82 +{
   37.83 +	struct razor_importer *importer;
   37.84 +	rpmdbMatchIterator iter;
   37.85 +	Header h;
   37.86 +	int_32 type, count, i;
   37.87 +	union rpm_entry name, epoch, version, release, arch;
   37.88 +	union rpm_entry basenames, dirnames, dirindexes;
   37.89 +	char filename[PATH_MAX], evr[128], buf[16];
   37.90 +	rpmdb db;
   37.91 +
   37.92 +	rpmReadConfigFiles(NULL, NULL);
   37.93 +
   37.94 +	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
   37.95 +		fprintf(stderr, "cannot open rpm database\n");
   37.96 +		exit(1);
   37.97 +	}
   37.98 +
   37.99 +	importer = razor_importer_new();
  37.100 +
  37.101 +	iter = rpmdbInitIterator(db, 0, NULL, 0);
  37.102 +	while (h = rpmdbNextIterator(iter), h != NULL) {
  37.103 +		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
  37.104 +		headerGetEntry(h, RPMTAG_EPOCH, &type, &epoch.p, &count);
  37.105 +		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
  37.106 +		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
  37.107 +		headerGetEntry(h, RPMTAG_ARCH, &type, &arch.p, &count);
  37.108 +
  37.109 +		if (epoch.flags != NULL) {
  37.110 +			snprintf(buf, sizeof buf, "%u", *epoch.flags);
  37.111 +			razor_build_evr(evr, sizeof evr,
  37.112 +					buf, version.string, release.string);
  37.113 +		} else {
  37.114 +			razor_build_evr(evr, sizeof evr,
  37.115 +					NULL, version.string, release.string);
  37.116 +		}
  37.117 +
  37.118 +		razor_importer_begin_package(importer,
  37.119 +					     name.string, evr, arch.string);
  37.120 +
  37.121 +		add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
  37.122 +			       RPMTAG_REQUIRENAME,
  37.123 +			       RPMTAG_REQUIREVERSION,
  37.124 +			       RPMTAG_REQUIREFLAGS);
  37.125 +
  37.126 +		add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
  37.127 +			       RPMTAG_PROVIDENAME,
  37.128 +			       RPMTAG_PROVIDEVERSION,
  37.129 +			       RPMTAG_PROVIDEFLAGS);
  37.130 +
  37.131 +		add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
  37.132 +			       RPMTAG_OBSOLETENAME,
  37.133 +			       RPMTAG_OBSOLETEVERSION,
  37.134 +			       RPMTAG_OBSOLETEFLAGS);
  37.135 +
  37.136 +		add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
  37.137 +			       RPMTAG_CONFLICTNAME,
  37.138 +			       RPMTAG_CONFLICTVERSION,
  37.139 +			       RPMTAG_CONFLICTFLAGS);
  37.140 +
  37.141 +		headerGetEntry(h, RPMTAG_BASENAMES, &type,
  37.142 +			       &basenames.p, &count);
  37.143 +		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
  37.144 +			       &dirnames.p, &count);
  37.145 +		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
  37.146 +			       &dirindexes.p, &count);
  37.147 +		for (i = 0; i < count; i++) {
  37.148 +			snprintf(filename, sizeof filename, "%s%s",
  37.149 +				 dirnames.list[dirindexes.flags[i]],
  37.150 +				 basenames.list[i]);
  37.151 +			razor_importer_add_file(importer, filename);
  37.152 +		}
  37.153 +
  37.154 +		razor_importer_finish_package(importer);
  37.155 +	}
  37.156 +
  37.157 +	rpmdbClose(db);
  37.158 +
  37.159 +	return razor_importer_finish(importer);
  37.160 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/src/import-yum.c	Mon Jun 16 15:40:30 2008 -0400
    38.3 @@ -0,0 +1,337 @@
    38.4 +/*
    38.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    38.6 + * Copyright (C) 2008  Red Hat, Inc
    38.7 + *
    38.8 + * This program is free software; you can redistribute it and/or modify
    38.9 + * it under the terms of the GNU General Public License as published by
   38.10 + * the Free Software Foundation; either version 2 of the License, or
   38.11 + * (at your option) any later version.
   38.12 + *
   38.13 + * This program is distributed in the hope that it will be useful,
   38.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   38.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   38.16 + * GNU General Public License for more details.
   38.17 + *
   38.18 + * You should have received a copy of the GNU General Public License along
   38.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   38.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   38.21 + */
   38.22 +
   38.23 +#define _GNU_SOURCE
   38.24 +
   38.25 +#include <string.h>
   38.26 +#include <stdio.h>
   38.27 +#include <sys/stat.h>
   38.28 +#include <sys/mman.h>
   38.29 +#include <unistd.h>
   38.30 +#include <fcntl.h>
   38.31 +#include <errno.h>
   38.32 +
   38.33 +#include <expat.h>
   38.34 +#include <zlib.h>
   38.35 +#include "razor.h"
   38.36 +
   38.37 +/* Import a yum filelist as a razor package set. */
   38.38 +
   38.39 +enum {
   38.40 +	YUM_STATE_BEGIN,
   38.41 +	YUM_STATE_PACKAGE_NAME,
   38.42 +	YUM_STATE_PACKAGE_ARCH,
   38.43 +	YUM_STATE_CHECKSUM,
   38.44 +	YUM_STATE_REQUIRES,
   38.45 +	YUM_STATE_PROVIDES,
   38.46 +	YUM_STATE_OBSOLETES,
   38.47 +	YUM_STATE_CONFLICTS,
   38.48 +	YUM_STATE_FILE
   38.49 +};
   38.50 +
   38.51 +struct yum_context {
   38.52 +	XML_Parser primary_parser;
   38.53 +	XML_Parser filelists_parser;
   38.54 +	XML_Parser current_parser;
   38.55 +
   38.56 +	struct razor_importer *importer;
   38.57 +	struct import_property_context *current_property_context;
   38.58 +	char name[256], arch[64], buffer[512], *p;
   38.59 +	char pkgid[128];
   38.60 +	int state;
   38.61 +};
   38.62 +
   38.63 +static enum razor_version_relation
   38.64 +yum_to_razor_flags (const char *flags)
   38.65 +{
   38.66 +	/* FIXME? */
   38.67 +	if (!flags)
   38.68 +		return RAZOR_VERSION_EQUAL;
   38.69 +
   38.70 +	if (flags[0] == 'L') {
   38.71 +		if (flags[1] == 'T')
   38.72 +			return RAZOR_VERSION_LESS;
   38.73 +		else
   38.74 +			return RAZOR_VERSION_LESS_OR_EQUAL;
   38.75 +	} else if (flags[0] == 'G') {
   38.76 +		if (flags[1] == 'T')
   38.77 +			return RAZOR_VERSION_GREATER;
   38.78 +		else
   38.79 +			return RAZOR_VERSION_GREATER_OR_EQUAL;
   38.80 +	} else
   38.81 +		return RAZOR_VERSION_EQUAL;
   38.82 +}
   38.83 +
   38.84 +static void
   38.85 +yum_primary_start_element(void *data, const char *name, const char **atts)
   38.86 +{
   38.87 +	struct yum_context *ctx = data;
   38.88 +	const char *n, *epoch, *version, *release, *flags;
   38.89 +	char buffer[128];
   38.90 +	int i;
   38.91 +
   38.92 +	if (strcmp(name, "name") == 0) {
   38.93 +		ctx->state = YUM_STATE_PACKAGE_NAME;
   38.94 +		ctx->p = ctx->name;
   38.95 +	} else if (strcmp(name, "arch") == 0) {
   38.96 +		ctx->state = YUM_STATE_PACKAGE_ARCH;
   38.97 +		ctx->p = ctx->arch;
   38.98 +	} else if (strcmp(name, "version") == 0) {
   38.99 +		epoch = NULL;
  38.100 +		version = NULL;
  38.101 +		release = NULL;
  38.102 +		for (i = 0; atts[i]; i += 2) {
  38.103 +			if (strcmp(atts[i], "epoch") == 0)
  38.104 +				epoch = atts[i + 1];
  38.105 +			else if (strcmp(atts[i], "ver") == 0)
  38.106 +				version = atts[i + 1];
  38.107 +			else if (strcmp(atts[i], "rel") == 0)
  38.108 +				release = atts[i + 1];
  38.109 +		}
  38.110 +		if (version == NULL || release == NULL) {
  38.111 +			fprintf(stderr, "invalid version tag, "
  38.112 +				"missing version or  release attribute\n");
  38.113 +			return;
  38.114 +		}
  38.115 +
  38.116 +		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  38.117 +		razor_importer_begin_package(ctx->importer,
  38.118 +					     ctx->name, buffer, ctx->arch);
  38.119 +	} else if (strcmp(name, "checksum") == 0) {
  38.120 +		ctx->p = ctx->pkgid;
  38.121 +		ctx->state = YUM_STATE_CHECKSUM;
  38.122 +	} else if (strcmp(name, "rpm:requires") == 0) {
  38.123 +		ctx->state = YUM_STATE_REQUIRES;
  38.124 +	} else if (strcmp(name, "rpm:provides") == 0) {
  38.125 +		ctx->state = YUM_STATE_PROVIDES;
  38.126 +	} else if (strcmp(name, "rpm:obsoletes") == 0) {
  38.127 +		ctx->state = YUM_STATE_OBSOLETES;
  38.128 +	} else if (strcmp(name, "rpm:conflicts") == 0) {
  38.129 +		ctx->state = YUM_STATE_CONFLICTS;
  38.130 +	} else if (strcmp(name, "rpm:entry") == 0 &&
  38.131 +		   ctx->state != YUM_STATE_BEGIN) {
  38.132 +		n = NULL;
  38.133 +		epoch = NULL;
  38.134 +		version = NULL;
  38.135 +		release = NULL;
  38.136 +		flags = NULL;
  38.137 +		for (i = 0; atts[i]; i += 2) {
  38.138 +			if (strcmp(atts[i], "name") == 0)
  38.139 +				n = atts[i + 1];
  38.140 +			else if (strcmp(atts[i], "epoch") == 0)
  38.141 +				epoch = atts[i + 1];
  38.142 +			else if (strcmp(atts[i], "ver") == 0)
  38.143 +				version = atts[i + 1];
  38.144 +			else if (strcmp(atts[i], "rel") == 0)
  38.145 +				release = atts[i + 1];
  38.146 +			else if (strcmp(atts[i], "flags") == 0)
  38.147 +				flags = atts[i + 1];
  38.148 +		}
  38.149 +
  38.150 +		if (n == NULL) {
  38.151 +			fprintf(stderr, "invalid rpm:entry, "
  38.152 +				"missing name or version attributes\n");
  38.153 +			return;
  38.154 +		}
  38.155 +
  38.156 +		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  38.157 +		switch (ctx->state) {
  38.158 +		case YUM_STATE_REQUIRES:
  38.159 +			razor_importer_add_property(ctx->importer, n,
  38.160 +						    yum_to_razor_flags (flags),
  38.161 +						    buffer,
  38.162 +						    RAZOR_PROPERTY_REQUIRES);
  38.163 +			break;
  38.164 +		case YUM_STATE_PROVIDES:
  38.165 +			razor_importer_add_property(ctx->importer, n,
  38.166 +						    yum_to_razor_flags (flags),
  38.167 +						    buffer,
  38.168 +						    RAZOR_PROPERTY_PROVIDES);
  38.169 +			break;
  38.170 +		case YUM_STATE_OBSOLETES:
  38.171 +			razor_importer_add_property(ctx->importer, n,
  38.172 +						    yum_to_razor_flags (flags),
  38.173 +						    buffer,
  38.174 +						    RAZOR_PROPERTY_OBSOLETES);
  38.175 +			break;
  38.176 +		case YUM_STATE_CONFLICTS:
  38.177 +			razor_importer_add_property(ctx->importer, n,
  38.178 +						    yum_to_razor_flags (flags),
  38.179 +						    buffer,
  38.180 +						    RAZOR_PROPERTY_CONFLICTS);
  38.181 +			break;
  38.182 +		}
  38.183 +	}
  38.184 +}
  38.185 +
  38.186 +static void
  38.187 +yum_primary_end_element (void *data, const char *name)
  38.188 +{
  38.189 +	struct yum_context *ctx = data;
  38.190 +
  38.191 +	switch (ctx->state) {
  38.192 +	case YUM_STATE_PACKAGE_NAME:
  38.193 +	case YUM_STATE_PACKAGE_ARCH:
  38.194 +	case YUM_STATE_CHECKSUM:
  38.195 +	case YUM_STATE_FILE:
  38.196 +		ctx->state = YUM_STATE_BEGIN;
  38.197 +		break;
  38.198 +	}
  38.199 +
  38.200 +	if (strcmp(name, "package") == 0) {
  38.201 +		XML_StopParser(ctx->current_parser, XML_TRUE);
  38.202 +		ctx->current_parser = ctx->filelists_parser;
  38.203 +	}
  38.204 +}
  38.205 +
  38.206 +static void
  38.207 +yum_character_data (void *data, const XML_Char *s, int len)
  38.208 +{
  38.209 +	struct yum_context *ctx = data;
  38.210 +
  38.211 +	switch (ctx->state) {
  38.212 +	case YUM_STATE_PACKAGE_NAME:
  38.213 +	case YUM_STATE_PACKAGE_ARCH:
  38.214 +	case YUM_STATE_CHECKSUM:
  38.215 +	case YUM_STATE_FILE:
  38.216 +		memcpy(ctx->p, s, len);
  38.217 +		ctx->p += len;
  38.218 +		*ctx->p = '\0';
  38.219 +		break;
  38.220 +	}
  38.221 +}
  38.222 +
  38.223 +static void
  38.224 +yum_filelists_start_element(void *data, const char *name, const char **atts)
  38.225 +{
  38.226 +	struct yum_context *ctx = data;
  38.227 +	const char *pkg, *pkgid;
  38.228 +	int i;
  38.229 +
  38.230 +	if (strcmp(name, "package") == 0) {
  38.231 +		pkg = NULL;
  38.232 +		pkgid = NULL;
  38.233 +		for (i = 0; atts[i]; i += 2) {
  38.234 +			if (strcmp(atts[i], "name") == 0)
  38.235 +				pkg = atts[i + 1];
  38.236 +			else if (strcmp(atts[i], "pkgid") == 0)
  38.237 +				pkgid = atts[i + 1];
  38.238 +		}
  38.239 +		if (strcmp(pkgid, ctx->pkgid) != 0)
  38.240 +			fprintf(stderr, "primary.xml and filelists.xml "
  38.241 +				"mismatch for %s: %s vs %s",
  38.242 +				pkg, pkgid, ctx->pkgid);
  38.243 +	} else if (strcmp(name, "file") == 0) {
  38.244 +		ctx->state = YUM_STATE_FILE;
  38.245 +		ctx->p = ctx->buffer;
  38.246 +	}
  38.247 +}
  38.248 +
  38.249 +
  38.250 +static void
  38.251 +yum_filelists_end_element (void *data, const char *name)
  38.252 +{
  38.253 +	struct yum_context *ctx = data;
  38.254 +
  38.255 +	ctx->state = YUM_STATE_BEGIN;
  38.256 +	if (strcmp(name, "package") == 0) {
  38.257 +		XML_StopParser(ctx->current_parser, XML_TRUE);
  38.258 +		ctx->current_parser = ctx->primary_parser;
  38.259 +		razor_importer_finish_package(ctx->importer);
  38.260 +	} else if (strcmp(name, "file") == 0)
  38.261 +		razor_importer_add_file(ctx->importer, ctx->buffer);
  38.262 +
  38.263 +}
  38.264 +
  38.265 +#define XML_BUFFER_SIZE 4096
  38.266 +
  38.267 +struct razor_set *
  38.268 +razor_set_create_from_yum(void)
  38.269 +{
  38.270 +	struct yum_context ctx;
  38.271 +	void *buf;
  38.272 +	int len, ret;
  38.273 +	gzFile primary, filelists;
  38.274 +	XML_ParsingStatus status;
  38.275 +
  38.276 +	ctx.importer = razor_importer_new();
  38.277 +	ctx.state = YUM_STATE_BEGIN;
  38.278 +
  38.279 +	ctx.primary_parser = XML_ParserCreate(NULL);
  38.280 +	XML_SetUserData(ctx.primary_parser, &ctx);
  38.281 +	XML_SetElementHandler(ctx.primary_parser,
  38.282 +			      yum_primary_start_element,
  38.283 +			      yum_primary_end_element);
  38.284 +	XML_SetCharacterDataHandler(ctx.primary_parser,
  38.285 +				    yum_character_data);
  38.286 +
  38.287 +	ctx.filelists_parser = XML_ParserCreate(NULL);
  38.288 +	XML_SetUserData(ctx.filelists_parser, &ctx);
  38.289 +	XML_SetElementHandler(ctx.filelists_parser,
  38.290 +			      yum_filelists_start_element,
  38.291 +			      yum_filelists_end_element);
  38.292 +	XML_SetCharacterDataHandler(ctx.filelists_parser,
  38.293 +				    yum_character_data);
  38.294 +
  38.295 +	primary = gzopen("primary.xml.gz", "rb");
  38.296 +	if (primary == NULL)
  38.297 +		return NULL;
  38.298 +	filelists = gzopen("filelists.xml.gz", "rb");
  38.299 +	if (filelists == NULL)
  38.300 +		return NULL;
  38.301 +
  38.302 +	ctx.current_parser = ctx.primary_parser;
  38.303 +
  38.304 +	do {
  38.305 +		XML_GetParsingStatus(ctx.current_parser, &status);
  38.306 +		switch (status.parsing) {
  38.307 +		case XML_SUSPENDED:
  38.308 +			ret = XML_ResumeParser(ctx.current_parser);
  38.309 +			break;
  38.310 +		case XML_PARSING:
  38.311 +		case XML_INITIALIZED:
  38.312 +			buf = XML_GetBuffer(ctx.current_parser,
  38.313 +					    XML_BUFFER_SIZE);
  38.314 +			if (ctx.current_parser == ctx.primary_parser)
  38.315 +				len = gzread(primary, buf, XML_BUFFER_SIZE);
  38.316 +			else
  38.317 +				len = gzread(filelists, buf, XML_BUFFER_SIZE);
  38.318 +			if (len < 0) {
  38.319 +				fprintf(stderr,
  38.320 +					"couldn't read input: %s\n",
  38.321 +					strerror(errno));
  38.322 +				return NULL;
  38.323 +			}
  38.324 +
  38.325 +			XML_ParseBuffer(ctx.current_parser, len, len == 0);
  38.326 +			break;
  38.327 +		case XML_FINISHED:
  38.328 +			break;
  38.329 +		}
  38.330 +	} while (status.parsing != XML_FINISHED);
  38.331 +
  38.332 +
  38.333 +	XML_ParserFree(ctx.primary_parser);
  38.334 +	XML_ParserFree(ctx.filelists_parser);
  38.335 +
  38.336 +	gzclose(primary);
  38.337 +	gzclose(filelists);
  38.338 +
  38.339 +	return razor_importer_finish(ctx.importer);
  38.340 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/src/main.c	Mon Jun 16 15:40:30 2008 -0400
    39.3 @@ -0,0 +1,804 @@
    39.4 +/*
    39.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    39.6 + * Copyright (C) 2008  Red Hat, Inc
    39.7 + *
    39.8 + * This program is free software; you can redistribute it and/or modify
    39.9 + * it under the terms of the GNU General Public License as published by
   39.10 + * the Free Software Foundation; either version 2 of the License, or
   39.11 + * (at your option) any later version.
   39.12 + *
   39.13 + * This program is distributed in the hope that it will be useful,
   39.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.16 + * GNU General Public License for more details.
   39.17 + *
   39.18 + * You should have received a copy of the GNU General Public License along
   39.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   39.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   39.21 + */
   39.22 +
   39.23 +#include <stdlib.h>
   39.24 +#include <stddef.h>
   39.25 +#include <stdio.h>
   39.26 +#include <stdint.h>
   39.27 +#include <string.h>
   39.28 +#include <sys/stat.h>
   39.29 +#include <unistd.h>
   39.30 +#include <fcntl.h>
   39.31 +#include <dirent.h>
   39.32 +#include <curl/curl.h>
   39.33 +#include <fnmatch.h>
   39.34 +#include <errno.h>
   39.35 +#include "razor.h"
   39.36 +
   39.37 +static const char system_repo_filename[] = "system.repo";
   39.38 +static const char next_repo_filename[] = "system-next.repo";
   39.39 +static const char rawhide_repo_filename[] = "rawhide.repo";
   39.40 +static const char updated_repo_filename[] = "system-updated.repo";
   39.41 +static const char install_root[] = "install";
   39.42 +static const char *repo_filename = system_repo_filename;
   39.43 +static const char *yum_url;
   39.44 +
   39.45 +static int
   39.46 +command_list(int argc, const char *argv[])
   39.47 +{
   39.48 +	struct razor_set *set;
   39.49 +	struct razor_package_iterator *pi;
   39.50 +	struct razor_package *package;
   39.51 +	const char *pattern, *name, *version, *arch;
   39.52 +	int only_names = 0, i = 0;
   39.53 +
   39.54 +	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
   39.55 +		only_names = 1;
   39.56 +		i++;
   39.57 +	}
   39.58 +
   39.59 +	pattern = argv[i];
   39.60 +	set = razor_set_open(repo_filename);
   39.61 +	pi = razor_package_iterator_create(set);
   39.62 +	while (razor_package_iterator_next(pi, &package,
   39.63 +					   &name, &version, &arch)) {
   39.64 +		if (pattern && fnmatch(pattern, name, 0) != 0)
   39.65 +			continue;
   39.66 +
   39.67 +		if (only_names)
   39.68 +			printf("%s\n", name);
   39.69 +		else
   39.70 +			printf("%s-%s.%s\n", name, version, arch);
   39.71 +	}
   39.72 +	razor_package_iterator_destroy(pi);
   39.73 +	razor_set_destroy(set);
   39.74 +
   39.75 +	return 0;
   39.76 +}
   39.77 +
   39.78 +static int
   39.79 +list_properties(const char *package_name,
   39.80 +		enum razor_property_type required_type)
   39.81 +{
   39.82 +	static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
   39.83 +	struct razor_set *set;
   39.84 +	struct razor_property *property;
   39.85 +	struct razor_package *package;
   39.86 +	struct razor_property_iterator *pi;
   39.87 +	const char *name, *version;
   39.88 +	enum razor_property_type type;
   39.89 +	enum razor_version_relation relation;
   39.90 +
   39.91 +	set = razor_set_open(repo_filename);
   39.92 +	if (package_name)
   39.93 +		package = razor_set_get_package(set, package_name);
   39.94 +	else
   39.95 +		package = NULL;
   39.96 +
   39.97 +	pi = razor_property_iterator_create(set, package);
   39.98 +	while (razor_property_iterator_next(pi, &property,
   39.99 +					    &name, &relation, &version,
  39.100 +					    &type)) {
  39.101 +		if (type != required_type)
  39.102 +			continue;
  39.103 +		if (version[0] == '\0')
  39.104 +			printf("%s\n", name);
  39.105 +		else
  39.106 +			printf("%s %s %s\n", name,
  39.107 +			       relation_string[relation], version);
  39.108 +	}
  39.109 +	razor_property_iterator_destroy(pi);
  39.110 +
  39.111 +	razor_set_destroy(set);
  39.112 +
  39.113 +	return 0;
  39.114 +}
  39.115 +
  39.116 +static int
  39.117 +command_list_requires(int argc, const char *argv[])
  39.118 +{
  39.119 +	return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
  39.120 +}
  39.121 +
  39.122 +static int
  39.123 +command_list_provides(int argc, const char *argv[])
  39.124 +{
  39.125 +	return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
  39.126 +}
  39.127 +
  39.128 +static int
  39.129 +command_list_obsoletes(int argc, const char *argv[])
  39.130 +{
  39.131 +	return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
  39.132 +}
  39.133 +
  39.134 +static int
  39.135 +command_list_conflicts(int argc, const char *argv[])
  39.136 +{
  39.137 +	return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
  39.138 +}
  39.139 +
  39.140 +static int
  39.141 +command_list_files(int argc, const char *argv[])
  39.142 +{
  39.143 +	struct razor_set *set;
  39.144 +
  39.145 +	set = razor_set_open(repo_filename);
  39.146 +	if (set == NULL)
  39.147 +		return 1;
  39.148 +	razor_set_list_files(set, argv[0]);
  39.149 +	razor_set_destroy(set);
  39.150 +
  39.151 +	return 0;
  39.152 +}
  39.153 +
  39.154 +static int
  39.155 +command_list_file_packages(int argc, const char *argv[])
  39.156 +{
  39.157 +	struct razor_set *set;
  39.158 +	struct razor_package_iterator *pi;
  39.159 +	struct razor_package *package;
  39.160 +	const char *name, *version, *arch;
  39.161 +
  39.162 +	set = razor_set_open(repo_filename);
  39.163 +	if (set == NULL)
  39.164 +		return 1;
  39.165 +
  39.166 +	pi = razor_package_iterator_create_for_file(set, argv[0]);
  39.167 +	while (razor_package_iterator_next(pi, &package,
  39.168 +					   &name, &version, &arch))
  39.169 +		printf("%s-%s\n", name, version);
  39.170 +	razor_package_iterator_destroy(pi);
  39.171 +
  39.172 +	razor_set_destroy(set);
  39.173 +
  39.174 +	return 0;
  39.175 +}
  39.176 +
  39.177 +static int
  39.178 +command_list_package_files(int argc, const char *argv[])
  39.179 +{
  39.180 +	struct razor_set *set;
  39.181 +
  39.182 +	set = razor_set_open(repo_filename);
  39.183 +	if (set == NULL)
  39.184 +		return 1;
  39.185 +	razor_set_list_package_files(set, argv[0]);
  39.186 +	razor_set_destroy(set);
  39.187 +
  39.188 +	return 0;
  39.189 +}
  39.190 +
  39.191 +static void
  39.192 +list_packages_for_property(struct razor_set *set,
  39.193 +			   struct razor_property *property)
  39.194 +{
  39.195 +	struct razor_package_iterator *pi;
  39.196 +	struct razor_package *package;
  39.197 +	const char *name, *version, *arch;
  39.198 +
  39.199 +	pi = razor_package_iterator_create_for_property(set, property);
  39.200 +	while (razor_package_iterator_next(pi, &package,
  39.201 +					   &name, &version, &arch))
  39.202 +		printf("%s-%s.%s\n", name, version, arch);
  39.203 +	razor_package_iterator_destroy(pi);
  39.204 +}
  39.205 +
  39.206 +static int
  39.207 +list_property_packages(const char *ref_name,
  39.208 +		       const char *ref_version,
  39.209 +		       enum razor_property_type ref_type)
  39.210 +{
  39.211 +	struct razor_set *set;
  39.212 +	struct razor_property *property;
  39.213 +	struct razor_property_iterator *pi;
  39.214 +	const char *name, *version;
  39.215 +	enum razor_property_type type;
  39.216 +	enum razor_version_relation relation;
  39.217 +
  39.218 +	if (ref_name == NULL)
  39.219 +		return 0;
  39.220 +
  39.221 +	set = razor_set_open(repo_filename);
  39.222 +	if (set == NULL)
  39.223 +		return 1;
  39.224 +
  39.225 +	pi = razor_property_iterator_create(set, NULL);
  39.226 +	while (razor_property_iterator_next(pi, &property,
  39.227 +					    &name, &relation, &version,
  39.228 +					    &type)) {
  39.229 +		if (strcmp(ref_name, name) != 0)
  39.230 +			continue;
  39.231 +		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
  39.232 +		    strcmp(ref_version, version) != 0)
  39.233 +			continue;
  39.234 +		if (ref_type != type)
  39.235 +			continue;
  39.236 +
  39.237 +		list_packages_for_property(set, property);
  39.238 +	}
  39.239 +	razor_property_iterator_destroy(pi);
  39.240 +
  39.241 +	return 0;
  39.242 +}
  39.243 +
  39.244 +static int
  39.245 +command_what_requires(int argc, const char *argv[])
  39.246 +{
  39.247 +	return list_property_packages(argv[0], argv[1],
  39.248 +				      RAZOR_PROPERTY_REQUIRES);
  39.249 +}
  39.250 +
  39.251 +static int
  39.252 +command_what_provides(int argc, const char *argv[])
  39.253 +{
  39.254 +	return list_property_packages(argv[0], argv[1],
  39.255 +				      RAZOR_PROPERTY_PROVIDES);
  39.256 +}
  39.257 +
  39.258 +static int
  39.259 +show_progress(void *clientp,
  39.260 +	      double dltotal, double dlnow, double ultotal, double ulnow)
  39.261 +{
  39.262 +	const char *file = clientp;
  39.263 +
  39.264 +	if (!dlnow < dltotal)
  39.265 +		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
  39.266 +			file, (int) dlnow / 1024, (int) dltotal / 1024);
  39.267 +
  39.268 +	return 0;
  39.269 +}
  39.270 +
  39.271 +static int
  39.272 +download_if_missing(const char *url, const char *file)
  39.273 +{
  39.274 +	CURL *curl;
  39.275 +	struct stat buf;
  39.276 +	char error[256];
  39.277 +	FILE *fp;
  39.278 +	CURLcode res;
  39.279 +	long response;
  39.280 +
  39.281 +	curl = curl_easy_init();
  39.282 +	if (curl == NULL)
  39.283 +		return 1;
  39.284 +
  39.285 +	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
  39.286 +	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
  39.287 +	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
  39.288 +	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
  39.289 +
  39.290 +	if (stat(file, &buf) < 0) {
  39.291 +		fp = fopen(file, "w");
  39.292 +		if (fp == NULL) {
  39.293 +			fprintf(stderr,
  39.294 +				"failed to open %s for writing\n", file);
  39.295 +			return -1;
  39.296 +		}
  39.297 +		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
  39.298 +		curl_easy_setopt(curl, CURLOPT_URL, url);
  39.299 +		res = curl_easy_perform(curl);
  39.300 +		fclose(fp);
  39.301 +		if (res != CURLE_OK) {
  39.302 +			fprintf(stderr, "curl error: %s\n", error);
  39.303 +			unlink(file);
  39.304 +			return -1;
  39.305 +		}
  39.306 +		res = curl_easy_getinfo(curl,
  39.307 +					CURLINFO_RESPONSE_CODE, &response);
  39.308 +		if (res != CURLE_OK) {
  39.309 +			fprintf(stderr, "curl error: %s\n", error);
  39.310 +                        unlink(file);
  39.311 +                        return -1;
  39.312 +		}
  39.313 +		if (response != 200) {
  39.314 +			fprintf(stderr, " - failed %ld\n", response);
  39.315 +                        unlink(file);
  39.316 +                        return -1;
  39.317 +		}
  39.318 +		fprintf(stderr, "\n");
  39.319 +	}
  39.320 +
  39.321 +	curl_easy_cleanup(curl);
  39.322 +
  39.323 +	return 0;
  39.324 +}
  39.325 +
  39.326 +#define YUM_URL "http://download.fedora.redhat.com" \
  39.327 +	"/pub/fedora/linux/development/i386/os"
  39.328 +
  39.329 +static int
  39.330 +command_import_yum(int argc, const char *argv[])
  39.331 +{
  39.332 +	struct razor_set *set;
  39.333 +	char buffer[512];
  39.334 +
  39.335 +	printf("downloading from %s.\n", yum_url);
  39.336 +	snprintf(buffer, sizeof buffer,
  39.337 +		 "%s/repodata/primary.xml.gz", yum_url);
  39.338 +	if (download_if_missing(buffer, "primary.xml.gz") < 0)
  39.339 +		return -1;
  39.340 +	snprintf(buffer, sizeof buffer,
  39.341 +		 "%s/repodata/filelists.xml.gz", yum_url);
  39.342 +	if (download_if_missing(buffer, "filelists.xml.gz") < 0)
  39.343 +		return -1;
  39.344 +
  39.345 +	set = razor_set_create_from_yum();
  39.346 +	if (set == NULL)
  39.347 +		return 1;
  39.348 +	razor_set_write(set, rawhide_repo_filename);
  39.349 +	razor_set_destroy(set);
  39.350 +	printf("wrote %s\n", rawhide_repo_filename);
  39.351 +
  39.352 +	return 0;
  39.353 +}
  39.354 +
  39.355 +static int
  39.356 +command_import_rpmdb(int argc, const char *argv[])
  39.357 +{
  39.358 +	struct razor_set *set;
  39.359 +
  39.360 +	set = razor_set_create_from_rpmdb();
  39.361 +	if (set == NULL)
  39.362 +		return 1;
  39.363 +	razor_set_write(set, repo_filename);
  39.364 +	razor_set_destroy(set);
  39.365 +	printf("wrote %s\n", repo_filename);
  39.366 +
  39.367 +	return 0;
  39.368 +}
  39.369 +
  39.370 +static int
  39.371 +mark_packages_for_update(struct razor_transaction *trans,
  39.372 +			 struct razor_set *set, const char *pattern)
  39.373 +{
  39.374 +	struct razor_package_iterator *pi;
  39.375 +	struct razor_package *package;
  39.376 +	const char *name, *version, *arch;
  39.377 +	int matches = 0;
  39.378 +
  39.379 +	pi = razor_package_iterator_create(set);
  39.380 +	while (razor_package_iterator_next(pi, &package,
  39.381 +					   &name, &version, &arch)) {
  39.382 +		if (pattern && fnmatch(pattern, name, 0) == 0) {
  39.383 +			razor_transaction_update_package(trans, package);
  39.384 +			matches++;
  39.385 +		}
  39.386 +	}
  39.387 +	razor_package_iterator_destroy(pi);
  39.388 +
  39.389 +	return matches;
  39.390 +}
  39.391 +
  39.392 +static int
  39.393 +mark_packages_for_removal(struct razor_transaction *trans,
  39.394 +			  struct razor_set *set, const char *pattern)
  39.395 +{
  39.396 +	struct razor_package_iterator *pi;
  39.397 +	struct razor_package *package;
  39.398 +	const char *name, *version, *arch;
  39.399 +	int matches = 0;
  39.400 +
  39.401 +	pi = razor_package_iterator_create(set);
  39.402 +	while (razor_package_iterator_next(pi, &package,
  39.403 +					   &name, &version, &arch)) {
  39.404 +		if (pattern && fnmatch(pattern, name, 0) == 0) {
  39.405 +			razor_transaction_remove_package(trans, package);
  39.406 +			matches++;
  39.407 +		}
  39.408 +	}
  39.409 +	razor_package_iterator_destroy(pi);
  39.410 +
  39.411 +	return matches;
  39.412 +}
  39.413 +
  39.414 +static int
  39.415 +command_update(int argc, const char *argv[])
  39.416 +{
  39.417 +	struct razor_set *set, *upstream;
  39.418 +	struct razor_transaction *trans;
  39.419 +	int i, errors;
  39.420 +
  39.421 +	set = razor_set_open(repo_filename);
  39.422 +	upstream = razor_set_open(rawhide_repo_filename);
  39.423 +	if (set == NULL || upstream == NULL)
  39.424 +		return 1;
  39.425 +
  39.426 +	trans = razor_transaction_create(set, upstream);
  39.427 +	if (argc == 0)
  39.428 +		razor_transaction_update_all(trans);
  39.429 +	for (i = 0; i < argc; i++) {
  39.430 +		if (mark_packages_for_update(trans, set, argv[i]) == 0) {
  39.431 +			fprintf(stderr, "no match for %s\n", argv[i]);
  39.432 +			return 1;
  39.433 +		}
  39.434 +	}
  39.435 +
  39.436 +	errors = razor_transaction_resolve(trans);
  39.437 +	if (errors)
  39.438 +		return 1;
  39.439 +
  39.440 +	set = razor_transaction_finish(trans);
  39.441 +	razor_set_write(set, updated_repo_filename);
  39.442 +	razor_set_destroy(set);
  39.443 +	razor_set_destroy(upstream);
  39.444 +	printf("wrote system-updated.repo\n");
  39.445 +
  39.446 +	return 0;
  39.447 +}
  39.448 +
  39.449 +static int
  39.450 +command_remove(int argc, const char *argv[])
  39.451 +{
  39.452 +	struct razor_set *set, *upstream;
  39.453 +	struct razor_transaction *trans;
  39.454 +	int i, errors;
  39.455 +
  39.456 +	set = razor_set_open(repo_filename);
  39.457 +	if (set == NULL)
  39.458 +		return 1;
  39.459 +
  39.460 +	upstream = razor_set_create();
  39.461 +	trans = razor_transaction_create(set, upstream);
  39.462 +	for (i = 0; i < argc; i++) {
  39.463 +		if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
  39.464 +			fprintf(stderr, "no match for %s\n", argv[i]);
  39.465 +			return 1;
  39.466 +		}
  39.467 +	}
  39.468 +
  39.469 +	errors = razor_transaction_resolve(trans);
  39.470 +	if (errors)
  39.471 +		return 1;
  39.472 +
  39.473 +	set = razor_transaction_finish(trans);
  39.474 +	razor_set_write(set, updated_repo_filename);
  39.475 +	razor_set_destroy(set);
  39.476 +	razor_set_destroy(upstream);
  39.477 +	printf("wrote system-updated.repo\n");
  39.478 +
  39.479 +	return 0;
  39.480 +}
  39.481 +
  39.482 +static void
  39.483 +print_diff(const char *name,
  39.484 +	   const char *old_version, const char *new_version, const char *arch,
  39.485 +	   void *data)
  39.486 +{
  39.487 +	if (old_version)
  39.488 +		printf("removing %s %s\n", name, old_version);
  39.489 +	else
  39.490 +		printf("install %s %s\n", name, new_version);
  39.491 +}
  39.492 +
  39.493 +static int
  39.494 +command_diff(int argc, const char *argv[])
  39.495 +{
  39.496 +	struct razor_set *set, *updated;
  39.497 +
  39.498 +	set = razor_set_open(repo_filename);
  39.499 +	updated = razor_set_open(updated_repo_filename);
  39.500 +	if (set == NULL || updated == NULL)
  39.501 +		return 1;
  39.502 +
  39.503 +	razor_set_diff(set, updated, print_diff, NULL);
  39.504 +
  39.505 +	razor_set_destroy(set);
  39.506 +	razor_set_destroy(updated);
  39.507 +
  39.508 +	return 0;
  39.509 +}
  39.510 +
  39.511 +static int
  39.512 +command_import_rpms(int argc, const char *argv[])
  39.513 +{
  39.514 +	DIR *dir;
  39.515 +	struct dirent *de;
  39.516 +	struct razor_importer *importer;
  39.517 +	struct razor_set *set;
  39.518 +	struct razor_rpm *rpm;
  39.519 +	int len;
  39.520 +	char filename[256];
  39.521 +	const char *dirname = argv[0];
  39.522 +
  39.523 +	if (dirname == NULL) {
  39.524 +		fprintf(stderr, "usage: razor import-rpms DIR\n");
  39.525 +		return -1;
  39.526 +	}
  39.527 +
  39.528 +	dir = opendir(dirname);
  39.529 +	if (dir == NULL) {
  39.530 +		fprintf(stderr, "couldn't read dir %s\n", dirname);
  39.531 +		return -1;
  39.532 +	}
  39.533 +
  39.534 +	importer = razor_importer_new();
  39.535 +
  39.536 +	while (de = readdir(dir), de != NULL) {
  39.537 +		len = strlen(de->d_name);
  39.538 +		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
  39.539 +		    continue;
  39.540 +		snprintf(filename, sizeof filename,
  39.541 +			 "%s/%s", dirname, de->d_name);
  39.542 +		rpm = razor_rpm_open(filename);
  39.543 +		if (rpm == NULL) {
  39.544 +			fprintf(stderr,
  39.545 +				"failed to open rpm \"%s\"\n", filename);
  39.546 +			continue;
  39.547 +		}
  39.548 +		if (razor_importer_add_rpm(importer, rpm)) {
  39.549 +			fprintf(stderr, "couldn't import %s\n", filename);
  39.550 +			break;
  39.551 +		}
  39.552 +		razor_rpm_close(rpm);
  39.553 +	}
  39.554 +
  39.555 +	if (de != NULL) {
  39.556 +		razor_importer_destroy(importer);
  39.557 +		return -1;
  39.558 +	}
  39.559 +
  39.560 +	set = razor_importer_finish(importer);
  39.561 +
  39.562 +	razor_set_write(set, repo_filename);
  39.563 +	razor_set_destroy(set);
  39.564 +	printf("wrote %s\n", repo_filename);
  39.565 +
  39.566 +	return 0;
  39.567 +}
  39.568 +
  39.569 +static void
  39.570 +download_package(const char *name,
  39.571 +		 const char *old_version,
  39.572 +		 const char *new_version,
  39.573 +		 const char *arch,
  39.574 +		 void *data)
  39.575 +{
  39.576 +	char file[PATH_MAX], url[256];
  39.577 +	const char *v;
  39.578 +	int *errors = data;
  39.579 +
  39.580 +	if (old_version)
  39.581 +		return;
  39.582 +
  39.583 +	/* Skip epoch */
  39.584 +	v = strchr(new_version, ':');
  39.585 +	if (v != NULL)
  39.586 +		v = v + 1;
  39.587 +	else
  39.588 +		v = new_version;
  39.589 +
  39.590 +	snprintf(url, sizeof url,
  39.591 +		 "%s/Packages/%s-%s.%s.rpm", yum_url, name, v, arch);
  39.592 +	snprintf(file, sizeof file,
  39.593 +		 "rpms/%s-%s.%s.rpm", name, v, arch);
  39.594 +	if (download_if_missing(url, file) < 0)
  39.595 +		(*errors)++;
  39.596 +}
  39.597 +
  39.598 +static void
  39.599 +install_package(const char *name,
  39.600 +		const char *old_version,
  39.601 +		const char *new_version,
  39.602 +		const char *arch,
  39.603 +		void *data)
  39.604 +{
  39.605 +	const char *v, *root = data;
  39.606 +	char file[PATH_MAX];
  39.607 +	struct razor_rpm *rpm;
  39.608 +
  39.609 +	if (old_version) {
  39.610 +		printf("removing %s %s not handled\n", name, old_version);
  39.611 +		return;
  39.612 +	}
  39.613 +
  39.614 +	/* Skip epoch */
  39.615 +	v = strchr(new_version, ':');
  39.616 +	if (v != NULL)
  39.617 +		v = v + 1;
  39.618 +	else
  39.619 +		v = new_version;
  39.620 +
  39.621 +	printf("install %s %s\n", name, v);
  39.622 +	snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
  39.623 +
  39.624 + 	rpm = razor_rpm_open(file);
  39.625 +	if (rpm == NULL) {
  39.626 +		fprintf(stderr, "failed to open rpm %s\n", file);
  39.627 +		return;
  39.628 +	}
  39.629 +	if (razor_rpm_install(rpm, root) < 0) {
  39.630 +		fprintf(stderr,
  39.631 +			"failed to install rpm %s\n", file);
  39.632 +		return;
  39.633 +	}
  39.634 +	razor_rpm_close(rpm);
  39.635 +}
  39.636 +
  39.637 +static int
  39.638 +command_install(int argc, const char *argv[])
  39.639 +{
  39.640 +	struct razor_root *root;
  39.641 +	struct razor_set *upstream, *next;
  39.642 +	struct razor_transaction *trans;
  39.643 +	int i = 0, errors, dependencies = 1;
  39.644 +
  39.645 +	if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
  39.646 +		dependencies = 0;
  39.647 +		i++;
  39.648 +	}
  39.649 +
  39.650 +	root = razor_root_open(install_root, RAZOR_ROOT_OPEN_WRITE);
  39.651 +	upstream = razor_set_open(rawhide_repo_filename);
  39.652 +	trans = razor_root_create_transaction(root, upstream);
  39.653 +
  39.654 +	for (; i < argc; i++) {
  39.655 +		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
  39.656 +			fprintf(stderr, "no package matched %s\n", argv[i]);
  39.657 +			razor_root_close(root);
  39.658 +			return 1;
  39.659 +		}
  39.660 +	}
  39.661 +
  39.662 +	if (dependencies) {
  39.663 +		errors = razor_transaction_resolve(trans);
  39.664 +		if (errors) {
  39.665 +			razor_root_close(root);
  39.666 +			return 1;
  39.667 +		}
  39.668 +	}
  39.669 +
  39.670 +	next = razor_transaction_finish(trans);
  39.671 +
  39.672 +	razor_root_update(root, next);
  39.673 +
  39.674 +	if (mkdir("rpms", 0777) && errno != EEXIST) {
  39.675 +		fprintf(stderr, "failed to create rpms directory.\n");
  39.676 +		razor_root_close(root);
  39.677 +		return 1;
  39.678 +	}
  39.679 +
  39.680 +	razor_root_diff(root, download_package, &errors);
  39.681 +	if (errors > 0) {
  39.682 +		fprintf(stderr, "failed to download %d packages\n", errors);
  39.683 +		razor_root_close(root);
  39.684 +                return 1;
  39.685 +        }
  39.686 +
  39.687 +	/* FIXME: We need to figure out the right install order here,
  39.688 +	 * so the post and pre scripts can run. */
  39.689 +	razor_root_diff(root, install_package, (void *) root);
  39.690 +
  39.691 +	razor_set_destroy(next);
  39.692 +	razor_set_destroy(upstream);
  39.693 +
  39.694 +	return razor_root_commit(root);
  39.695 +}
  39.696 +
  39.697 +static int
  39.698 +command_init(int argc, const char *argv[])
  39.699 +{
  39.700 +	return razor_root_create(install_root);
  39.701 +}
  39.702 +
  39.703 +static int
  39.704 +command_download(int argc, const char *argv[])
  39.705 +{
  39.706 +	struct razor_set *set;
  39.707 +	struct razor_package_iterator *pi;
  39.708 +	struct razor_package *package;
  39.709 +	const char *pattern = argv[0], *name, *version, *arch;
  39.710 +	char url[256], file[256];
  39.711 +	int matches = 0;
  39.712 +
  39.713 +	if (mkdir("rpms", 0777) && errno != EEXIST) {
  39.714 +		fprintf(stderr, "failed to create rpms directory.\n");
  39.715 +		return 1;
  39.716 +	}
  39.717 +
  39.718 +	set = razor_set_open(rawhide_repo_filename);
  39.719 +	pi = razor_package_iterator_create(set);
  39.720 +	while (razor_package_iterator_next(pi, &package,
  39.721 +					   &name, &version, &arch)) {
  39.722 +		if (pattern && fnmatch(pattern, name, 0) != 0)
  39.723 +			continue;
  39.724 +
  39.725 +		matches++;
  39.726 +		snprintf(url, sizeof url,
  39.727 +			 "%s/Packages/%s-%s.%s.rpm",
  39.728 +			 yum_url, name, version, arch);
  39.729 +		snprintf(file, sizeof file,
  39.730 +			 "rpms/%s-%s.%s.rpm", name, version, arch);
  39.731 +		download_if_missing(url, file);
  39.732 +	}
  39.733 +	razor_package_iterator_destroy(pi);
  39.734 +	razor_set_destroy(set);
  39.735 +
  39.736 +	if (matches == 0)
  39.737 +		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
  39.738 +	else if (matches == 1)
  39.739 +		fprintf(stderr, "downloaded 1 package\n");
  39.740 +	else
  39.741 +		fprintf(stderr, "downloaded %d packages\n", matches);
  39.742 +
  39.743 +	return 0;
  39.744 +}
  39.745 +
  39.746 +static struct {
  39.747 +	const char *name;
  39.748 +	const char *description;
  39.749 +	int (*func)(int argc, const char *argv[]);
  39.750 +} razor_commands[] = {
  39.751 +	{ "list", "list all packages", command_list },
  39.752 +	{ "list-requires", "list all requires for the given package", command_list_requires },
  39.753 +	{ "list-provides", "list all provides for the given package", command_list_provides },
  39.754 +	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
  39.755 +	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
  39.756 +	{ "list-files", "list files for package set", command_list_files },
  39.757 +	{ "list-file-packages", "list packages owning file", command_list_file_packages },
  39.758 +	{ "list-package-files", "list files in package", command_list_package_files },
  39.759 +	{ "what-requires", "list the packages that have the given requires", command_what_requires },
  39.760 +	{ "what-provides", "list the packages that have the given provides", command_what_provides },
  39.761 +	{ "import-yum", "import yum metadata files", command_import_yum },
  39.762 +	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
  39.763 +	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
  39.764 +	{ "update", "update all or specified packages", command_update },
  39.765 +	{ "remove", "remove specified packages", command_remove },
  39.766 +	{ "diff", "show diff between two package sets", command_diff },
  39.767 +	{ "install", "install rpm", command_install },
  39.768 +	{ "init", "init razor root", command_init },
  39.769 +	{ "download", "download packages", command_download }
  39.770 +};
  39.771 +
  39.772 +static int
  39.773 +usage(void)
  39.774 +{
  39.775 +	int i;
  39.776 +
  39.777 +	printf("usage:\n");
  39.778 +	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  39.779 +		printf("  %-20s%s\n",
  39.780 +		       razor_commands[i].name, razor_commands[i].description);
  39.781 +
  39.782 +	return 1;
  39.783 +}
  39.784 +
  39.785 +int
  39.786 +main(int argc, const char *argv[])
  39.787 +{
  39.788 +	char *repo;
  39.789 +	int i;
  39.790 +
  39.791 +	repo = getenv("RAZOR_REPO");
  39.792 +	if (repo != NULL)
  39.793 +		repo_filename = repo;
  39.794 +
  39.795 +	yum_url = getenv("YUM_URL");
  39.796 +	if (yum_url == NULL)
  39.797 +		yum_url = YUM_URL;
  39.798 +
  39.799 +	if (argc < 2)
  39.800 +		return usage();
  39.801 +
  39.802 +	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  39.803 +		if (strcmp(razor_commands[i].name, argv[1]) == 0)
  39.804 +			return razor_commands[i].func(argc - 2, argv + 2);
  39.805 +
  39.806 +	return usage();
  39.807 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/src/rpm.c	Mon Jun 16 15:40:30 2008 -0400
    40.3 @@ -0,0 +1,897 @@
    40.4 +/*
    40.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    40.6 + * Copyright (C) 2008  Red Hat, Inc
    40.7 + *
    40.8 + * This program is free software; you can redistribute it and/or modify
    40.9 + * it under the terms of the GNU General Public License as published by
   40.10 + * the Free Software Foundation; either version 2 of the License, or
   40.11 + * (at your option) any later version.
   40.12 + *
   40.13 + * This program is distributed in the hope that it will be useful,
   40.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   40.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40.16 + * GNU General Public License for more details.
   40.17 + *
   40.18 + * You should have received a copy of the GNU General Public License along
   40.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   40.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   40.21 + */
   40.22 +
   40.23 +#include <stdlib.h>
   40.24 +#include <string.h>
   40.25 +#include <stdio.h>
   40.26 +#include <dirent.h>
   40.27 +#include "razor.h"
   40.28 +
   40.29 +enum option_type {
   40.30 +	OPTION_LAST,
   40.31 +	OPTION_GROUP,
   40.32 +	OPTION_BOOL,
   40.33 +	OPTION_STRING
   40.34 +};
   40.35 +
   40.36 +struct option {
   40.37 +	enum option_type type;
   40.38 +	const char *name;
   40.39 +	char short_name;
   40.40 +	const char *arg_name;
   40.41 +	const char *description;
   40.42 +	void *data;
   40.43 +};
   40.44 +
   40.45 +/* A note about all these options: rpm allows options to mean
   40.46 + * different things depending on what other options are present on the
   40.47 + * command line.  For example, if -q or --query is present, -i no
   40.48 + * longer means install, but info.  The way we handle this is by
   40.49 + * setting all the options that may match (ie if -i is given we set
   40.50 + * install and info), and then look at the relevent one depending on
   40.51 + * what else in on the command line. */
   40.52 +
   40.53 +static int option_all, option_whatrequires, option_whatprovides;
   40.54 +static int option_package;
   40.55 +
   40.56 +static const struct option query_options[] = {
   40.57 +	{ OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
   40.58 +	{ OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
   40.59 +	{ OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
   40.60 +	{ OPTION_BOOL, "list", 0, NULL, "list files in package", NULL },
   40.61 +	{ OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
   40.62 +	{ OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
   40.63 +	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   40.64 +	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   40.65 +	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   40.66 +	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   40.67 +	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   40.68 +	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   40.69 +	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   40.70 +	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   40.71 +	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
   40.72 +	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   40.73 +	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   40.74 +	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   40.75 +	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
   40.76 +	{ }
   40.77 +};
   40.78 +
   40.79 +static int option_nodeps;
   40.80 +
   40.81 +static const struct option verify_options[] = {
   40.82 +	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
   40.83 +	{ OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
   40.84 +	{ OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", &option_nodeps },
   40.85 +	{ OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
   40.86 +	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   40.87 +	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   40.88 +	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   40.89 +	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   40.90 +	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   40.91 +	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   40.92 +	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   40.93 +	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   40.94 +	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
   40.95 +	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   40.96 +	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   40.97 +	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   40.98 +	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
   40.99 +	{ }
  40.100 +};
  40.101 +
  40.102 +static const struct option ftw_options[] = {
  40.103 +	{ OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
  40.104 +	{ OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
  40.105 +	{ OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
  40.106 +	{ OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
  40.107 +	{ OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
  40.108 +	{ OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
  40.109 +	{ OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
  40.110 +	{ OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
  40.111 +	{ }
  40.112 +};
  40.113 +
  40.114 +static const struct option signature_options[] = {
  40.115 +	{ OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
  40.116 +	{ OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
  40.117 +	{ OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
  40.118 +	{ OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
  40.119 +	{ OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
  40.120 +	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  40.121 +	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
  40.122 +	{ }
  40.123 +};
  40.124 +
  40.125 +static int option_initdb;
  40.126 +
  40.127 +static const struct option database_options[] = {
  40.128 +	{ OPTION_BOOL, "initdb", 0, NULL, "initialize database", &option_initdb },
  40.129 +	{ OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
  40.130 +	{ }
  40.131 +};
  40.132 +
  40.133 +static int option_erase, option_install, option_upgrade, option_justdb;
  40.134 +static int option_test;
  40.135 +
  40.136 +static const struct option install_options[] = {
  40.137 +	{ OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
  40.138 +	{ OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
  40.139 +	{ OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
  40.140 +	{ OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
  40.141 +	{ OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
  40.142 +	{ OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
  40.143 +	{ OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
  40.144 +	{ OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
  40.145 +	{ OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
  40.146 +	{ OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
  40.147 +	{ OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
  40.148 +	{ OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
  40.149 +	{ OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
  40.150 +	{ OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
  40.151 +	{ OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
  40.152 +	{ OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", &option_justdb, },
  40.153 +	{ OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", &option_nodeps, },
  40.154 +	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
  40.155 +	{ OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
  40.156 +	{ OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
  40.157 +	{ OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
  40.158 +	{ OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
  40.159 +	{ OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
  40.160 +	{ OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
  40.161 +	{ OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
  40.162 +	{ OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
  40.163 +	{ OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
  40.164 +	{ OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
  40.165 +	{ OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
  40.166 +	{ OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
  40.167 +	{ OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", &option_test },
  40.168 +	{ OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
  40.169 +	{ }
  40.170 +};
  40.171 +
  40.172 +static int option_version;
  40.173 +static const char *option_root = "install";
  40.174 +
  40.175 +static const struct option common_options[] = {
  40.176 +	{ OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
  40.177 +	{ OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
  40.178 +	{ OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  40.179 +	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  40.180 +	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
  40.181 +	{ OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  40.182 +	{ OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", &option_root },
  40.183 +	{ OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
  40.184 +	{ OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
  40.185 +	{ OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
  40.186 +	{ OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
  40.187 +	{ OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
  40.188 +	{ }
  40.189 +};
  40.190 +
  40.191 +static int option_conflicts, option_obsoletes, option_requires;
  40.192 +static int option_provides, option_info, option_changelog;
  40.193 +
  40.194 +static const struct option alias_options[] = {
  40.195 +	{ OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
  40.196 +	{ OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
  40.197 +	{ OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
  40.198 +	{ OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
  40.199 +	{ OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
  40.200 +	{ OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
  40.201 +	{ OPTION_BOOL, "requires", 0, NULL, "list capabilities required by package(s)", &option_requires, },
  40.202 +	{ OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
  40.203 +	{ OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
  40.204 +	{ OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
  40.205 +	{ OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
  40.206 +	{ OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
  40.207 +	{ OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
  40.208 +	{ OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
  40.209 +	{ OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
  40.210 +	{ OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
  40.211 +	{ OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
  40.212 +	{ OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
  40.213 +	{ OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
  40.214 +	{ OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
  40.215 +	{ OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
  40.216 +	{ OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
  40.217 +	{ OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
  40.218 +	{ OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
  40.219 +	{ OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
  40.220 +	{ OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
  40.221 +	{ }
  40.222 +};
  40.223 +
  40.224 +static int option_help, option_usage;
  40.225 +
  40.226 +static const struct option help_options[] = {
  40.227 +	{ OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
  40.228 +	{ OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
  40.229 +	{ }
  40.230 +};
  40.231 +
  40.232 +static int option_query, option_verify;
  40.233 +
  40.234 +static const struct option rpm_options[] = {
  40.235 +	{ OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
  40.236 +	{ OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
  40.237 +	{ OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
  40.238 +	{ OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
  40.239 +	{ OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
  40.240 +	{ OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
  40.241 +	{ OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
  40.242 +	{ OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
  40.243 +	{ OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
  40.244 +	{ OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
  40.245 +	{ OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
  40.246 +	{ }
  40.247 +};
  40.248 +
  40.249 +static const char system_repo_filename[] = "system.repo";
  40.250 +static const char *repo_filename = system_repo_filename;
  40.251 +
  40.252 +static void
  40.253 +command_initdb(int argc, const char *argv[])
  40.254 +{
  40.255 +	razor_root_create(option_root);
  40.256 +}
  40.257 +
  40.258 +static struct razor_property *
  40.259 +add_property_packages(struct razor_set *set,
  40.260 +		      struct razor_package_query *query,
  40.261 +		      const char *ref_name,
  40.262 +		      const char *ref_version,
  40.263 +		      enum razor_property_type ref_type)
  40.264 +{
  40.265 +	struct razor_property *property;
  40.266 +	struct razor_property_iterator *pi;
  40.267 +	struct razor_package_iterator *pkgi;
  40.268 +	const char *name, *version;
  40.269 +	enum razor_property_type type;
  40.270 +	enum razor_version_relation relation;
  40.271 +
  40.272 +	pi = razor_property_iterator_create(set, NULL);
  40.273 +	while (razor_property_iterator_next(pi, &property, &name,
  40.274 +					    &relation, &version, &type)) {
  40.275 +		if (strcmp(ref_name, name) != 0)
  40.276 +			continue;
  40.277 +		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
  40.278 +		    strcmp(ref_version, version) != 0)
  40.279 +			continue;
  40.280 +		if (ref_type != type)
  40.281 +			continue;
  40.282 +
  40.283 +		pkgi = razor_package_iterator_create_for_property(set,
  40.284 +								  property);
  40.285 +		razor_package_query_add_iterator(query, pkgi);
  40.286 +		razor_package_iterator_destroy(pkgi);
  40.287 +	}
  40.288 +	razor_property_iterator_destroy(pi);
  40.289 +
  40.290 +	return property;
  40.291 +}
  40.292 +
  40.293 +static int
  40.294 +strcmpp(const void *p1, const void *p2)
  40.295 +{
  40.296 +	return strcmp(*(char * const *) p1, *(char * const *) p2);
  40.297 +}
  40.298 +
  40.299 +static void
  40.300 +add_command_line_packages(struct razor_set *set,
  40.301 +			  struct razor_package_query *query,
  40.302 +			  int argc, const char **argv)
  40.303 +{
  40.304 +	struct razor_package *package;
  40.305 +	struct razor_package_iterator *pi;
  40.306 +	const char *name, *version, *arch;
  40.307 +	int i, cmp, errors;
  40.308 +
  40.309 +	qsort(argv, argc, sizeof(*argv), strcmpp);
  40.310 +	i = 0;
  40.311 +	errors = 0;
  40.312 +
  40.313 +	pi = razor_package_iterator_create(set);
  40.314 +
  40.315 +	while (razor_package_iterator_next(pi, &package,
  40.316 +					   &name, &version, &arch)) {
  40.317 +		while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
  40.318 +			fprintf(stderr, "error: package %s is not installed\n",
  40.319 +				argv[i]);
  40.320 +			errors++;
  40.321 +			i++;
  40.322 +		}
  40.323 +
  40.324 +		if (cmp == 0) {
  40.325 +			razor_package_query_add_package(query, package);
  40.326 +			i++;
  40.327 +		}
  40.328 +	}
  40.329 +
  40.330 +	razor_package_iterator_destroy(pi);
  40.331 +
  40.332 +	if (errors)
  40.333 +		exit(1);
  40.334 +}
  40.335 +
  40.336 +static struct razor_package_iterator *
  40.337 +get_query_packages(struct razor_set *set, int argc, const char *argv[])
  40.338 +{
  40.339 +	struct razor_package_query *query;
  40.340 +	struct razor_package_iterator *pi;
  40.341 +	int i;
  40.342 +
  40.343 +	if (option_all + option_whatprovides + option_whatrequires > 1) {
  40.344 +		printf("only one type of query/verify "
  40.345 +		       "may be performed at a time\n");
  40.346 +		exit(1);
  40.347 +	}
  40.348 +
  40.349 +	query = razor_package_query_create(set);
  40.350 +
  40.351 +	if (option_all) {
  40.352 +		pi = razor_package_iterator_create(set);
  40.353 +		razor_package_query_add_iterator(query, pi);
  40.354 +		razor_package_iterator_destroy(pi);
  40.355 +	} else if (option_whatrequires) {
  40.356 +		for (i = 0; i < argc; i++)
  40.357 +			add_property_packages(set, query,
  40.358 +					      argv[i], NULL,
  40.359 +					      RAZOR_PROPERTY_REQUIRES);
  40.360 +	} else if (option_whatprovides) {
  40.361 +		for (i = 0; i < argc; i++)
  40.362 +			add_property_packages(set, query,
  40.363 +					      argv[i], NULL,
  40.364 +					      RAZOR_PROPERTY_PROVIDES);
  40.365 +	} else if (argc > 0) {
  40.366 +		add_command_line_packages(set, query, argc, argv);
  40.367 +	} else {
  40.368 +		printf("no arguments given for query/verify\n");
  40.369 +		exit(1);
  40.370 +	}
  40.371 +
  40.372 +	return razor_package_query_finish(query);
  40.373 +}
  40.374 +
  40.375 +static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  40.376 +
  40.377 +static void
  40.378 +print_package_properties(struct razor_set *set,
  40.379 +			 struct razor_package *package,
  40.380 +			 enum razor_property_type ref_type)
  40.381 +{
  40.382 +	struct razor_property *property;
  40.383 +	struct razor_property_iterator *pi;
  40.384 +	const char *name, *version;
  40.385 +	enum razor_property_type type;
  40.386 +	enum razor_version_relation relation;
  40.387 +
  40.388 +	pi = razor_property_iterator_create(set, package);
  40.389 +	while (razor_property_iterator_next(pi, &property,
  40.390 +					    &name, &relation, &version,
  40.391 +					    &type)) {
  40.392 +		if (type != ref_type)
  40.393 +			continue;
  40.394 +		if (version[0] == '\0')
  40.395 +			printf("%s\n", name);
  40.396 +		else
  40.397 +			printf("%s %s %s\n", name,
  40.398 +			       relation_string[relation], version);
  40.399 +	}
  40.400 +	razor_property_iterator_destroy(pi);
  40.401 +}
  40.402 +
  40.403 +static void
  40.404 +print_package_info(struct razor_set *set, struct razor_package *package)
  40.405 +{
  40.406 +	printf("FIXME: Package info not tracked.\n");
  40.407 +}
  40.408 +
  40.409 +static void
  40.410 +print_package_changelog(struct razor_set *set, struct razor_package *package)
  40.411 +{
  40.412 +	printf("FIXME: Package changelog not tracked.\n");
  40.413 +}
  40.414 +
  40.415 +static struct razor_set *
  40.416 +create_set_from_command_line(int argc, const char *argv[])
  40.417 +{
  40.418 +	struct razor_importer *importer;
  40.419 +	struct razor_rpm *rpm;
  40.420 +	int i;
  40.421 +
  40.422 +	importer = razor_importer_new();
  40.423 +
  40.424 +	for (i = 0; i < argc; i++) {
  40.425 +		rpm = razor_rpm_open(argv[i]);
  40.426 +		if (rpm == NULL)
  40.427 +			continue;
  40.428 +		if (razor_importer_add_rpm(importer, rpm))
  40.429 +			printf("couldn't import %s\n", argv[i]);
  40.430 +
  40.431 +		razor_rpm_close(rpm);
  40.432 +	}
  40.433 +
  40.434 +	return razor_importer_finish(importer);
  40.435 +}
  40.436 +
  40.437 +static void
  40.438 +command_query(int argc, const char *argv[])
  40.439 +{
  40.440 +	struct razor_set *set;
  40.441 +	struct razor_package_iterator *pi;
  40.442 +	struct razor_package *package;
  40.443 +	const char *name, *version, *arch;
  40.444 +
  40.445 +	if (option_package) {
  40.446 +		set = create_set_from_command_line(argc, argv);
  40.447 +		argc = 0;
  40.448 +		option_all = 1;
  40.449 +	} else {
  40.450 +		set = razor_root_open_read_only(option_root);
  40.451 +	}
  40.452 +
  40.453 +	pi = get_query_packages(set, argc, argv);
  40.454 +
  40.455 +	while (razor_package_iterator_next(pi, &package,
  40.456 +					   &name, &version, &arch)) {
  40.457 +		if (option_conflicts)
  40.458 +			print_package_properties(set, package,
  40.459 +						 RAZOR_PROPERTY_CONFLICTS);
  40.460 +		if (option_obsoletes)
  40.461 +			print_package_properties(set, package,
  40.462 +						 RAZOR_PROPERTY_OBSOLETES);
  40.463 +		if (option_requires)
  40.464 +			print_package_properties(set, package,
  40.465 +						 RAZOR_PROPERTY_REQUIRES);
  40.466 +		if (option_provides)
  40.467 +			print_package_properties(set, package,
  40.468 +						 RAZOR_PROPERTY_PROVIDES);
  40.469 +		if (option_info)
  40.470 +			print_package_info(set, package);
  40.471 +		if (option_changelog)
  40.472 +			print_package_changelog(set, package);
  40.473 +
  40.474 +		if (option_conflicts + option_obsoletes +
  40.475 +		    option_requires + option_provides +
  40.476 +		    option_info + option_changelog == 0)
  40.477 +			printf("%s-%s.%s\n", name, version, arch);
  40.478 +	}
  40.479 +
  40.480 +	razor_package_iterator_destroy(pi);
  40.481 +
  40.482 +	razor_set_destroy(set);
  40.483 +
  40.484 +	return;
  40.485 +}
  40.486 +
  40.487 +static void
  40.488 +command_verify(int argc, const char *argv[])
  40.489 +{
  40.490 +	struct razor_set *set;
  40.491 +	struct razor_package_iterator *pi;
  40.492 +	struct razor_package *package;
  40.493 +	const char *name, *version, *arch;
  40.494 +
  40.495 +	if (option_package) {
  40.496 +		set = create_set_from_command_line(argc, argv);
  40.497 +		argc = 0;
  40.498 +		option_all = 1;
  40.499 +	} else {
  40.500 +		set = razor_root_open_read_only(option_root);
  40.501 +	}
  40.502 +
  40.503 +	pi = get_query_packages(set, argc, argv);
  40.504 +
  40.505 +	while (razor_package_iterator_next(pi, &package,
  40.506 +					   &name, &version, &arch)) {
  40.507 +		printf("verify %s-%s.%s - not implemented\n",
  40.508 +		       name, version, arch);
  40.509 +	}
  40.510 +
  40.511 +	razor_package_iterator_destroy(pi);
  40.512 +}
  40.513 +
  40.514 +static void
  40.515 +remove_package(const char *name,
  40.516 +	       const char *old_version, const char *new_version,
  40.517 +	       const char *arch, void *data)
  40.518 +{
  40.519 +	if (old_version)
  40.520 +		printf("remove %s-%s.%s\n", name, old_version, arch);
  40.521 +}
  40.522 +
  40.523 +static void
  40.524 +command_erase(int argc, const char *argv[])
  40.525 +{
  40.526 +	struct razor_set *set, *upstream, *next;
  40.527 +	struct razor_transaction *trans;
  40.528 +	struct razor_package_query *query;
  40.529 +	struct razor_package_iterator *pi;
  40.530 +	struct razor_package *package;
  40.531 +	const char *name, *version, *arch;
  40.532 +
  40.533 +	if (argc == 0) {
  40.534 +		printf("no packages given for erase\n");
  40.535 +		exit(1);
  40.536 +	}
  40.537 +
  40.538 +	set = razor_set_open(repo_filename);
  40.539 +	upstream = razor_set_create();
  40.540 +
  40.541 +	trans = razor_transaction_create(set, upstream);
  40.542 +
  40.543 +	query = razor_package_query_create(set);
  40.544 +	add_command_line_packages(set, query, argc, argv);
  40.545 +
  40.546 +	pi = razor_package_query_finish(query);
  40.547 +	while (razor_package_iterator_next(pi, &package,
  40.548 +					   &name, &version, &arch))
  40.549 +		razor_transaction_remove_package(trans, package);
  40.550 +	razor_package_iterator_destroy(pi);
  40.551 +
  40.552 +	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  40.553 +		printf("unsatisfied dependencies.\n");
  40.554 +		exit(1);
  40.555 +	}
  40.556 +
  40.557 +	if (option_test)
  40.558 +		exit(0);
  40.559 +
  40.560 +	next = razor_transaction_finish(trans);
  40.561 +
  40.562 +	if (!option_justdb)
  40.563 +		razor_set_diff(set, next, remove_package, NULL);
  40.564 +
  40.565 +	razor_set_destroy(set);
  40.566 +	razor_set_destroy(upstream);
  40.567 +
  40.568 +	razor_set_destroy(next);
  40.569 +}
  40.570 +
  40.571 +static void
  40.572 +install_package(const char *name,
  40.573 +		const char *old_version, const char *new_version,
  40.574 +		const char *arch, void *data)
  40.575 +{
  40.576 +	if (new_version)
  40.577 +		printf("install %s-%s.%s\n", name, new_version, arch);
  40.578 +}
  40.579 +
  40.580 +static void
  40.581 +command_install(int argc, const char *argv[])
  40.582 +{
  40.583 +	struct razor_set *set, *upstream, *next;
  40.584 +	struct razor_transaction *trans;
  40.585 +	struct razor_package_iterator *pi;
  40.586 +	struct razor_package *package;
  40.587 +	const char *name, *version, *arch;
  40.588 +
  40.589 +	if (argc == 0) {
  40.590 +		printf("no packages given for install\n");
  40.591 +		exit(1);
  40.592 +	}
  40.593 +
  40.594 +	set = razor_set_open(repo_filename);
  40.595 +	upstream = create_set_from_command_line(argc, argv);
  40.596 +
  40.597 +	trans = razor_transaction_create(set, upstream);
  40.598 +
  40.599 +	pi = razor_package_iterator_create(upstream);
  40.600 +	while (razor_package_iterator_next(pi, &package,
  40.601 +					   &name, &version, &arch))
  40.602 +		razor_transaction_install_package(trans, package);
  40.603 +	razor_package_iterator_destroy(pi);
  40.604 +
  40.605 +	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  40.606 +		printf("unsatisfied dependencies.\n");
  40.607 +		exit(1);
  40.608 +	}
  40.609 +
  40.610 +	if (option_test)
  40.611 +		exit(0);
  40.612 +
  40.613 +	next = razor_transaction_finish(trans);
  40.614 +
  40.615 +	if (!option_justdb)
  40.616 +		razor_set_diff(set, next, install_package, NULL);
  40.617 +
  40.618 +	razor_set_destroy(set);
  40.619 +	razor_set_destroy(upstream);
  40.620 +
  40.621 +	razor_set_destroy(next);
  40.622 +}
  40.623 +
  40.624 +static void
  40.625 +update_package(const char *name,
  40.626 +	       const char *old_version, const char *new_version,
  40.627 +	       const char *arch, void *data)
  40.628 +{
  40.629 +	if (old_version)
  40.630 +		printf("remove %s-%s.%s\n", name, old_version, arch);
  40.631 +	if (new_version)
  40.632 +		printf("install %s-%s.%s\n", name, new_version, arch);
  40.633 +}
  40.634 +
  40.635 +static void
  40.636 +command_update(int argc, const char *argv[])
  40.637 +{
  40.638 +	struct razor_set *set, *upstream, *next;
  40.639 +	struct razor_transaction *trans;
  40.640 +	struct razor_package_iterator *pi;
  40.641 +	struct razor_package *package;
  40.642 +	const char *name, *version, *arch;
  40.643 +
  40.644 +	if (argc == 0) {
  40.645 +		printf("no packages given for update\n");
  40.646 +		exit(1);
  40.647 +	}
  40.648 +
  40.649 +	set = razor_set_open(repo_filename);
  40.650 +	upstream = create_set_from_command_line(argc, argv);
  40.651 +
  40.652 +	trans = razor_transaction_create(set, upstream);
  40.653 +
  40.654 +	pi = razor_package_iterator_create(upstream);
  40.655 +	while (razor_package_iterator_next(pi, &package,
  40.656 +					   &name, &version, &arch))
  40.657 +		razor_transaction_update_package(trans, package);
  40.658 +	razor_package_iterator_destroy(pi);
  40.659 +
  40.660 +	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  40.661 +		printf("unsatisfied dependencies.\n");
  40.662 +		exit(1);
  40.663 +	}
  40.664 +
  40.665 +	if (option_test)
  40.666 +		exit(0);
  40.667 +
  40.668 +	next = razor_transaction_finish(trans);
  40.669 +
  40.670 +	if (!option_justdb)
  40.671 +		razor_set_diff(set, next, update_package, NULL);
  40.672 +
  40.673 +	razor_set_destroy(set);
  40.674 +	razor_set_destroy(upstream);
  40.675 +
  40.676 +	razor_set_destroy(next);
  40.677 +}
  40.678 +
  40.679 +static int
  40.680 +for_each_option(const struct option *options,
  40.681 +		const char *name, char short_name,
  40.682 +		void (*fn)(const struct option *o,
  40.683 +			   const char *name, char short_name,
  40.684 +			   void *data), void *data)
  40.685 +{
  40.686 +	int i, count = 0;
  40.687 +
  40.688 +	for (i = 0; options[i].type != OPTION_LAST; i++) {
  40.689 +		switch (options[i].type) {
  40.690 +		case OPTION_GROUP:
  40.691 +			count += for_each_option(options[i].data,
  40.692 +						 name, short_name, fn, data);
  40.693 +			break;
  40.694 +
  40.695 +		case OPTION_BOOL:
  40.696 +		case OPTION_STRING:
  40.697 +			if (name && strcmp(options[i].name, name) == 0) {
  40.698 +				fn(&options[i], name, 0, data);
  40.699 +				count++;
  40.700 +				break;
  40.701 +			}
  40.702 +
  40.703 +			if (short_name &&
  40.704 +			    short_name == options[i].short_name) {
  40.705 +				fn(&options[i], NULL, short_name, data);
  40.706 +				count++;
  40.707 +				break;
  40.708 +			}
  40.709 +			break;
  40.710 +
  40.711 +		case OPTION_LAST:
  40.712 +			break;
  40.713 +		}
  40.714 +	}
  40.715 +
  40.716 +	return count;
  40.717 +}
  40.718 +
  40.719 +static void
  40.720 +handle_option(const struct option *o,
  40.721 +	      const char *name, char short_name, void *data)
  40.722 +{
  40.723 +	if (o->data == NULL) {
  40.724 +		if (name)
  40.725 +			printf("option --%s not supported\n", name);
  40.726 +		else
  40.727 +			printf("option -%c not supported\n", short_name);
  40.728 +		return;
  40.729 +	}
  40.730 +
  40.731 +	switch (o->type) {
  40.732 +	case OPTION_BOOL:
  40.733 +		*(int *) o->data = 1;
  40.734 +		break;
  40.735 +
  40.736 +	case OPTION_STRING:
  40.737 +		*(const char **) o->data = name + strlen(o->name) + 1;
  40.738 +		break;
  40.739 +
  40.740 +	case OPTION_LAST:
  40.741 +	case OPTION_GROUP:
  40.742 +		/* Shouldn't happen. */
  40.743 +		break;
  40.744 +	}
  40.745 +}
  40.746 +
  40.747 +static int
  40.748 +parse_options(const struct option *options, int argc, const char **argv)
  40.749 +{
  40.750 +	int i, j, k;
  40.751 +
  40.752 +	for (i = 1, j = 0; i < argc; i++) {
  40.753 +		if (argv[i][0] != '-') {
  40.754 +			argv[j++] = argv[i];
  40.755 +			continue;
  40.756 +		}
  40.757 +
  40.758 +		if (argv[i][1] == '-') {
  40.759 +			if (for_each_option(options, &argv[i][2], 0,
  40.760 +					    handle_option, NULL) == 0) {
  40.761 +				printf("unknown option: %s\n", argv[i]);
  40.762 +				exit(1);
  40.763 +			}
  40.764 +			continue;
  40.765 +		}
  40.766 +
  40.767 +		for (k = 1; argv[i][k]; k++) {
  40.768 +			if (for_each_option(options, NULL, argv[i][k],
  40.769 +					    handle_option, NULL) == 0) {
  40.770 +				printf("unknown option: -%c\n", argv[i][k]);
  40.771 +				exit(1);
  40.772 +			}
  40.773 +		}
  40.774 +	}
  40.775 +
  40.776 +	return j;
  40.777 +}
  40.778 +
  40.779 +static void
  40.780 +print_options_help(const struct option *options)
  40.781 +{
  40.782 +	int i;
  40.783 +
  40.784 +	for (i = 0; options[i].type != OPTION_LAST; i++) {
  40.785 +		switch (options[i].type) {
  40.786 +		case OPTION_GROUP:
  40.787 +			printf("%s\n", options[i].description);
  40.788 +			print_options_help(options[i].data);
  40.789 +			printf("\n");
  40.790 +			break;
  40.791 +
  40.792 +		case OPTION_BOOL:
  40.793 +		case OPTION_STRING:
  40.794 +			printf("  ");
  40.795 +			if (options[i].short_name)
  40.796 +				printf("-%c", options[i].short_name);
  40.797 +			if (options[i].short_name && options[i].name)
  40.798 +				printf(", ");
  40.799 +			if (options[i].name)
  40.800 +				printf("--%s", options[i].name);
  40.801 +			if (options[i].arg_name)
  40.802 +				printf("=%s", options[i].arg_name);
  40.803 +			if (options[i].description)
  40.804 +				printf("\t\t%s", options[i].description);
  40.805 +			printf("\n");
  40.806 +			break;
  40.807 +
  40.808 +		case OPTION_LAST:
  40.809 +			break;
  40.810 +		}
  40.811 +	}
  40.812 +}
  40.813 +
  40.814 +static void
  40.815 +print_options_usage(const struct option *options)
  40.816 +{
  40.817 +	int i;
  40.818 +
  40.819 +	for (i = 0; options[i].type != OPTION_LAST; i++) {
  40.820 +		switch (options[i].type) {
  40.821 +		case OPTION_GROUP:
  40.822 +			print_options_usage(options[i].data);
  40.823 +			break;
  40.824 +
  40.825 +		case OPTION_BOOL:
  40.826 +			printf("[");
  40.827 +			if (options[i].short_name)
  40.828 +				printf("-%c", options[i].short_name);
  40.829 +			if (options[i].short_name && options[i].name)
  40.830 +				printf("|");
  40.831 +			if (options[i].name)
  40.832 +				printf("--%s", options[i].name);
  40.833 +			printf("] ");
  40.834 +			break;
  40.835 +
  40.836 +		case OPTION_STRING:
  40.837 +			printf("[");
  40.838 +			if (options[i].short_name)
  40.839 +				printf("-%c", options[i].short_name);
  40.840 +			if (options[i].short_name && options[i].name)
  40.841 +				printf("|");
  40.842 +			if (options[i].name)
  40.843 +				printf("--%s", options[i].name);
  40.844 +			if (options[i].arg_name)
  40.845 +				printf("=%s", options[i].arg_name);
  40.846 +			printf("] ");
  40.847 +			break;
  40.848 +
  40.849 +
  40.850 +			break;
  40.851 +
  40.852 +		case OPTION_LAST:
  40.853 +			break;
  40.854 +		}
  40.855 +	}
  40.856 +}
  40.857 +
  40.858 +int
  40.859 +main(int argc, const char *argv[])
  40.860 +{
  40.861 +	argc = parse_options(rpm_options, argc, argv);
  40.862 +
  40.863 +	if (option_version) {
  40.864 +		printf("razor rpm version hoopla.\n");
  40.865 +		exit(0);
  40.866 +	}
  40.867 +
  40.868 +	if (option_help) {
  40.869 +		printf("Usage: rpm [OPTION...]\n");
  40.870 +		print_options_help(rpm_options);
  40.871 +		exit(0);
  40.872 +	}
  40.873 +
  40.874 +	if (option_usage) {
  40.875 +		printf("Usage: rpm [OPTION...]\n");
  40.876 +		print_options_usage(rpm_options);
  40.877 +		printf("\n");
  40.878 +		exit(0);
  40.879 +	}
  40.880 +
  40.881 +	if (option_initdb) {
  40.882 +		command_initdb(argc, argv);
  40.883 +	} else if (option_verify) {
  40.884 +		command_verify(argc, argv);
  40.885 +	} else if (option_query) {
  40.886 +		command_query(argc, argv);
  40.887 +	} else if (option_install) {
  40.888 +		command_install(argc, argv);
  40.889 +	} else if (option_upgrade) {
  40.890 +		command_update(argc, argv);
  40.891 +	} else if (option_erase) {
  40.892 +		command_erase(argc, argv);
  40.893 +	} else {
  40.894 +		print_options_usage(rpm_options);
  40.895 +		printf("\n");
  40.896 +		exit(0);
  40.897 +	}
  40.898 +
  40.899 +	return 0;
  40.900 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/src/test-driver.c	Mon Jun 16 15:40:30 2008 -0400
    41.3 @@ -0,0 +1,458 @@
    41.4 +#include <stdio.h>
    41.5 +#include <string.h>
    41.6 +#include <stdarg.h>
    41.7 +#include <unistd.h>
    41.8 +#include <fcntl.h>
    41.9 +#include <errno.h>
   41.10 +#include <expat.h>
   41.11 +
   41.12 +#include "razor.h"
   41.13 +
   41.14 +#define XML_BUFFER_SIZE 4096
   41.15 +
   41.16 +static void
   41.17 +parse_xml_file(const char *filename,
   41.18 +	       XML_StartElementHandler start,
   41.19 +	       XML_EndElementHandler end,
   41.20 +	       void *data)
   41.21 +{
   41.22 +	XML_Parser parser;
   41.23 +	char *buffer;
   41.24 +	int fd, len, err;
   41.25 +
   41.26 +	parser = XML_ParserCreate(NULL);
   41.27 +	XML_SetElementHandler(parser, start, end);
   41.28 +	XML_SetUserData(parser, data);
   41.29 +
   41.30 +	fd = open(filename, O_RDONLY);
   41.31 +	if (fd < 0) {
   41.32 +		fprintf(stderr, "failed to open %s: %m\n", filename);
   41.33 +		exit(-1);
   41.34 +	}
   41.35 +
   41.36 +	while (1) {
   41.37 +		buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
   41.38 +		len = read(fd, buffer, XML_BUFFER_SIZE);
   41.39 +		if (len == 0)
   41.40 +			break;
   41.41 +		err = XML_ParseBuffer(parser, len, len == 0);
   41.42 +		if (err == XML_STATUS_ERROR) {
   41.43 +			fprintf(stderr, "parse error at line %lu:\n%s\n",
   41.44 +				XML_GetCurrentLineNumber(parser),
   41.45 +				XML_ErrorString(XML_GetErrorCode(parser)));
   41.46 +			exit(-1);
   41.47 +		}
   41.48 +	}
   41.49 +
   41.50 +	if (fd < 0) {
   41.51 +		fprintf(stderr, "read: %m\n");
   41.52 +		exit(-1);
   41.53 +	}
   41.54 +
   41.55 +	close(fd);
   41.56 +}
   41.57 +
   41.58 +struct test_context {
   41.59 +	struct razor_set *system_set, *repo_set, *result_set;
   41.60 +
   41.61 +	struct razor_importer *importer;
   41.62 +	struct razor_set **importer_set;
   41.63 +
   41.64 +	struct razor_transaction *trans;
   41.65 +
   41.66 +	char *install_pkgs[3], *remove_pkgs[3];
   41.67 +	int n_install_pkgs, n_remove_pkgs;
   41.68 +
   41.69 +	int unsat;
   41.70 +	int in_result;
   41.71 +
   41.72 +	int debug, errors;
   41.73 +};
   41.74 +
   41.75 +static void
   41.76 +get_atts(const char **atts, ...)
   41.77 +{
   41.78 +	va_list ap;
   41.79 +	const char *name, **ptr;
   41.80 +	int i;
   41.81 +
   41.82 +	va_start(ap, atts);
   41.83 +	while (name = va_arg(ap, const char *), name != NULL) {
   41.84 +		ptr = va_arg(ap, const char **);
   41.85 +		*ptr = NULL;
   41.86 +		for (i = 0; atts[i]; i += 2) {
   41.87 +			if (strcmp(atts[i], name) == 0)
   41.88 +				*ptr = atts[i + 1];
   41.89 +		}
   41.90 +	}
   41.91 +	va_end(ap);
   41.92 +}
   41.93 +
   41.94 +static enum razor_version_relation
   41.95 +parse_relation (const char *rel_str)
   41.96 +{
   41.97 +	if (!rel_str)
   41.98 +		return -1;
   41.99 +	if (rel_str[0] == 'L')
  41.100 +		return rel_str[1] == 'E' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
  41.101 +	else if (rel_str[0] == 'G')
  41.102 +		return rel_str[1] == 'E' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
  41.103 +	else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
  41.104 +		return RAZOR_VERSION_EQUAL;
  41.105 +	else
  41.106 +		return -1;
  41.107 +}
  41.108 +
  41.109 +static void
  41.110 +start_test(struct test_context *ctx, const char **atts)
  41.111 +{
  41.112 +	const char *name = NULL;
  41.113 +
  41.114 +	get_atts(atts, "name", &name, NULL);
  41.115 +	if (!name) {
  41.116 +		fprintf(stderr, "Test with no name\n");
  41.117 +		exit(1);
  41.118 +	}
  41.119 +	printf("%s\n", name);
  41.120 +}
  41.121 +
  41.122 +static void
  41.123 +end_test(struct test_context *ctx)
  41.124 +{
  41.125 +	if (ctx->system_set) {
  41.126 +		razor_set_destroy(ctx->system_set);
  41.127 +		ctx->system_set = NULL;
  41.128 +	}
  41.129 +	if (ctx->repo_set) {
  41.130 +		razor_set_destroy(ctx->repo_set);
  41.131 +		ctx->repo_set = NULL;
  41.132 +	}
  41.133 +	if (ctx->result_set) {
  41.134 +		razor_set_destroy(ctx->result_set);
  41.135 +		ctx->result_set = NULL;
  41.136 +	}
  41.137 +	if (ctx->trans) {
  41.138 +		razor_transaction_destroy(ctx->trans);
  41.139 +		ctx->trans = NULL;
  41.140 +	}
  41.141 +}
  41.142 +
  41.143 +static void
  41.144 +start_set(struct test_context *ctx, const char **atts)
  41.145 +{
  41.146 +	const char *name = NULL;
  41.147 +
  41.148 +	ctx->importer = razor_importer_new();
  41.149 +	get_atts(atts, "name", &name, NULL);
  41.150 +	if (!name)
  41.151 +		ctx->importer_set = &ctx->result_set;
  41.152 +	else if (!strcmp(name, "system"))
  41.153 +		ctx->importer_set = &ctx->system_set;
  41.154 +	else if (!strcmp(name, "repo"))
  41.155 +		ctx->importer_set = &ctx->repo_set;
  41.156 +	else {
  41.157 +		fprintf(stderr, "  bad set name '%s'\n", name);
  41.158 +		exit(1);
  41.159 +	}
  41.160 +}
  41.161 +
  41.162 +static void
  41.163 +end_set(struct test_context *ctx)
  41.164 +{
  41.165 +	*ctx->importer_set = razor_importer_finish(ctx->importer);
  41.166 +	ctx->importer = NULL;
  41.167 +}
  41.168 +
  41.169 +static void
  41.170 +start_package(struct test_context *ctx, const char **atts)
  41.171 +{
  41.172 +	const char *name = NULL, *version = NULL, *arch = NULL;
  41.173 +
  41.174 +	get_atts(atts, "name", &name,
  41.175 +		 "version", &version,
  41.176 +		 "arch", &arch,
  41.177 +		 NULL);
  41.178 +
  41.179 +	if (!name) {
  41.180 +		fprintf(stderr, "  package with no name\n");
  41.181 +		exit(1);
  41.182 +	}
  41.183 +
  41.184 +	razor_importer_begin_package(ctx->importer, name, version, arch);
  41.185 +	razor_importer_add_property(ctx->importer, name,
  41.186 +				    RAZOR_VERSION_EQUAL, version,
  41.187 +				    RAZOR_PROPERTY_PROVIDES);
  41.188 +}
  41.189 +
  41.190 +static void
  41.191 +end_package(struct test_context *ctx)
  41.192 +{
  41.193 +	razor_importer_finish_package(ctx->importer);
  41.194 +}
  41.195 +
  41.196 +static void
  41.197 +add_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
  41.198 +{
  41.199 +	razor_importer_add_property(ctx->importer, name,
  41.200 +				    rel, version, type);
  41.201 +}
  41.202 +
  41.203 +static void
  41.204 +check_unsatisfiable_property(struct test_context *ctx,
  41.205 +			     enum razor_property_type type,
  41.206 +			     const char *name,
  41.207 +			     enum razor_version_relation rel,
  41.208 +			     const char *version)
  41.209 +{
  41.210 +	static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  41.211 +
  41.212 +	if (!version)
  41.213 +		version = "";
  41.214 +
  41.215 +	if (razor_transaction_unsatisfied_property(ctx->trans,
  41.216 +						   name, rel, version, type))
  41.217 +		return;
  41.218 +
  41.219 +	fprintf(stderr, "  didn't get unsatisfiable '%s %s %s'\n",
  41.220 +		name, relation_string[rel], version);
  41.221 +	ctx->errors++;
  41.222 +}
  41.223 +
  41.224 +static void
  41.225 +start_property(struct test_context *ctx, enum razor_property_type type, const char **atts)
  41.226 +{
  41.227 +	const char *name = NULL, *rel_str = NULL, *version = NULL;
  41.228 +	enum razor_version_relation rel;
  41.229 +
  41.230 +	get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
  41.231 +	if (name == NULL) {
  41.232 +		fprintf(stderr, "  no name specified for property\n");
  41.233 +		exit(1);
  41.234 +	}
  41.235 +	if (version) {
  41.236 +		rel = parse_relation(rel_str);
  41.237 +		if (rel == -1) {
  41.238 +			fprintf(stderr, "  bad or missing version relation for property %s\n", name);
  41.239 +			exit(1);
  41.240 +		}
  41.241 +	} else
  41.242 +		rel = RAZOR_VERSION_EQUAL;
  41.243 +
  41.244 +	if (ctx->unsat)
  41.245 +		check_unsatisfiable_property(ctx, type, name, rel, version);
  41.246 +	else
  41.247 +		add_property(ctx, type, name, rel, version);
  41.248 +}
  41.249 +
  41.250 +static void
  41.251 +start_transaction(struct test_context *ctx, const char **atts)
  41.252 +{
  41.253 +	ctx->n_install_pkgs = 0;
  41.254 +	ctx->n_remove_pkgs = 0;
  41.255 +}
  41.256 +
  41.257 +static void
  41.258 +end_transaction(struct test_context *ctx)
  41.259 +{
  41.260 +	struct razor_package *pkg;
  41.261 +	int errors, i;
  41.262 +
  41.263 +	ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
  41.264 +	for (i = 0; i < ctx->n_install_pkgs; i++) {
  41.265 +		pkg = razor_set_get_package(ctx->repo_set,
  41.266 +					    ctx->install_pkgs[i]);
  41.267 +		razor_transaction_install_package(ctx->trans, pkg);
  41.268 +	}
  41.269 +	for (i = 0; i < ctx->n_remove_pkgs; i++) {
  41.270 +		pkg = razor_set_get_package(ctx->repo_set,
  41.271 +					    ctx->remove_pkgs[i]);
  41.272 +		razor_transaction_remove_package(ctx->trans, pkg);
  41.273 +	}
  41.274 +
  41.275 +	errors = razor_transaction_resolve(ctx->trans);
  41.276 +	printf("\n");
  41.277 +
  41.278 +	while (ctx->n_install_pkgs--)
  41.279 +		free(ctx->install_pkgs[ctx->n_install_pkgs]);
  41.280 +	while (ctx->n_remove_pkgs--)
  41.281 +		free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
  41.282 +
  41.283 +	if (!errors) {
  41.284 +		struct razor_set *new;
  41.285 +		new = razor_transaction_finish(ctx->trans);
  41.286 +		ctx->system_set = new;
  41.287 +	}
  41.288 +}
  41.289 +
  41.290 +static void
  41.291 +start_install_or_update(struct test_context *ctx, const char **atts)
  41.292 +{
  41.293 +	const char *name = NULL;
  41.294 +
  41.295 +	get_atts(atts, "name", &name, NULL);
  41.296 +	if (!name) {
  41.297 +		fprintf(stderr, "  install/update with no name\n");
  41.298 +		exit(1);
  41.299 +	}
  41.300 +
  41.301 +	ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
  41.302 +}
  41.303 +
  41.304 +static void
  41.305 +start_remove(struct test_context *ctx, const char **atts)
  41.306 +{
  41.307 +	const char *name = NULL;
  41.308 +
  41.309 +	get_atts(atts, "name", &name, NULL);
  41.310 +	if (!name) {
  41.311 +		fprintf(stderr, "  remove with no name\n");
  41.312 +		exit(1);
  41.313 +	}
  41.314 +
  41.315 +	ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
  41.316 +}
  41.317 +
  41.318 +static void
  41.319 +start_result(struct test_context *ctx, const char **atts)
  41.320 +{
  41.321 +	ctx->in_result = 1;
  41.322 +}
  41.323 +
  41.324 +static void
  41.325 +diff_callback(const char *name,
  41.326 +	      const char *old_version,
  41.327 +	      const char *new_version,
  41.328 +	      const char *arch,
  41.329 +	      void *data)
  41.330 +{
  41.331 +	struct test_context *ctx = data;
  41.332 +
  41.333 +	ctx->errors++;
  41.334 +	if (old_version) {
  41.335 +		fprintf(stderr, "  result set should not contain %s %s\n",
  41.336 +			name, old_version);
  41.337 +	} else {
  41.338 +		fprintf(stderr, "  result set should contain %s %s\n",
  41.339 +			name, new_version);
  41.340 +	}
  41.341 +}
  41.342 +
  41.343 +static void
  41.344 +end_result(struct test_context *ctx)
  41.345 +{
  41.346 +	ctx->in_result = 0;
  41.347 +
  41.348 +	if (ctx->result_set) {
  41.349 +		if (!ctx->system_set)
  41.350 +			ctx->system_set = razor_set_create();
  41.351 +		razor_set_diff(ctx->system_set, ctx->result_set,
  41.352 +			       diff_callback, ctx);
  41.353 +	}
  41.354 +}
  41.355 +
  41.356 +static void
  41.357 +start_unsatisfiable(struct test_context *ctx, const char **atts)
  41.358 +{
  41.359 +	if (ctx->result_set) {
  41.360 +		fprintf(stderr, "Expected to fail, but didn't\n");
  41.361 +		exit(1);
  41.362 +	}
  41.363 +
  41.364 +	ctx->unsat = 1;
  41.365 +}
  41.366 +
  41.367 +static void
  41.368 +end_unsatisfiable(struct test_context *ctx)
  41.369 +{
  41.370 +	ctx->unsat = 0;
  41.371 +}
  41.372 +
  41.373 +static void
  41.374 +start_test_element(void *data, const char *element, const char **atts)
  41.375 +{
  41.376 +	struct test_context *ctx = data;
  41.377 +
  41.378 +	if (strcmp(element, "tests") == 0) {
  41.379 +		;
  41.380 +	} else if (strcmp(element, "test") == 0) {
  41.381 +		start_test(ctx, atts);
  41.382 +	} else if (strcmp(element, "set") == 0) {
  41.383 +		start_set(ctx, atts);
  41.384 +	} else if (strcmp(element, "transaction") == 0) {
  41.385 +		start_transaction(ctx, atts);
  41.386 +	} else if (strcmp(element, "install") == 0) {
  41.387 +		start_install_or_update(ctx, atts);
  41.388 +	} else if (strcmp(element, "install") == 0) {
  41.389 +		start_install_or_update(ctx, atts);
  41.390 +	} else if (strcmp(element, "remove") == 0) {
  41.391 +		start_remove(ctx, atts);
  41.392 +	} else if (strcmp(element, "result") == 0) {
  41.393 +		start_result(ctx, atts);
  41.394 +	} else if (strcmp(element, "unsatisfiable") == 0) {
  41.395 +		start_unsatisfiable(ctx, atts);
  41.396 +	} else if (strcmp(element, "package") == 0) {
  41.397 +		start_package(ctx, atts);
  41.398 +	} else if (strcmp(element, "requires") == 0) {
  41.399 +		start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
  41.400 +	} else if (strcmp(element, "provides") == 0) {
  41.401 +		start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
  41.402 +	} else if (strcmp(element, "conflicts") == 0) {
  41.403 +		start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
  41.404 +	} else if (strcmp(element, "obsoletes") == 0) {
  41.405 +		start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
  41.406 +	} else {
  41.407 +		fprintf(stderr, "Unrecognized element '%s'\n", element);
  41.408 +		exit(1);
  41.409 +	}
  41.410 +}
  41.411 +
  41.412 +static void
  41.413 +end_test_element (void *data, const char *element)
  41.414 +{
  41.415 +	struct test_context *ctx = data;
  41.416 +
  41.417 +	if (strcmp(element, "test") == 0) {
  41.418 +		end_test(ctx);
  41.419 +	} else if (strcmp(element, "set") == 0) {
  41.420 +		end_set(ctx);
  41.421 +	} else if (strcmp(element, "package") == 0) {
  41.422 +		end_package(ctx);
  41.423 +	} else if (strcmp(element, "transaction") == 0) {
  41.424 +		end_transaction(ctx);
  41.425 +	} else if (strcmp(element, "result") == 0) {
  41.426 +		end_result(ctx);
  41.427 +	} else if (strcmp(element, "unsatisfiable") == 0) {
  41.428 +		end_unsatisfiable(ctx);
  41.429 +	}
  41.430 +}
  41.431 +
  41.432 +int main(int argc, char *argv[])
  41.433 +{
  41.434 +	struct test_context ctx;
  41.435 +	const char *test_file;
  41.436 +
  41.437 +	memset(&ctx, 0, sizeof ctx);
  41.438 +
  41.439 +	if (argc > 3) {
  41.440 +		fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
  41.441 +		exit(-1);
  41.442 +	}
  41.443 +
  41.444 +	if (argc >= 2 && !strcmp (argv[1], "-d")) {
  41.445 +		ctx.debug = 1;
  41.446 +		argc--;
  41.447 +		argv++;
  41.448 +	}
  41.449 +	if (argc == 2)
  41.450 +		test_file = argv[1];
  41.451 +	else
  41.452 +		test_file = "test.xml";
  41.453 +
  41.454 +	parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
  41.455 +
  41.456 +	if (ctx.errors) {
  41.457 +		fprintf(stderr, "\n%d errors\n", ctx.errors);
  41.458 +		return 1;
  41.459 +	} else
  41.460 +		return 0;
  41.461 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/src/test.xml	Mon Jun 16 15:40:30 2008 -0400
    42.3 @@ -0,0 +1,858 @@
    42.4 +<tests>
    42.5 +
    42.6 +    <test name="testEmpty">
    42.7 +	<set name="system"/>
    42.8 +	<set name="repo">
    42.9 +	    <package name="zsh" version="1-1" arch="i386"/>
   42.10 +	</set>
   42.11 +	<transaction>
   42.12 +	    <install name="zsh"/>
   42.13 +	    <remove name="zsh"/>
   42.14 +	</transaction>
   42.15 +	<result>
   42.16 +	    <set/>
   42.17 +	</result>
   42.18 +    </test>
   42.19 +
   42.20 +    <test name="testInstallSinglePackageNoRequires">
   42.21 +	<set name="system"/>
   42.22 +	<set name="repo">
   42.23 +	    <package name="zsh" version="1-1" arch="i386"/>
   42.24 +	</set>
   42.25 +	<transaction>
   42.26 +	    <install name="zsh"/>
   42.27 +	</transaction>
   42.28 +	<result>
   42.29 +	    <set>
   42.30 +		<package name="zsh" version="1-1" arch="i386"/>
   42.31 +	    </set>
   42.32 +	</result>
   42.33 +    </test>
   42.34 +
   42.35 +    <test name="testInstallSinglePackageRequireNotProvided">
   42.36 +	<set name="system"/>
   42.37 +	<set name="repo">
   42.38 +	    <package name="zsh" version="1-1" arch="i386">
   42.39 +		<requires name="zip"/>
   42.40 +	    </package>
   42.41 +	</set>
   42.42 +	<transaction>
   42.43 +	    <install name="zsh"/>
   42.44 +	</transaction>
   42.45 +	<result>
   42.46 +	    <unsatisfiable>
   42.47 +		<requires name="zip"/>
   42.48 +	    </unsatisfiable>
   42.49 +	</result>
   42.50 +    </test>
   42.51 +
   42.52 +    <test name="testInstallSinglePackageRequireInstalled">
   42.53 +	<set name="system">
   42.54 +	    <package name="zip" version="1-1" arch="i386"/>
   42.55 +	</set>
   42.56 +	<set name="repo">
   42.57 +	    <package name="zsh" version="1-1" arch="i386">
   42.58 +		<requires name="zip"/>
   42.59 +	    </package>
   42.60 +	</set>
   42.61 +	<transaction>
   42.62 +	    <install name="zsh"/>
   42.63 +	</transaction>
   42.64 +	<result>
   42.65 +	    <set>
   42.66 +		<package name="zip" version="1-1" arch="i386"/>
   42.67 +		<package name="zsh" version="1-1" arch="i386"/>
   42.68 +	    </set>
   42.69 +	</result>
   42.70 +    </test>
   42.71 +
   42.72 +    <test name="testInstallSinglePackageRequireInstalledRequireNotProvided">
   42.73 +	<set name="system">
   42.74 +	    <package name="zip" version="1-2" arch="i386"/>
   42.75 +	</set>
   42.76 +	<set name="repo">
   42.77 +	    <package name="zsh" version="1-1" arch="i386">
   42.78 +		<requires name="zip"/>
   42.79 +		<!-- This may be a bug in the python test: it looks
   42.80 +		     like they meant to have zip require zap, not zsh.
   42.81 +		     But the install succeeds if you do that...
   42.82 +		  -->
   42.83 +		<requires name="zap"/>
   42.84 +	    </package>
   42.85 +	</set>
   42.86 +	<transaction>
   42.87 +	    <install name="zsh"/>
   42.88 +	</transaction>
   42.89 +	<result>
   42.90 +	    <unsatisfiable>
   42.91 +		<requires name="zap"/>
   42.92 +	    </unsatisfiable>
   42.93 +	</result>
   42.94 +    </test>
   42.95 +
   42.96 +    <test name="testInstallSinglePackageRequireInstalledRequireInstall">
   42.97 +	<set name="system">
   42.98 +	    <package name="zip" version="1-3" arch="i386">
   42.99 +		<requires name="zap"/>
  42.100 +	    </package>
  42.101 +	</set>
  42.102 +	<set name="repo">
  42.103 +	    <package name="zsh" version="1-1" arch="i386">
  42.104 +		<requires name="zip"/>
  42.105 +	    </package>
  42.106 +	    <package name="zap" version="1-2" arch="i386"/>
  42.107 +	</set>
  42.108 +	<transaction>
  42.109 +	    <install name="zsh"/>
  42.110 +	    <install name="zap"/>
  42.111 +	</transaction>
  42.112 +	<result>
  42.113 +	    <set>
  42.114 +		<package name="zap" version="1-2" arch="i386"/>
  42.115 +		<package name="zip" version="1-3" arch="i386"/>
  42.116 +		<package name="zsh" version="1-1" arch="i386"/>
  42.117 +	    </set>
  42.118 +	</result>
  42.119 +    </test>
  42.120 +
  42.121 +    <test name="testInstallSinglePackageRequireVer1NotProvided">
  42.122 +	<set name="system">
  42.123 +	    <package name="zip" version="1.0-2" arch="i386"/>
  42.124 +	</set>
  42.125 +	<set name="repo">
  42.126 +	    <package name="zsh" version="1-1" arch="i386">
  42.127 +		<requires name="zip" relation="EQ" version="1.3-2"/>
  42.128 +	    </package>
  42.129 +	</set>
  42.130 +	<transaction>
  42.131 +	    <install name="zsh"/>
  42.132 +	</transaction>
  42.133 +	<result>
  42.134 +	    <unsatisfiable>
  42.135 +		<requires name="zip" relation="EQ" version="1.3-2"/>
  42.136 +	    </unsatisfiable>
  42.137 +	</result>
  42.138 +    </test>
  42.139 +
  42.140 +    <test name="testInstallSinglePackageRequireVer1Installed">
  42.141 +	<set name="system">
  42.142 +	    <package name="zip" version="1.3-2" arch="i386"/>
  42.143 +	</set>
  42.144 +	<set name="repo">
  42.145 +	    <package name="zsh" version="1-1" arch="i386">
  42.146 +		<requires name="zip" relation="EQ" version="1.3-2"/>
  42.147 +	    </package>
  42.148 +	</set>
  42.149 +	<transaction>
  42.150 +	    <install name="zsh"/>
  42.151 +	</transaction>
  42.152 +	<result>
  42.153 +	    <set>
  42.154 +		<package name="zip" version="1.3-2" arch="i386"/>
  42.155 +		<package name="zsh" version="1-1" arch="i386"/>
  42.156 +	    </set>
  42.157 +	</result>
  42.158 +    </test>
  42.159 +
  42.160 +    <test name="testInstallSinglePackageRequireVer2NotProvided">
  42.161 +	<set name="system">
  42.162 +	    <package name="zip" version="1.3-2" arch="i386"/>
  42.163 +	</set>
  42.164 +	<set name="repo">
  42.165 +	    <package name="zsh" version="1-1" arch="i386">
  42.166 +		<requires name="zip" relation="EQ" version="1.3-4"/>
  42.167 +	    </package>
  42.168 +	</set>
  42.169 +	<transaction>
  42.170 +	    <install name="zsh"/>
  42.171 +	</transaction>
  42.172 +	<result>
  42.173 +	    <unsatisfiable>
  42.174 +		<requires name="zip" relation="EQ" version="1.3-4"/>
  42.175 +	    </unsatisfiable>
  42.176 +	</result>
  42.177 +    </test>
  42.178 +
  42.179 +    <test name="testInstallSinglePackageRequireVer2Installed">
  42.180 +	<set name="system">
  42.181 +	    <package name="zip" version="1.3-4" arch="i386"/>
  42.182 +	</set>
  42.183 +	<set name="repo">
  42.184 +	    <package name="zsh" version="1-1" arch="i386">
  42.185 +		<requires name="zip" relation="EQ" version="1.3-4"/>
  42.186 +	    </package>
  42.187 +	</set>
  42.188 +	<transaction>
  42.189 +	    <install name="zsh"/>
  42.190 +	</transaction>
  42.191 +	<result>
  42.192 +	    <set>
  42.193 +		<package name="zip" version="1.3-4" arch="i386"/>
  42.194 +		<package name="zsh" version="1-1" arch="i386"/>
  42.195 +	    </set>
  42.196 +	</result>
  42.197 +    </test>
  42.198 +
  42.199 +    <test name="testInstallSinglePackageRequireVer3NotProvided">
  42.200 +	<set name="system">
  42.201 +	    <package name="zip" version="0:1.3-4" arch="i386"/>
  42.202 +	</set>
  42.203 +	<set name="repo">
  42.204 +	    <package name="zsh" version="1-1" arch="i386">
  42.205 +		<requires name="zip" relation="GE" version="1:1.3-4"/>
  42.206 +	    </package>
  42.207 +	</set>
  42.208 +	<transaction>
  42.209 +	    <install name="zsh"/>
  42.210 +	</transaction>
  42.211 +	<result>
  42.212 +	    <unsatisfiable>
  42.213 +		<requires name="zip" relation="GE" version="1:1.3-4"/>
  42.214 +	    </unsatisfiable>
  42.215 +	</result>
  42.216 +    </test>
  42.217 +
  42.218 +    <test name="testInstallSinglePackageRequireVer3Installed">
  42.219 +	<set name="system">
  42.220 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  42.221 +	</set>
  42.222 +	<set name="repo">
  42.223 +	    <package name="zsh" version="1-1" arch="i386">
  42.224 +		<requires name="zip" relation="GE" version="2:1.3-4"/>
  42.225 +	    </package>
  42.226 +	</set>
  42.227 +	<transaction>
  42.228 +	    <install name="zsh"/>
  42.229 +	</transaction>
  42.230 +	<result>
  42.231 +	    <set>
  42.232 +		<package name="zip" version="2:1.3-4" arch="i386"/>
  42.233 +		<package name="zsh" version="1-1" arch="i386"/>
  42.234 +	    </set>
  42.235 +	</result>
  42.236 +    </test>
  42.237 +
  42.238 +    <test name="testInstallSinglePackageRequireVer4NotProvided">
  42.239 +	<set name="system">
  42.240 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  42.241 +	</set>
  42.242 +	<set name="repo">
  42.243 +	    <package name="zsh" version="1-1" arch="i386">
  42.244 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  42.245 +	    </package>
  42.246 +	</set>
  42.247 +	<transaction>
  42.248 +	    <install name="zsh"/>
  42.249 +	</transaction>
  42.250 +	<result>
  42.251 +	    <unsatisfiable>
  42.252 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  42.253 +	    </unsatisfiable>
  42.254 +	</result>
  42.255 +    </test>
  42.256 +
  42.257 +    <test name="testInstallSinglePackageRequireVer4_1Installed">
  42.258 +	<set name="system">
  42.259 +	    <package name="zip" version="2:1.0-4" arch="i386"/>
  42.260 +	</set>
  42.261 +	<set name="repo">
  42.262 +	    <package name="zsh" version="1-1" arch="i386">
  42.263 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  42.264 +	    </package>
  42.265 +	</set>
  42.266 +	<transaction>
  42.267 +	    <install name="zsh"/>
  42.268 +	</transaction>
  42.269 +	<result>
  42.270 +	    <set>
  42.271 +		<package name="zip" version="2:1.0-4" arch="i386"/>
  42.272 +		<package name="zsh" version="1-1" arch="i386"/>
  42.273 +	    </set>
  42.274 +	</result>
  42.275 +    </test>
  42.276 +
  42.277 +    <test name="testInstallSinglePackageRequireVer4_2Installed">
  42.278 +	<set name="system">
  42.279 +	    <package name="zip" version="2:1.3-3" arch="i386"/>
  42.280 +	</set>
  42.281 +	<set name="repo">
  42.282 +	    <package name="zsh" version="1-1" arch="i386">
  42.283 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  42.284 +	    </package>
  42.285 +	</set>
  42.286 +	<transaction>
  42.287 +	    <install name="zsh"/>
  42.288 +	</transaction>
  42.289 +	<result>
  42.290 +	    <set>
  42.291 +		<package name="zip" version="2:1.3-3" arch="i386"/>
  42.292 +		<package name="zsh" version="1-1" arch="i386"/>
  42.293 +	    </set>
  42.294 +	</result>
  42.295 +    </test>
  42.296 +
  42.297 +    <test name="testInstallSinglePackageRequireVer4_3Installed">
  42.298 +	<set name="system">
  42.299 +	    <package name="zip" version="1.3-4" arch="i386"/>
  42.300 +	</set>
  42.301 +	<set name="repo">
  42.302 +	    <package name="zsh" version="1-1" arch="i386">
  42.303 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  42.304 +	    </package>
  42.305 +	</set>
  42.306 +	<transaction>
  42.307 +	    <install name="zsh"/>
  42.308 +	</transaction>
  42.309 +	<result>
  42.310 +	    <set>
  42.311 +		<package name="zip" version="1.3-4" arch="i386"/>
  42.312 +		<package name="zsh" version="1-1" arch="i386"/>
  42.313 +	    </set>
  42.314 +	</result>
  42.315 +    </test>
  42.316 +
  42.317 +    <test name="testInstallSinglePackageRequireVer4_4Installed">
  42.318 +	<set name="system">
  42.319 +	    <package name="zip" version="1:1.3-4" arch="i386"/>
  42.320 +	</set>
  42.321 +	<set name="repo">
  42.322 +	    <package name="zsh" version="1-1" arch="i386">
  42.323 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  42.324 +	    </package>
  42.325 +	</set>
  42.326 +	<transaction>
  42.327 +	    <install name="zsh"/>
  42.328 +	</transaction>
  42.329 +	<result>
  42.330 +	    <set>
  42.331 +		<package name="zip" version="1:1.3-4" arch="i386"/>
  42.332 +		<package name="zsh" version="1-1" arch="i386"/>
  42.333 +	    </set>
  42.334 +	</result>
  42.335 +    </test>
  42.336 +
  42.337 +    <test name="testInstallSinglePackageRequireVer4_5Installed">
  42.338 +	<set name="system">
  42.339 +	    <package name="zip" version="2:0.3-4" arch="i386"/>
  42.340 +	</set>
  42.341 +	<set name="repo">
  42.342 +	    <package name="zsh" version="1-1" arch="i386">
  42.343 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  42.344 +	    </package>
  42.345 +	</set>
  42.346 +	<transaction>
  42.347 +	    <install name="zsh"/>
  42.348 +	</transaction>
  42.349 +	<result>
  42.350 +	    <set>
  42.351 +		<package name="zip" version="2:0.3-4" arch="i386"/>
  42.352 +		<package name="zsh" version="1-1" arch="i386"/>
  42.353 +	    </set>
  42.354 +	</result>
  42.355 +    </test>
  42.356 +
  42.357 +    <test name="testInstallSinglePackageRequireXtraBadVer">
  42.358 +	<set name="system">
  42.359 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  42.360 +	</set>
  42.361 +	<set name="repo">
  42.362 +	    <package name="zsh" version="1-1" arch="i386">
  42.363 +		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  42.364 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  42.365 +	    </package>
  42.366 +	    <package name="zap" version="0:1.3-4" arch="i386"/>
  42.367 +	</set>
  42.368 +	<transaction>
  42.369 +	    <install name="zsh"/>
  42.370 +	</transaction>
  42.371 +	<result>
  42.372 +	    <unsatisfiable>
  42.373 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  42.374 +	    </unsatisfiable>
  42.375 +	</result>
  42.376 +    </test>
  42.377 +
  42.378 +    <test name="testInstallSinglePackageRequireXtra">
  42.379 +	<set name="system">
  42.380 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  42.381 +	</set>
  42.382 +	<set name="repo">
  42.383 +	    <package name="zsh" version="1-1" arch="i386">
  42.384 +		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  42.385 +		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  42.386 +	    </package>
  42.387 +	    <package name="zap" version="4:2.6-8" arch="i386"/>
  42.388 +	</set>
  42.389 +	<transaction>
  42.390 +	    <install name="zsh"/>
  42.391 +	</transaction>
  42.392 +	<result>
  42.393 +	    <set>
  42.394 +		<package name="zap" version="4:2.6-8" arch="i386"/>
  42.395 +		<package name="zip" version="2:1.3-4" arch="i386"/>
  42.396 +		<package name="zsh" version="1-1" arch="i386"/>
  42.397 +	    </set>
  42.398 +	</result>
  42.399 +    </test>
  42.400 +
  42.401 +    <test name="testInstallSinglePackageRequireInstalledRequireXtra">
  42.402 +	<set name="system">
  42.403 +	    <package name="zip" version="2:1.3-4" arch="i386">
  42.404 +		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  42.405 +	    </package>
  42.406 +	</set>
  42.407 +	<set name="repo">
  42.408 +	    <package name="zsh" version="1-1" arch="i386">
  42.409 +		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  42.410 +	    </package>
  42.411 +	    <!-- This may be a bug in the python test; it doesn't
  42.412 +	         actually matter whether or not zap is available
  42.413 +	      -->
  42.414 +	    <package name="zap" version="4:2.6-8" arch="i386"/>
  42.415 +	</set>
  42.416 +	<transaction>
  42.417 +	    <install name="zsh"/>
  42.418 +	</transaction>
  42.419 +	<result>
  42.420 +	    <set>
  42.421 +		<package name="zip" version="2:1.3-4" arch="i386"/>
  42.422 +		<package name="zsh" version="1-1" arch="i386"/>
  42.423 +	    </set>
  42.424 +	</result>
  42.425 +    </test>
  42.426 +
  42.427 +    <test name="testInstallSinglePackageRequireUpgradeRequireXtraErr">
  42.428 +	<set name="system">
  42.429 +	    <package name="zip" version="2:1.3-4" arch="i386">
  42.430 +		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  42.431 +	    </package>
  42.432 +	</set>
  42.433 +	<set name="repo">
  42.434 +	    <package name="zsh" version="1-1" arch="i386">
  42.435 +		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  42.436 +	    </package>
  42.437 +	    <package name="zip" version="4:2.6-8" arch="i386">
  42.438 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  42.439 +	    </package>
  42.440 +	    <package name="zap" version="2:1.3-4" arch="i386">
  42.441 +		<requires name="zsh" relation="EQ" version="2:4-8"/>
  42.442 +	    </package>
  42.443 +	</set>
  42.444 +	<transaction>
  42.445 +	    <install name="zsh"/>
  42.446 +	</transaction>
  42.447 +	<result>
  42.448 +	    <unsatisfiable>
  42.449 +		<requires name="zsh" relation="EQ" version="2:4-8"/>
  42.450 +	    </unsatisfiable>
  42.451 +	</result>
  42.452 +    </test>
  42.453 +
  42.454 +    <test name="testInstallSinglePackageRequireUpgradeRequireXtraOk">
  42.455 +	<set name="system">
  42.456 +	    <package name="zip" version="2:1.3-4" arch="i386">
  42.457 +		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  42.458 +	    </package>
  42.459 +	</set>
  42.460 +	<set name="repo">
  42.461 +	    <package name="zsh" version="1-1" arch="i386">
  42.462 +		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  42.463 +	    </package>
  42.464 +	    <package name="zip" version="4:2.6-8" arch="i386">
  42.465 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  42.466 +	    </package>
  42.467 +	    <package name="zap" version="2:1.3-4" arch="i386"/>
  42.468 +	</set>
  42.469 +	<transaction>
  42.470 +	    <install name="zsh"/>
  42.471 +	</transaction>
  42.472 +	<result>
  42.473 +	    <set>
  42.474 +		<package name="zap" version="2:1.3-4" arch="i386"/>
  42.475 +		<package name="zip" version="4:2.6-8" arch="i386"/>
  42.476 +		<package name="zsh" version="1-1" arch="i386"/>
  42.477 +	    </set>
  42.478 +	</result>
  42.479 +    </test>
  42.480 +
  42.481 +    <test name="testInstallSinglePackageRequireMultiXtra">
  42.482 +	<set name="system"/>
  42.483 +	<set name="repo">
  42.484 +	    <package name="zsh" version="1-1" arch="i386">
  42.485 +		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  42.486 +	    </package>
  42.487 +	    <package name="zip" version="4:2.6-8" arch="i386">
  42.488 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  42.489 +	    </package>
  42.490 +	    <package name="zap" version="2:1.3-4" arch="i386"/>
  42.491 +	</set>
  42.492 +	<transaction>
  42.493 +	    <install name="zsh"/>
  42.494 +	</transaction>
  42.495 +	<result>
  42.496 +	    <set>
  42.497 +		<package name="zap" version="2:1.3-4" arch="i386"/>
  42.498 +		<package name="zip" version="4:2.6-8" arch="i386"/>
  42.499 +		<package name="zsh" version="1-1" arch="i386"/>
  42.500 +	    </set>
  42.501 +	</result>
  42.502 +    </test>
  42.503 +
  42.504 +    <test name="testInstallSinglePackageRequireInstalledMultiLib">
  42.505 +	<set name="system">
  42.506 +	    <package name="zip" version="1-3" arch="i386"/>
  42.507 +	</set>
  42.508 +	<set name="repo">
  42.509 +	    <package name="zsh" version="1-1" arch="x86_64">
  42.510 +		<requires name="zip"/>
  42.511 +	    </package>
  42.512 +	    <package name="zip" version="1-3" arch="x86_64"/>
  42.513 +	</set>
  42.514 +	<transaction>
  42.515 +	    <install name="zsh"/>
  42.516 +	</transaction>
  42.517 +	<result>
  42.518 +	    <set>
  42.519 +		<package name="zip" version="1-3" arch="i386"/>
  42.520 +		<package name="zsh" version="1-1" arch="x86_64"/>
  42.521 +	    </set>
  42.522 +	</result>
  42.523 +    </test>
  42.524 +
  42.525 +    <test name="testInstallSinglePackageRequireXtra1MultiLib">
  42.526 +	<set name="system"/>
  42.527 +	<set name="repo">
  42.528 +	    <package name="zsh" version="1-1" arch="x86_64">
  42.529 +		<requires name="zip"/>
  42.530 +	    </package>
  42.531 +	    <package name="zip" version="1-3" arch="i386"/>
  42.532 +	</set>
  42.533 +	<transaction>
  42.534 +	    <install name="zsh"/>
  42.535 +	</transaction>
  42.536 +	<result>
  42.537 +	    <set>
  42.538 +		<package name="zip" version="1-3" arch="i386"/>
  42.539 +		<package name="zsh" version="1-1" arch="x86_64"/>
  42.540 +	    </set>
  42.541 +	</result>
  42.542 +    </test>
  42.543 +
  42.544 +    <test name="testInstallSinglePackageRequireXtra2_64MultiLib">
  42.545 +	<set name="system"/>
  42.546 +	<set name="repo">
  42.547 +	    <package name="zsh" version="1-1" arch="x86_64">
  42.548 +		<requires name="zip"/>
  42.549 +	    </package>
  42.550 +	    <package name="zip" version="1-3" arch="i386"/>
  42.551 +	    <package name="zip" version="1-3" arch="x86_64"/>
  42.552 +	</set>
  42.553 +	<transaction>
  42.554 +	    <install name="zsh"/>
  42.555 +	</transaction>
  42.556 +	<result>
  42.557 +	    <set>
  42.558 +		<package name="zsh" version="1-1" arch="x86_64"/>
  42.559 +		<package name="zip" version="1-3" arch="x86_64"/>
  42.560 +	    </set>
  42.561 +	</result>
  42.562 +    </test>
  42.563 +
  42.564 +    <test name="testInstallSinglePackageRequireXtra2_32MultiLib">
  42.565 +	<set name="system"/>
  42.566 +	<set name="repo">
  42.567 +	    <package name="zsh" version="1-1" arch="i386">
  42.568 +		<requires name="zip"/>
  42.569 +	    </package>
  42.570 +	    <package name="zip" version="1-3" arch="i386"/>
  42.571 +	    <package name="zip" version="1-3" arch="x86_64"/>
  42.572 +	</set>
  42.573 +	<transaction>
  42.574 +	    <install name="zsh"/>
  42.575 +	</transaction>
  42.576 +	<result>
  42.577 +	    <set>
  42.578 +		<package name="zip" version="1-3" arch="i386"/>
  42.579 +		<package name="zsh" version="1-1" arch="i386"/>
  42.580 +	    </set>
  42.581 +	</result>
  42.582 +    </test>
  42.583 +
  42.584 +    <test name="testUpdateSinglePackage">
  42.585 +	<set name="system">
  42.586 +	    <package name="zsh" version="1-1" arch="i386"/>
  42.587 +	</set>
  42.588 +	<set name="repo">
  42.589 +	    <package name="zsh" version="1-3" arch="i386"/>
  42.590 +	</set>
  42.591 +	<transaction>
  42.592 +	    <install name="zsh"/>
  42.593 +	</transaction>
  42.594 +	<result>
  42.595 +	    <set>
  42.596 +		<package name="zsh" version="1-3" arch="i386"/>
  42.597 +	    </set>
  42.598 +	</result>
  42.599 +    </test>
  42.600 +
  42.601 +    <test name="testUpdateForDependency">
  42.602 +	<set name="system">
  42.603 +	    <package name="zip" version="0:1-1" arch="i386"/>
  42.604 +	</set>
  42.605 +	<set name="repo">
  42.606 +	    <package name="zsh" version="0:1-1" arch="i386">
  42.607 +		<requires name="zip" relation="EQ" version="0:2-1"/>
  42.608 +	    </package>
  42.609 +	    <package name="zip" version="0:2-1" arch="i386"/>
  42.610 +	</set>
  42.611 +	<transaction>
  42.612 +	    <install name="zsh"/>
  42.613 +	</transaction>
  42.614 +	<result>
  42.615 +	    <set>
  42.616 +		<package name="zip" version="0:2-1" arch="i386"/>
  42.617 +		<package name="zsh" version="0:1-1" arch="i386"/>
  42.618 +	    </set>
  42.619 +	</result>
  42.620 +    </test>
  42.621 +
  42.622 +    <test name="testUpdateSplitPackage">
  42.623 +	<set name="system">
  42.624 +	    <package name="zip" version="0:1-1" arch="i386">
  42.625 +		<provides name="libzip" relation="EQ" version="0:1-1"/>
  42.626 +	    </package>
  42.627 +	</set>
  42.628 +	<set name="repo">
  42.629 +	    <package name="zsh" version="0:1-1" arch="i386">
  42.630 +		<requires name="libzip" relation="EQ" version="0:2-1"/>
  42.631 +	    </package>
  42.632 +	    <package name="zip" version="0:2-1" arch="i386">
  42.633 +		<requires name="zip-libs" relation="EQ" version="0:2-1"/>
  42.634 +	    </package>
  42.635 +	    <package name="zip-libs" version="0:2-1" arch="i386">
  42.636 +		<provides name="libzip" relation="EQ" version="0:2-1"/>
  42.637 +	    </package>
  42.638 +	</set>
  42.639 +	<transaction>
  42.640 +	    <install name="zsh"/>
  42.641 +	</transaction>
  42.642 +	<result>
  42.643 +	    <set>
  42.644 +		<package name="zip" version="0:1-1" arch="i386"/>
  42.645 +		<package name="zip-libs" version="0:2-1" arch="i386"/>
  42.646 +		<package name="zsh" version="0:1-1" arch="i386"/>
  42.647 +	    </set>
  42.648 +	</result>
  42.649 +    </test>
  42.650 +
  42.651 +    <test name="testUpdateSinglePackageNewRequires">
  42.652 +	<set name="system">
  42.653 +	    <package name="zsh" version="1-1" arch="i386"/>
  42.654 +	</set>
  42.655 +	<set name="repo">
  42.656 +	    <package name="zsh" version="1-3" arch="i386">
  42.657 +		<requires name="zip"/>
  42.658 +	    </package>
  42.659 +	    <package name="zip" version="1-3" arch="x86_64"/>
  42.660 +	</set>
  42.661 +	<transaction>
  42.662 +	    <install name="zsh"/>
  42.663 +	</transaction>
  42.664 +	<result>
  42.665 +	    <set>
  42.666 +		<package name="zsh" version="1-3" arch="i386"/>
  42.667 +		<package name="zip" version="1-3" arch="x86_64"/>
  42.668 +	    </set>
  42.669 +	</result>
  42.670 +    </test>
  42.671 +
  42.672 +    <test name="testUpdateSinglePackageOldRequires">
  42.673 +	<set name="system">
  42.674 +	    <package name="zsh" version="1-1" arch="i386">
  42.675 +		<requires name="zip"/>
  42.676 +	    </package>
  42.677 +	    <package name="zip" version="1-3" arch="x86_64"/>
  42.678 +	</set>
  42.679 +	<set name="repo">
  42.680 +	    <package name="zsh" version="1-3" arch="i386">
  42.681 +		<requires name="zip"/>
  42.682 +	    </package>
  42.683 +	</set>
  42.684 +	<transaction>
  42.685 +	    <install name="zsh"/>
  42.686 +	</transaction>
  42.687 +	<result>
  42.688 +	    <set>
  42.689 +		<package name="zip" version="1-3" arch="x86_64"/>
  42.690 +		<package name="zsh" version="1-3" arch="i386"/>
  42.691 +	    </set>
  42.692 +	</result>
  42.693 +    </test>
  42.694 +
  42.695 +    <test name="testUpdateSinglePackageOldRequiresGone">
  42.696 +	<set name="system">
  42.697 +	    <package name="zsh" version="1-1" arch="i386">
  42.698 +		<requires name="zip"/>
  42.699 +	    </package>
  42.700 +	    <package name="zip" version="1-3" arch="x86_64"/>
  42.701 +	</set>
  42.702 +	<set name="repo">
  42.703 +	    <package name="zsh" version="1-3" arch="i386"/>
  42.704 +	</set>
  42.705 +	<transaction>
  42.706 +	    <install name="zsh"/>
  42.707 +	</transaction>
  42.708 +	<result>
  42.709 +	    <set>
  42.710 +		<package name="zip" version="1-3" arch="x86_64"/>
  42.711 +		<package name="zsh" version="1-3" arch="i386"/>
  42.712 +	    </set>
  42.713 +	</result>
  42.714 +    </test>
  42.715 +
  42.716 +    <test name="testUpdateSinglePackageObsoletesOldRequirement">
  42.717 +	<set name="system">
  42.718 +	    <package name="zsh" version="1-1" arch="i386">
  42.719 +		<requires name="zip"/>
  42.720 +	    </package>
  42.721 +	    <package name="zip" version="1-1" arch="i386"/>
  42.722 +	</set>
  42.723 +	<set name="repo">
  42.724 +	    <package name="zsh" version="1-3" arch="i386">
  42.725 +		<!-- depsolvetests.py actually adds the obsoletes
  42.726 +		     to the installed zsh rather than the new zsh,
  42.727 +		     but I'm assuming that's a bug -->
  42.728 +		<obsoletes name="zip"/>
  42.729 +	    </package>
  42.730 +	</set>
  42.731 +	<transaction>
  42.732 +	    <install name="zsh"/>
  42.733 +	</transaction>
  42.734 +	<result>
  42.735 +	    <set>
  42.736 +		<package name="zsh" version="1-3" arch="i386"/>
  42.737 +	    </set>
  42.738 +	</result>
  42.739 +    </test>
  42.740 +
  42.741 +    <test name="testUpdateForConflict">
  42.742 +	<set name="system">
  42.743 +	    <package name="zip" version="0:1-1" arch="i386"/>
  42.744 +	</set>
  42.745 +	<set name="repo">
  42.746 +	    <package name="zsh" version="0:1-1" arch="i386">
  42.747 +		<conflicts name="zip" relation="LE" version="0:1-1"/>
  42.748 +	    </package>
  42.749 +	    <package name="zip" version="0:2-1" arch="i386"/>
  42.750 +	</set>
  42.751 +	<transaction>
  42.752 +	    <install name="zsh"/>
  42.753 +	</transaction>
  42.754 +	<result>
  42.755 +	    <set>
  42.756 +		<package name="zip" version="0:2-1" arch="i386"/>
  42.757 +		<package name="zsh" version="0:1-1" arch="i386"/>
  42.758 +	    </set>
  42.759 +	</result>
  42.760 +    </test>
  42.761 +
  42.762 +    <test name="testUpdateForConflict2">
  42.763 +	<set name="system">
  42.764 +	    <package name="zip" version="0:1-1" arch="i386">
  42.765 +		<conflicts name="zsh" relation="LE" version="0:1-1"/>
  42.766 +	    </package>
  42.767 +	</set>
  42.768 +	<set name="repo">
  42.769 +	    <package name="zsh" version="0:1-1" arch="i386"/>
  42.770 +	    <package name="zip" version="0:2-1" arch="i386"/>
  42.771 +	</set>
  42.772 +	<transaction>
  42.773 +	    <install name="zsh"/>
  42.774 +	</transaction>
  42.775 +	<result>
  42.776 +	    <set>
  42.777 +		<package name="zsh" version="0:1-1" arch="i386"/>
  42.778 +		<package name="zip" version="0:2-1" arch="i386"/>
  42.779 +	    </set>
  42.780 +	</result>
  42.781 +    </test>
  42.782 +
  42.783 +    <test name="testUpdateForConflictProvide">
  42.784 +	<set name="system">
  42.785 +	    <package name="zip" version="0:1-1" arch="i386">
  42.786 +		<provides name="zippy" relation="EQ" version="0:1-1"/>
  42.787 +	    </package>
  42.788 +	</set>
  42.789 +	<set name="repo">
  42.790 +	    <package name="zsh" version="0:1-1" arch="i386">
  42.791 +		<conflicts name="zippy" relation="LE" version="0:1-1"/>
  42.792 +	    </package>
  42.793 +	    <package name="zip" version="0:2-1" arch="i386"/>
  42.794 +	</set>
  42.795 +	<transaction>
  42.796 +	    <install name="zsh"/>
  42.797 +	</transaction>
  42.798 +	<result>
  42.799 +	    <set>
  42.800 +		<package name="zip" version="0:2-1" arch="i386"/>
  42.801 +		<package name="zsh" version="0:1-1" arch="i386"/>
  42.802 +	    </set>
  42.803 +	</result>
  42.804 +    </test>
  42.805 +
  42.806 +    <test name="testUpdateForConflictProvide2">
  42.807 +	<set name="system">
  42.808 +	    <package name="zip" version="0:1-1" arch="i386">
  42.809 +		<conflicts name="zippy" relation="GT" version="0:1-1"/>
  42.810 +		<conflicts name="zippy" relation="LT" version="0:1-1"/>
  42.811 +	    </package>
  42.812 +	</set>
  42.813 +	<set name="repo">
  42.814 +	    <package name="zsh" version="0:1-1" arch="i386">
  42.815 +		<provides name="zippy" relation="EQ" version="0:2-1"/>
  42.816 +	    </package>
  42.817 +	    <package name="zip" version="0:2-1" arch="i386">
  42.818 +		<conflicts name="zippy" relation="GT" version="0:2-1"/>
  42.819 +		<conflicts name="zippy" relation="LT" version="0:2-1"/>
  42.820 +	    </package>
  42.821 +	</set>
  42.822 +	<transaction>
  42.823 +	    <install name="zsh"/>
  42.824 +	</transaction>
  42.825 +	<result>
  42.826 +	    <set>
  42.827 +		<package name="zip" version="0:2-1" arch="i386"/>
  42.828 +		<package name="zsh" version="0:1-1" arch="i386"/>
  42.829 +	    </set>
  42.830 +	</result>
  42.831 +    </test>
  42.832 +
  42.833 +    <test name="testEraseSinglePackage">
  42.834 +	<set name="system">
  42.835 +	    <package name="zsh" version="0:1-1" arch="i386"/>
  42.836 +	</set>
  42.837 +	<set name="repo"/>
  42.838 +	<transaction>
  42.839 +	    <remove name="zsh"/>
  42.840 +	</transaction>
  42.841 +	<result>
  42.842 +	    <set/>
  42.843 +	</result>
  42.844 +    </test>
  42.845 +
  42.846 +    <test name="testEraseSinglePackageRequiredByOneInstalled">
  42.847 +	<set name="system">
  42.848 +	    <package name="zippy" version="0:1-1" arch="i386">
  42.849 +		<requires name="zsh"/>
  42.850 +	    </package>
  42.851 +	    <package name="zsh" version="0:1-1" arch="i386"/>
  42.852 +	</set>
  42.853 +	<set name="repo"/>
  42.854 +	<transaction>
  42.855 +	    <remove name="zsh"/>
  42.856 +	</transaction>
  42.857 +	<result>
  42.858 +	    <set/>
  42.859 +	</result>
  42.860 +    </test>
  42.861 +</tests>
    43.1 --- a/test-driver.c	Sun Jun 15 23:15:59 2008 -0400
    43.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.3 @@ -1,458 +0,0 @@
    43.4 -#include <stdio.h>
    43.5 -#include <string.h>
    43.6 -#include <stdarg.h>
    43.7 -#include <unistd.h>
    43.8 -#include <fcntl.h>
    43.9 -#include <errno.h>
   43.10 -#include <expat.h>
   43.11 -
   43.12 -#include "razor.h"
   43.13 -
   43.14 -#define XML_BUFFER_SIZE 4096
   43.15 -
   43.16 -static void
   43.17 -parse_xml_file(const char *filename,
   43.18 -	       XML_StartElementHandler start,
   43.19 -	       XML_EndElementHandler end,
   43.20 -	       void *data)
   43.21 -{
   43.22 -	XML_Parser parser;
   43.23 -	char *buffer;
   43.24 -	int fd, len, err;
   43.25 -
   43.26 -	parser = XML_ParserCreate(NULL);
   43.27 -	XML_SetElementHandler(parser, start, end);
   43.28 -	XML_SetUserData(parser, data);
   43.29 -
   43.30 -	fd = open(filename, O_RDONLY);
   43.31 -	if (fd < 0) {
   43.32 -		fprintf(stderr, "failed to open %s: %m\n", filename);
   43.33 -		exit(-1);
   43.34 -	}
   43.35 -
   43.36 -	while (1) {
   43.37 -		buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
   43.38 -		len = read(fd, buffer, XML_BUFFER_SIZE);
   43.39 -		if (len == 0)
   43.40 -			break;
   43.41 -		err = XML_ParseBuffer(parser, len, len == 0);
   43.42 -		if (err == XML_STATUS_ERROR) {
   43.43 -			fprintf(stderr, "parse error at line %lu:\n%s\n",
   43.44 -				XML_GetCurrentLineNumber(parser),
   43.45 -				XML_ErrorString(XML_GetErrorCode(parser)));
   43.46 -			exit(-1);
   43.47 -		}
   43.48 -	}
   43.49 -
   43.50 -	if (fd < 0) {
   43.51 -		fprintf(stderr, "read: %m\n");
   43.52 -		exit(-1);
   43.53 -	}
   43.54 -
   43.55 -	close(fd);
   43.56 -}
   43.57 -
   43.58 -struct test_context {
   43.59 -	struct razor_set *system_set, *repo_set, *result_set;
   43.60 -
   43.61 -	struct razor_importer *importer;
   43.62 -	struct razor_set **importer_set;
   43.63 -
   43.64 -	struct razor_transaction *trans;
   43.65 -
   43.66 -	char *install_pkgs[3], *remove_pkgs[3];
   43.67 -	int n_install_pkgs, n_remove_pkgs;
   43.68 -
   43.69 -	int unsat;
   43.70 -	int in_result;
   43.71 -
   43.72 -	int debug, errors;
   43.73 -};
   43.74 -
   43.75 -static void
   43.76 -get_atts(const char **atts, ...)
   43.77 -{
   43.78 -	va_list ap;
   43.79 -	const char *name, **ptr;
   43.80 -	int i;
   43.81 -
   43.82 -	va_start(ap, atts);
   43.83 -	while (name = va_arg(ap, const char *), name != NULL) {
   43.84 -		ptr = va_arg(ap, const char **);
   43.85 -		*ptr = NULL;
   43.86 -		for (i = 0; atts[i]; i += 2) {
   43.87 -			if (strcmp(atts[i], name) == 0)
   43.88 -				*ptr = atts[i + 1];
   43.89 -		}
   43.90 -	}
   43.91 -	va_end(ap);
   43.92 -}
   43.93 -
   43.94 -static enum razor_version_relation
   43.95 -parse_relation (const char *rel_str)
   43.96 -{
   43.97 -	if (!rel_str)
   43.98 -		return -1;
   43.99 -	if (rel_str[0] == 'L')
  43.100 -		return rel_str[1] == 'E' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
  43.101 -	else if (rel_str[0] == 'G')
  43.102 -		return rel_str[1] == 'E' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
  43.103 -	else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
  43.104 -		return RAZOR_VERSION_EQUAL;
  43.105 -	else
  43.106 -		return -1;
  43.107 -}
  43.108 -
  43.109 -static void
  43.110 -start_test(struct test_context *ctx, const char **atts)
  43.111 -{
  43.112 -	const char *name = NULL;
  43.113 -
  43.114 -	get_atts(atts, "name", &name, NULL);
  43.115 -	if (!name) {
  43.116 -		fprintf(stderr, "Test with no name\n");
  43.117 -		exit(1);
  43.118 -	}
  43.119 -	printf("%s\n", name);
  43.120 -}
  43.121 -
  43.122 -static void
  43.123 -end_test(struct test_context *ctx)
  43.124 -{
  43.125 -	if (ctx->system_set) {
  43.126 -		razor_set_destroy(ctx->system_set);
  43.127 -		ctx->system_set = NULL;
  43.128 -	}
  43.129 -	if (ctx->repo_set) {
  43.130 -		razor_set_destroy(ctx->repo_set);
  43.131 -		ctx->repo_set = NULL;
  43.132 -	}
  43.133 -	if (ctx->result_set) {
  43.134 -		razor_set_destroy(ctx->result_set);
  43.135 -		ctx->result_set = NULL;
  43.136 -	}
  43.137 -	if (ctx->trans) {
  43.138 -		razor_transaction_destroy(ctx->trans);
  43.139 -		ctx->trans = NULL;
  43.140 -	}
  43.141 -}
  43.142 -
  43.143 -static void
  43.144 -start_set(struct test_context *ctx, const char **atts)
  43.145 -{
  43.146 -	const char *name = NULL;
  43.147 -
  43.148 -	ctx->importer = razor_importer_new();
  43.149 -	get_atts(atts, "name", &name, NULL);
  43.150 -	if (!name)
  43.151 -		ctx->importer_set = &ctx->result_set;
  43.152 -	else if (!strcmp(name, "system"))
  43.153 -		ctx->importer_set = &ctx->system_set;
  43.154 -	else if (!strcmp(name, "repo"))
  43.155 -		ctx->importer_set = &ctx->repo_set;
  43.156 -	else {
  43.157 -		fprintf(stderr, "  bad set name '%s'\n", name);
  43.158 -		exit(1);
  43.159 -	}
  43.160 -}
  43.161 -
  43.162 -static void
  43.163 -end_set(struct test_context *ctx)
  43.164 -{
  43.165 -	*ctx->importer_set = razor_importer_finish(ctx->importer);
  43.166 -	ctx->importer = NULL;
  43.167 -}
  43.168 -
  43.169 -static void
  43.170 -start_package(struct test_context *ctx, const char **atts)
  43.171 -{
  43.172 -	const char *name = NULL, *version = NULL, *arch = NULL;
  43.173 -
  43.174 -	get_atts(atts, "name", &name,
  43.175 -		 "version", &version,
  43.176 -		 "arch", &arch,
  43.177 -		 NULL);
  43.178 -
  43.179 -	if (!name) {
  43.180 -		fprintf(stderr, "  package with no name\n");
  43.181 -		exit(1);
  43.182 -	}
  43.183 -
  43.184 -	razor_importer_begin_package(ctx->importer, name, version, arch);
  43.185 -	razor_importer_add_property(ctx->importer, name,
  43.186 -				    RAZOR_VERSION_EQUAL, version,
  43.187 -				    RAZOR_PROPERTY_PROVIDES);
  43.188 -}
  43.189 -
  43.190 -static void
  43.191 -end_package(struct test_context *ctx)
  43.192 -{
  43.193 -	razor_importer_finish_package(ctx->importer);
  43.194 -}
  43.195 -
  43.196 -static void
  43.197 -add_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
  43.198 -{
  43.199 -	razor_importer_add_property(ctx->importer, name,
  43.200 -				    rel, version, type);
  43.201 -}
  43.202 -
  43.203 -static void
  43.204 -check_unsatisfiable_property(struct test_context *ctx,
  43.205 -			     enum razor_property_type type,
  43.206 -			     const char *name,
  43.207 -			     enum razor_version_relation rel,
  43.208 -			     const char *version)
  43.209 -{
  43.210 -	static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  43.211 -
  43.212 -	if (!version)
  43.213 -		version = "";
  43.214 -
  43.215 -	if (razor_transaction_unsatisfied_property(ctx->trans,
  43.216 -						   name, rel, version, type))
  43.217 -		return;
  43.218 -
  43.219 -	fprintf(stderr, "  didn't get unsatisfiable '%s %s %s'\n",
  43.220 -		name, relation_string[rel], version);
  43.221 -	ctx->errors++;
  43.222 -}
  43.223 -
  43.224 -static void
  43.225 -start_property(struct test_context *ctx, enum razor_property_type type, const char **atts)
  43.226 -{
  43.227 -	const char *name = NULL, *rel_str = NULL, *version = NULL;
  43.228 -	enum razor_version_relation rel;
  43.229 -
  43.230 -	get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
  43.231 -	if (name == NULL) {
  43.232 -		fprintf(stderr, "  no name specified for property\n");
  43.233 -		exit(1);
  43.234 -	}
  43.235 -	if (version) {
  43.236 -		rel = parse_relation(rel_str);
  43.237 -		if (rel == -1) {
  43.238 -			fprintf(stderr, "  bad or missing version relation for property %s\n", name);
  43.239 -			exit(1);
  43.240 -		}
  43.241 -	} else
  43.242 -		rel = RAZOR_VERSION_EQUAL;
  43.243 -	
  43.244 -	if (ctx->unsat)
  43.245 -		check_unsatisfiable_property(ctx, type, name, rel, version);
  43.246 -	else
  43.247 -		add_property(ctx, type, name, rel, version);
  43.248 -}
  43.249 -
  43.250 -static void
  43.251 -start_transaction(struct test_context *ctx, const char **atts)
  43.252 -{
  43.253 -	ctx->n_install_pkgs = 0;
  43.254 -	ctx->n_remove_pkgs = 0;
  43.255 -}
  43.256 -
  43.257 -static void
  43.258 -end_transaction(struct test_context *ctx)
  43.259 -{
  43.260 -	struct razor_package *pkg;
  43.261 -	int errors, i;
  43.262 -
  43.263 -	ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
  43.264 -	for (i = 0; i < ctx->n_install_pkgs; i++) {
  43.265 -		pkg = razor_set_get_package(ctx->repo_set,
  43.266 -					    ctx->install_pkgs[i]);
  43.267 -		razor_transaction_install_package(ctx->trans, pkg);
  43.268 -	}		
  43.269 -	for (i = 0; i < ctx->n_remove_pkgs; i++) {
  43.270 -		pkg = razor_set_get_package(ctx->repo_set,
  43.271 -					    ctx->remove_pkgs[i]);
  43.272 -		razor_transaction_remove_package(ctx->trans, pkg);
  43.273 -	}		
  43.274 -
  43.275 -	errors = razor_transaction_resolve(ctx->trans);
  43.276 -	printf("\n");
  43.277 -
  43.278 -	while (ctx->n_install_pkgs--)
  43.279 -		free(ctx->install_pkgs[ctx->n_install_pkgs]);
  43.280 -	while (ctx->n_remove_pkgs--)
  43.281 -		free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
  43.282 -
  43.283 -	if (!errors) {
  43.284 -		struct razor_set *new;
  43.285 -		new = razor_transaction_finish(ctx->trans);
  43.286 -		ctx->system_set = new;
  43.287 -	}
  43.288 -}
  43.289 -
  43.290 -static void
  43.291 -start_install_or_update(struct test_context *ctx, const char **atts)
  43.292 -{
  43.293 -	const char *name = NULL;
  43.294 -
  43.295 -	get_atts(atts, "name", &name, NULL);
  43.296 -	if (!name) {
  43.297 -		fprintf(stderr, "  install/update with no name\n");
  43.298 -		exit(1);
  43.299 -	}
  43.300 -
  43.301 -	ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
  43.302 -}
  43.303 -
  43.304 -static void
  43.305 -start_remove(struct test_context *ctx, const char **atts)
  43.306 -{
  43.307 -	const char *name = NULL;
  43.308 -
  43.309 -	get_atts(atts, "name", &name, NULL);
  43.310 -	if (!name) {
  43.311 -		fprintf(stderr, "  remove with no name\n");
  43.312 -		exit(1);
  43.313 -	}
  43.314 -
  43.315 -	ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
  43.316 -}
  43.317 -
  43.318 -static void
  43.319 -start_result(struct test_context *ctx, const char **atts)
  43.320 -{
  43.321 -	ctx->in_result = 1;
  43.322 -}
  43.323 -
  43.324 -static void
  43.325 -diff_callback(const char *name,
  43.326 -	      const char *old_version,
  43.327 -	      const char *new_version,
  43.328 -	      const char *arch,
  43.329 -	      void *data)
  43.330 -{
  43.331 -	struct test_context *ctx = data;
  43.332 -
  43.333 -	ctx->errors++;
  43.334 -	if (old_version) {
  43.335 -		fprintf(stderr, "  result set should not contain %s %s\n",
  43.336 -			name, old_version);
  43.337 -	} else {
  43.338 -		fprintf(stderr, "  result set should contain %s %s\n",
  43.339 -			name, new_version);
  43.340 -	}
  43.341 -}
  43.342 -
  43.343 -static void
  43.344 -end_result(struct test_context *ctx)
  43.345 -{
  43.346 -	ctx->in_result = 0;
  43.347 -
  43.348 -	if (ctx->result_set) {
  43.349 -		if (!ctx->system_set)
  43.350 -			ctx->system_set = razor_set_create();
  43.351 -		razor_set_diff(ctx->system_set, ctx->result_set,
  43.352 -			       diff_callback, ctx);
  43.353 -	}
  43.354 -}
  43.355 -
  43.356 -static void
  43.357 -start_unsatisfiable(struct test_context *ctx, const char **atts)
  43.358 -{
  43.359 -	if (ctx->result_set) {
  43.360 -		fprintf(stderr, "Expected to fail, but didn't\n");
  43.361 -		exit(1);
  43.362 -	}
  43.363 -
  43.364 -	ctx->unsat = 1;
  43.365 -}
  43.366 -
  43.367 -static void
  43.368 -end_unsatisfiable(struct test_context *ctx)
  43.369 -{
  43.370 -	ctx->unsat = 0;
  43.371 -}
  43.372 -
  43.373 -static void
  43.374 -start_test_element(void *data, const char *element, const char **atts)
  43.375 -{
  43.376 -	struct test_context *ctx = data;
  43.377 -
  43.378 -	if (strcmp(element, "tests") == 0) {
  43.379 -		;
  43.380 -	} else if (strcmp(element, "test") == 0) {
  43.381 -		start_test(ctx, atts);
  43.382 -	} else if (strcmp(element, "set") == 0) {
  43.383 -		start_set(ctx, atts);
  43.384 -	} else if (strcmp(element, "transaction") == 0) {
  43.385 -		start_transaction(ctx, atts);
  43.386 -	} else if (strcmp(element, "install") == 0) {
  43.387 -		start_install_or_update(ctx, atts);
  43.388 -	} else if (strcmp(element, "install") == 0) {
  43.389 -		start_install_or_update(ctx, atts);
  43.390 -	} else if (strcmp(element, "remove") == 0) {
  43.391 -		start_remove(ctx, atts);
  43.392 -	} else if (strcmp(element, "result") == 0) {
  43.393 -		start_result(ctx, atts);
  43.394 -	} else if (strcmp(element, "unsatisfiable") == 0) {
  43.395 -		start_unsatisfiable(ctx, atts);
  43.396 -	} else if (strcmp(element, "package") == 0) {
  43.397 -		start_package(ctx, atts);
  43.398 -	} else if (strcmp(element, "requires") == 0) {
  43.399 -		start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
  43.400 -	} else if (strcmp(element, "provides") == 0) {
  43.401 -		start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
  43.402 -	} else if (strcmp(element, "conflicts") == 0) {
  43.403 -		start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
  43.404 -	} else if (strcmp(element, "obsoletes") == 0) {
  43.405 -		start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
  43.406 -	} else {
  43.407 -		fprintf(stderr, "Unrecognized element '%s'\n", element);
  43.408 -		exit(1);
  43.409 -	}
  43.410 -}
  43.411 -
  43.412 -static void
  43.413 -end_test_element (void *data, const char *element)
  43.414 -{
  43.415 -	struct test_context *ctx = data;
  43.416 -
  43.417 -	if (strcmp(element, "test") == 0) {
  43.418 -		end_test(ctx);
  43.419 -	} else if (strcmp(element, "set") == 0) {
  43.420 -		end_set(ctx);
  43.421 -	} else if (strcmp(element, "package") == 0) {
  43.422 -		end_package(ctx);
  43.423 -	} else if (strcmp(element, "transaction") == 0) {
  43.424 -		end_transaction(ctx);
  43.425 -	} else if (strcmp(element, "result") == 0) {
  43.426 -		end_result(ctx);
  43.427 -	} else if (strcmp(element, "unsatisfiable") == 0) {
  43.428 -		end_unsatisfiable(ctx);
  43.429 -	}
  43.430 -}
  43.431 -
  43.432 -int main(int argc, char *argv[])
  43.433 -{
  43.434 -	struct test_context ctx;
  43.435 -	const char *test_file;
  43.436 -
  43.437 -	memset(&ctx, 0, sizeof ctx);
  43.438 -
  43.439 -	if (argc > 3) {
  43.440 -		fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
  43.441 -		exit(-1);			
  43.442 -	}
  43.443 -
  43.444 -	if (argc >= 2 && !strcmp (argv[1], "-d")) {
  43.445 -		ctx.debug = 1;
  43.446 -		argc--;
  43.447 -		argv++;
  43.448 -	}
  43.449 -	if (argc == 2)
  43.450 -		test_file = argv[1];
  43.451 -	else
  43.452 -		test_file = "test.xml";
  43.453 -
  43.454 -	parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
  43.455 -
  43.456 -	if (ctx.errors) {
  43.457 -		fprintf(stderr, "\n%d errors\n", ctx.errors);
  43.458 -		return 1;
  43.459 -	} else
  43.460 -		return 0;
  43.461 -}
    44.1 --- a/test.xml	Sun Jun 15 23:15:59 2008 -0400
    44.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.3 @@ -1,858 +0,0 @@
    44.4 -<tests>
    44.5 -
    44.6 -    <test name="testEmpty">
    44.7 -	<set name="system"/>
    44.8 -	<set name="repo">
    44.9 -	    <package name="zsh" version="1-1" arch="i386"/>
   44.10 -	</set>
   44.11 -	<transaction>
   44.12 -	    <install name="zsh"/>
   44.13 -	    <remove name="zsh"/>
   44.14 -	</transaction>
   44.15 -	<result>
   44.16 -	    <set/>
   44.17 -	</result>
   44.18 -    </test>
   44.19 -
   44.20 -    <test name="testInstallSinglePackageNoRequires">
   44.21 -	<set name="system"/>
   44.22 -	<set name="repo">
   44.23 -	    <package name="zsh" version="1-1" arch="i386"/>
   44.24 -	</set>
   44.25 -	<transaction>
   44.26 -	    <install name="zsh"/>
   44.27 -	</transaction>
   44.28 -	<result>
   44.29 -	    <set>
   44.30 -		<package name="zsh" version="1-1" arch="i386"/>
   44.31 -	    </set>
   44.32 -	</result>
   44.33 -    </test>
   44.34 -
   44.35 -    <test name="testInstallSinglePackageRequireNotProvided">
   44.36 -	<set name="system"/>
   44.37 -	<set name="repo">
   44.38 -	    <package name="zsh" version="1-1" arch="i386">
   44.39 -		<requires name="zip"/>
   44.40 -	    </package>
   44.41 -	</set>
   44.42 -	<transaction>
   44.43 -	    <install name="zsh"/>
   44.44 -	</transaction>
   44.45 -	<result>
   44.46 -	    <unsatisfiable>
   44.47 -		<requires name="zip"/>
   44.48 -	    </unsatisfiable>
   44.49 -	</result>
   44.50 -    </test>
   44.51 -
   44.52 -    <test name="testInstallSinglePackageRequireInstalled">
   44.53 -	<set name="system">
   44.54 -	    <package name="zip" version="1-1" arch="i386"/>
   44.55 -	</set>
   44.56 -	<set name="repo">
   44.57 -	    <package name="zsh" version="1-1" arch="i386">
   44.58 -		<requires name="zip"/>
   44.59 -	    </package>
   44.60 -	</set>
   44.61 -	<transaction>
   44.62 -	    <install name="zsh"/>
   44.63 -	</transaction>
   44.64 -	<result>
   44.65 -	    <set>
   44.66 -		<package name="zip" version="1-1" arch="i386"/>
   44.67 -		<package name="zsh" version="1-1" arch="i386"/>
   44.68 -	    </set>
   44.69 -	</result>
   44.70 -    </test>
   44.71 -
   44.72 -    <test name="testInstallSinglePackageRequireInstalledRequireNotProvided">
   44.73 -	<set name="system">
   44.74 -	    <package name="zip" version="1-2" arch="i386"/>
   44.75 -	</set>
   44.76 -	<set name="repo">
   44.77 -	    <package name="zsh" version="1-1" arch="i386">
   44.78 -		<requires name="zip"/>
   44.79 -		<!-- This may be a bug in the python test: it looks
   44.80 -		     like they meant to have zip require zap, not zsh.
   44.81 -		     But the install succeeds if you do that...
   44.82 -		  -->
   44.83 -		<requires name="zap"/>
   44.84 -	    </package>
   44.85 -	</set>
   44.86 -	<transaction>
   44.87 -	    <install name="zsh"/>
   44.88 -	</transaction>
   44.89 -	<result>
   44.90 -	    <unsatisfiable>
   44.91 -		<requires name="zap"/>
   44.92 -	    </unsatisfiable>
   44.93 -	</result>
   44.94 -    </test>
   44.95 -
   44.96 -    <test name="testInstallSinglePackageRequireInstalledRequireInstall">
   44.97 -	<set name="system">
   44.98 -	    <package name="zip" version="1-3" arch="i386">
   44.99 -		<requires name="zap"/>
  44.100 -	    </package>
  44.101 -	</set>
  44.102 -	<set name="repo">
  44.103 -	    <package name="zsh" version="1-1" arch="i386">
  44.104 -		<requires name="zip"/>
  44.105 -	    </package>
  44.106 -	    <package name="zap" version="1-2" arch="i386"/>
  44.107 -	</set>
  44.108 -	<transaction>
  44.109 -	    <install name="zsh"/>
  44.110 -	    <install name="zap"/>
  44.111 -	</transaction>
  44.112 -	<result>
  44.113 -	    <set>
  44.114 -		<package name="zap" version="1-2" arch="i386"/>
  44.115 -		<package name="zip" version="1-3" arch="i386"/>
  44.116 -		<package name="zsh" version="1-1" arch="i386"/>
  44.117 -	    </set>
  44.118 -	</result>
  44.119 -    </test>
  44.120 -
  44.121 -    <test name="testInstallSinglePackageRequireVer1NotProvided">
  44.122 -	<set name="system">
  44.123 -	    <package name="zip" version="1.0-2" arch="i386"/>
  44.124 -	</set>
  44.125 -	<set name="repo">
  44.126 -	    <package name="zsh" version="1-1" arch="i386">
  44.127 -		<requires name="zip" relation="EQ" version="1.3-2"/>
  44.128 -	    </package>
  44.129 -	</set>
  44.130 -	<transaction>
  44.131 -	    <install name="zsh"/>
  44.132 -	</transaction>
  44.133 -	<result>
  44.134 -	    <unsatisfiable>
  44.135 -		<requires name="zip" relation="EQ" version="1.3-2"/>
  44.136 -	    </unsatisfiable>
  44.137 -	</result>
  44.138 -    </test>
  44.139 -
  44.140 -    <test name="testInstallSinglePackageRequireVer1Installed">
  44.141 -	<set name="system">
  44.142 -	    <package name="zip" version="1.3-2" arch="i386"/>
  44.143 -	</set>
  44.144 -	<set name="repo">
  44.145 -	    <package name="zsh" version="1-1" arch="i386">
  44.146 -		<requires name="zip" relation="EQ" version="1.3-2"/>
  44.147 -	    </package>
  44.148 -	</set>
  44.149 -	<transaction>
  44.150 -	    <install name="zsh"/>
  44.151 -	</transaction>
  44.152 -	<result>
  44.153 -	    <set>
  44.154 -		<package name="zip" version="1.3-2" arch="i386"/>
  44.155 -		<package name="zsh" version="1-1" arch="i386"/>
  44.156 -	    </set>
  44.157 -	</result>
  44.158 -    </test>
  44.159 -
  44.160 -    <test name="testInstallSinglePackageRequireVer2NotProvided">
  44.161 -	<set name="system">
  44.162 -	    <package name="zip" version="1.3-2" arch="i386"/>
  44.163 -	</set>
  44.164 -	<set name="repo">
  44.165 -	    <package name="zsh" version="1-1" arch="i386">
  44.166 -		<requires name="zip" relation="EQ" version="1.3-4"/>
  44.167 -	    </package>
  44.168 -	</set>
  44.169 -	<transaction>
  44.170 -	    <install name="zsh"/>
  44.171 -	</transaction>
  44.172 -	<result>
  44.173 -	    <unsatisfiable>
  44.174 -		<requires name="zip" relation="EQ" version="1.3-4"/>
  44.175 -	    </unsatisfiable>
  44.176 -	</result>
  44.177 -    </test>
  44.178 -
  44.179 -    <test name="testInstallSinglePackageRequireVer2Installed">
  44.180 -	<set name="system">
  44.181 -	    <package name="zip" version="1.3-4" arch="i386"/>
  44.182 -	</set>
  44.183 -	<set name="repo">
  44.184 -	    <package name="zsh" version="1-1" arch="i386">
  44.185 -		<requires name="zip" relation="EQ" version="1.3-4"/>
  44.186 -	    </package>
  44.187 -	</set>
  44.188 -	<transaction>
  44.189 -	    <install name="zsh"/>
  44.190 -	</transaction>
  44.191 -	<result>
  44.192 -	    <set>
  44.193 -		<package name="zip" version="1.3-4" arch="i386"/>
  44.194 -		<package name="zsh" version="1-1" arch="i386"/>
  44.195 -	    </set>
  44.196 -	</result>
  44.197 -    </test>
  44.198 -
  44.199 -    <test name="testInstallSinglePackageRequireVer3NotProvided">
  44.200 -	<set name="system">
  44.201 -	    <package name="zip" version="0:1.3-4" arch="i386"/>
  44.202 -	</set>
  44.203 -	<set name="repo">
  44.204 -	    <package name="zsh" version="1-1" arch="i386">
  44.205 -		<requires name="zip" relation="GE" version="1:1.3-4"/>
  44.206 -	    </package>
  44.207 -	</set>
  44.208 -	<transaction>
  44.209 -	    <install name="zsh"/>
  44.210 -	</transaction>
  44.211 -	<result>
  44.212 -	    <unsatisfiable>
  44.213 -		<requires name="zip" relation="GE" version="1:1.3-4"/>
  44.214 -	    </unsatisfiable>
  44.215 -	</result>
  44.216 -    </test>
  44.217 -
  44.218 -    <test name="testInstallSinglePackageRequireVer3Installed">
  44.219 -	<set name="system">
  44.220 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  44.221 -	</set>
  44.222 -	<set name="repo">
  44.223 -	    <package name="zsh" version="1-1" arch="i386">
  44.224 -		<requires name="zip" relation="GE" version="2:1.3-4"/>
  44.225 -	    </package>
  44.226 -	</set>
  44.227 -	<transaction>
  44.228 -	    <install name="zsh"/>
  44.229 -	</transaction>
  44.230 -	<result>
  44.231 -	    <set>
  44.232 -		<package name="zip" version="2:1.3-4" arch="i386"/>
  44.233 -		<package name="zsh" version="1-1" arch="i386"/>
  44.234 -	    </set>
  44.235 -	</result>
  44.236 -    </test>
  44.237 -
  44.238 -    <test name="testInstallSinglePackageRequireVer4NotProvided">
  44.239 -	<set name="system">
  44.240 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  44.241 -	</set>
  44.242 -	<set name="repo">
  44.243 -	    <package name="zsh" version="1-1" arch="i386">
  44.244 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  44.245 -	    </package>
  44.246 -	</set>
  44.247 -	<transaction>
  44.248 -	    <install name="zsh"/>
  44.249 -	</transaction>
  44.250 -	<result>
  44.251 -	    <unsatisfiable>
  44.252 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  44.253 -	    </unsatisfiable>
  44.254 -	</result>
  44.255 -    </test>
  44.256 -
  44.257 -    <test name="testInstallSinglePackageRequireVer4_1Installed">
  44.258 -	<set name="system">
  44.259 -	    <package name="zip" version="2:1.0-4" arch="i386"/>
  44.260 -	</set>
  44.261 -	<set name="repo">
  44.262 -	    <package name="zsh" version="1-1" arch="i386">
  44.263 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  44.264 -	    </package>
  44.265 -	</set>
  44.266 -	<transaction>
  44.267 -	    <install name="zsh"/>
  44.268 -	</transaction>
  44.269 -	<result>
  44.270 -	    <set>
  44.271 -		<package name="zip" version="2:1.0-4" arch="i386"/>
  44.272 -		<package name="zsh" version="1-1" arch="i386"/>
  44.273 -	    </set>
  44.274 -	</result>
  44.275 -    </test>
  44.276 -
  44.277 -    <test name="testInstallSinglePackageRequireVer4_2Installed">
  44.278 -	<set name="system">
  44.279 -	    <package name="zip" version="2:1.3-3" arch="i386"/>
  44.280 -	</set>
  44.281 -	<set name="repo">
  44.282 -	    <package name="zsh" version="1-1" arch="i386">
  44.283 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  44.284 -	    </package>
  44.285 -	</set>
  44.286 -	<transaction>
  44.287 -	    <install name="zsh"/>
  44.288 -	</transaction>
  44.289 -	<result>
  44.290 -	    <set>
  44.291 -		<package name="zip" version="2:1.3-3" arch="i386"/>
  44.292 -		<package name="zsh" version="1-1" arch="i386"/>
  44.293 -	    </set>
  44.294 -	</result>
  44.295 -    </test>
  44.296 -
  44.297 -    <test name="testInstallSinglePackageRequireVer4_3Installed">
  44.298 -	<set name="system">
  44.299 -	    <package name="zip" version="1.3-4" arch="i386"/>
  44.300 -	</set>
  44.301 -	<set name="repo">
  44.302 -	    <package name="zsh" version="1-1" arch="i386">
  44.303 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  44.304 -	    </package>
  44.305 -	</set>
  44.306 -	<transaction>
  44.307 -	    <install name="zsh"/>
  44.308 -	</transaction>
  44.309 -	<result>
  44.310 -	    <set>
  44.311 -		<package name="zip" version="1.3-4" arch="i386"/>
  44.312 -		<package name="zsh" version="1-1" arch="i386"/>
  44.313 -	    </set>
  44.314 -	</result>
  44.315 -    </test>
  44.316 -
  44.317 -    <test name="testInstallSinglePackageRequireVer4_4Installed">
  44.318 -	<set name="system">
  44.319 -	    <package name="zip" version="1:1.3-4" arch="i386"/>
  44.320 -	</set>
  44.321 -	<set name="repo">
  44.322 -	    <package name="zsh" version="1-1" arch="i386">
  44.323 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  44.324 -	    </package>
  44.325 -	</set>
  44.326 -	<transaction>
  44.327 -	    <install name="zsh"/>
  44.328 -	</transaction>
  44.329 -	<result>
  44.330 -	    <set>
  44.331 -		<package name="zip" version="1:1.3-4" arch="i386"/>
  44.332 -		<package name="zsh" version="1-1" arch="i386"/>
  44.333 -	    </set>
  44.334 -	</result>
  44.335 -    </test>
  44.336 -
  44.337 -    <test name="testInstallSinglePackageRequireVer4_5Installed">
  44.338 -	<set name="system">
  44.339 -	    <package name="zip" version="2:0.3-4" arch="i386"/>
  44.340 -	</set>
  44.341 -	<set name="repo">
  44.342 -	    <package name="zsh" version="1-1" arch="i386">
  44.343 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  44.344 -	    </package>
  44.345 -	</set>
  44.346 -	<transaction>
  44.347 -	    <install name="zsh"/>
  44.348 -	</transaction>
  44.349 -	<result>
  44.350 -	    <set>
  44.351 -		<package name="zip" version="2:0.3-4" arch="i386"/>
  44.352 -		<package name="zsh" version="1-1" arch="i386"/>
  44.353 -	    </set>
  44.354 -	</result>
  44.355 -    </test>
  44.356 -
  44.357 -    <test name="testInstallSinglePackageRequireXtraBadVer">
  44.358 -	<set name="system">
  44.359 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  44.360 -	</set>
  44.361 -	<set name="repo">
  44.362 -	    <package name="zsh" version="1-1" arch="i386">
  44.363 -		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  44.364 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  44.365 -	    </package>
  44.366 -	    <package name="zap" version="0:1.3-4" arch="i386"/>
  44.367 -	</set>
  44.368 -	<transaction>
  44.369 -	    <install name="zsh"/>
  44.370 -	</transaction>
  44.371 -	<result>
  44.372 -	    <unsatisfiable>
  44.373 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  44.374 -	    </unsatisfiable>
  44.375 -	</result>
  44.376 -    </test>
  44.377 -
  44.378 -    <test name="testInstallSinglePackageRequireXtra">
  44.379 -	<set name="system">
  44.380 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  44.381 -	</set>
  44.382 -	<set name="repo">
  44.383 -	    <package name="zsh" version="1-1" arch="i386">
  44.384 -		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  44.385 -		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  44.386 -	    </package>
  44.387 -	    <package name="zap" version="4:2.6-8" arch="i386"/>
  44.388 -	</set>
  44.389 -	<transaction>
  44.390 -	    <install name="zsh"/>
  44.391 -	</transaction>
  44.392 -	<result>
  44.393 -	    <set>
  44.394 -		<package name="zap" version="4:2.6-8" arch="i386"/>
  44.395 -		<package name="zip" version="2:1.3-4" arch="i386"/>
  44.396 -		<package name="zsh" version="1-1" arch="i386"/>
  44.397 -	    </set>
  44.398 -	</result>
  44.399 -    </test>
  44.400 -
  44.401 -    <test name="testInstallSinglePackageRequireInstalledRequireXtra">
  44.402 -	<set name="system">
  44.403 -	    <package name="zip" version="2:1.3-4" arch="i386">
  44.404 -		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  44.405 -	    </package>
  44.406 -	</set>
  44.407 -	<set name="repo">
  44.408 -	    <package name="zsh" version="1-1" arch="i386">
  44.409 -		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  44.410 -	    </package>
  44.411 -	    <!-- This may be a bug in the python test; it doesn't
  44.412 -	         actually matter whether or not zap is available
  44.413 -	      -->
  44.414 -	    <package name="zap" version="4:2.6-8" arch="i386"/>
  44.415 -	</set>
  44.416 -	<transaction>
  44.417 -	    <install name="zsh"/>
  44.418 -	</transaction>
  44.419 -	<result>
  44.420 -	    <set>
  44.421 -		<package name="zip" version="2:1.3-4" arch="i386"/>
  44.422 -		<package name="zsh" version="1-1" arch="i386"/>
  44.423 -	    </set>
  44.424 -	</result>
  44.425 -    </test>
  44.426 -
  44.427 -    <test name="testInstallSinglePackageRequireUpgradeRequireXtraErr">
  44.428 -	<set name="system">
  44.429 -	    <package name="zip" version="2:1.3-4" arch="i386">
  44.430 -		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  44.431 -	    </package>
  44.432 -	</set>
  44.433 -	<set name="repo">
  44.434 -	    <package name="zsh" version="1-1" arch="i386">
  44.435 -		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  44.436 -	    </package>
  44.437 -	    <package name="zip" version="4:2.6-8" arch="i386">
  44.438 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  44.439 -	    </package>
  44.440 -	    <package name="zap" version="2:1.3-4" arch="i386">
  44.441 -		<requires name="zsh" relation="EQ" version="2:4-8"/>
  44.442 -	    </package>
  44.443 -	</set>
  44.444 -	<transaction>
  44.445 -	    <install name="zsh"/>
  44.446 -	</transaction>
  44.447 -	<result>
  44.448 -	    <unsatisfiable>
  44.449 -		<requires name="zsh" relation="EQ" version="2:4-8"/>
  44.450 -	    </unsatisfiable>
  44.451 -	</result>
  44.452 -    </test>
  44.453 -
  44.454 -    <test name="testInstallSinglePackageRequireUpgradeRequireXtraOk">
  44.455 -	<set name="system">
  44.456 -	    <package name="zip" version="2:1.3-4" arch="i386">
  44.457 -		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  44.458 -	    </package>
  44.459 -	</set>
  44.460 -	<set name="repo">
  44.461 -	    <package name="zsh" version="1-1" arch="i386">
  44.462 -		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  44.463 -	    </package>
  44.464 -	    <package name="zip" version="4:2.6-8" arch="i386">
  44.465 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  44.466 -	    </package>
  44.467 -	    <package name="zap" version="2:1.3-4" arch="i386"/>
  44.468 -	</set>
  44.469 -	<transaction>
  44.470 -	    <install name="zsh"/>
  44.471 -	</transaction>
  44.472 -	<result>
  44.473 -	    <set>
  44.474 -		<package name="zap" version="2:1.3-4" arch="i386"/>
  44.475 -		<package name="zip" version="4:2.6-8" arch="i386"/>
  44.476 -		<package name="zsh" version="1-1" arch="i386"/>
  44.477 -	    </set>
  44.478 -	</result>
  44.479 -    </test>
  44.480 -
  44.481 -    <test name="testInstallSinglePackageRequireMultiXtra">
  44.482 -	<set name="system"/>
  44.483 -	<set name="repo">
  44.484 -	    <package name="zsh" version="1-1" arch="i386">
  44.485 -		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  44.486 -	    </package>
  44.487 -	    <package name="zip" version="4:2.6-8" arch="i386">
  44.488 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  44.489 -	    </package>
  44.490 -	    <package name="zap" version="2:1.3-4" arch="i386"/>
  44.491 -	</set>
  44.492 -	<transaction>
  44.493 -	    <install name="zsh"/>
  44.494 -	</transaction>
  44.495 -	<result>
  44.496 -	    <set>
  44.497 -		<package name="zap" version="2:1.3-4" arch="i386"/>
  44.498 -		<package name="zip" version="4:2.6-8" arch="i386"/>
  44.499 -		<package name="zsh" version="1-1" arch="i386"/>
  44.500 -	    </set>
  44.501 -	</result>
  44.502 -    </test>
  44.503 -
  44.504 -    <test name="testInstallSinglePackageRequireInstalledMultiLib">
  44.505 -	<set name="system">
  44.506 -	    <package name="zip" version="1-3" arch="i386"/>
  44.507 -	</set>
  44.508 -	<set name="repo">
  44.509 -	    <package name="zsh" version="1-1" arch="x86_64">
  44.510 -		<requires name="zip"/>
  44.511 -	    </package>
  44.512 -	    <package name="zip" version="1-3" arch="x86_64"/>
  44.513 -	</set>
  44.514 -	<transaction>
  44.515 -	    <install name="zsh"/>
  44.516 -	</transaction>
  44.517 -	<result>
  44.518 -	    <set>
  44.519 -		<package name="zip" version="1-3" arch="i386"/>
  44.520 -		<package name="zsh" version="1-1" arch="x86_64"/>
  44.521 -	    </set>
  44.522 -	</result>
  44.523 -    </test>
  44.524 -
  44.525 -    <test name="testInstallSinglePackageRequireXtra1MultiLib">
  44.526 -	<set name="system"/>
  44.527 -	<set name="repo">
  44.528 -	    <package name="zsh" version="1-1" arch="x86_64">
  44.529 -		<requires name="zip"/>
  44.530 -	    </package>
  44.531 -	    <package name="zip" version="1-3" arch="i386"/>
  44.532 -	</set>
  44.533 -	<transaction>
  44.534 -	    <install name="zsh"/>
  44.535 -	</transaction>
  44.536 -	<result>
  44.537 -	    <set>
  44.538 -		<package name="zip" version="1-3" arch="i386"/>
  44.539 -		<package name="zsh" version="1-1" arch="x86_64"/>
  44.540 -	    </set>
  44.541 -	</result>
  44.542 -    </test>
  44.543 -
  44.544 -    <test name="testInstallSinglePackageRequireXtra2_64MultiLib">
  44.545 -	<set name="system"/>
  44.546 -	<set name="repo">
  44.547 -	    <package name="zsh" version="1-1" arch="x86_64">
  44.548 -		<requires name="zip"/>
  44.549 -	    </package>
  44.550 -	    <package name="zip" version="1-3" arch="i386"/>
  44.551 -	    <package name="zip" version="1-3" arch="x86_64"/>
  44.552 -	</set>
  44.553 -	<transaction>
  44.554 -	    <install name="zsh"/>
  44.555 -	</transaction>
  44.556 -	<result>
  44.557 -	    <set>
  44.558 -		<package name="zsh" version="1-1" arch="x86_64"/>
  44.559 -		<package name="zip" version="1-3" arch="x86_64"/>
  44.560 -	    </set>
  44.561 -	</result>
  44.562 -    </test>
  44.563 -
  44.564 -    <test name="testInstallSinglePackageRequireXtra2_32MultiLib">
  44.565 -	<set name="system"/>
  44.566 -	<set name="repo">
  44.567 -	    <package name="zsh" version="1-1" arch="i386">
  44.568 -		<requires name="zip"/>
  44.569 -	    </package>
  44.570 -	    <package name="zip" version="1-3" arch="i386"/>
  44.571 -	    <package name="zip" version="1-3" arch="x86_64"/>
  44.572 -	</set>
  44.573 -	<transaction>
  44.574 -	    <install name="zsh"/>
  44.575 -	</transaction>
  44.576 -	<result>
  44.577 -	    <set>
  44.578 -		<package name="zip" version="1-3" arch="i386"/>
  44.579 -		<package name="zsh" version="1-1" arch="i386"/>
  44.580 -	    </set>
  44.581 -	</result>
  44.582 -    </test>
  44.583 -
  44.584 -    <test name="testUpdateSinglePackage">
  44.585 -	<set name="system">
  44.586 -	    <package name="zsh" version="1-1" arch="i386"/>
  44.587 -	</set>
  44.588 -	<set name="repo">
  44.589 -	    <package name="zsh" version="1-3" arch="i386"/>
  44.590 -	</set>
  44.591 -	<transaction>
  44.592 -	    <install name="zsh"/>
  44.593 -	</transaction>
  44.594 -	<result>
  44.595 -	    <set>
  44.596 -		<package name="zsh" version="1-3" arch="i386"/>
  44.597 -	    </set>
  44.598 -	</result>
  44.599 -    </test>
  44.600 -
  44.601 -    <test name="testUpdateForDependency">
  44.602 -	<set name="system">
  44.603 -	    <package name="zip" version="0:1-1" arch="i386"/>
  44.604 -	</set>
  44.605 -	<set name="repo">
  44.606 -	    <package name="zsh" version="0:1-1" arch="i386">
  44.607 -		<requires name="zip" relation="EQ" version="0:2-1"/>
  44.608 -	    </package>
  44.609 -	    <package name="zip" version="0:2-1" arch="i386"/>
  44.610 -	</set>
  44.611 -	<transaction>
  44.612 -	    <install name="zsh"/>
  44.613 -	</transaction>
  44.614 -	<result>
  44.615 -	    <set>
  44.616 -		<package name="zip" version="0:2-1" arch="i386"/>
  44.617 -		<package name="zsh" version="0:1-1" arch="i386"/>
  44.618 -	    </set>
  44.619 -	</result>
  44.620 -    </test>
  44.621 -
  44.622 -    <test name="testUpdateSplitPackage">
  44.623 -	<set name="system">
  44.624 -	    <package name="zip" version="0:1-1" arch="i386">
  44.625 -		<provides name="libzip" relation="EQ" version="0:1-1"/>
  44.626 -	    </package>
  44.627 -	</set>
  44.628 -	<set name="repo">
  44.629 -	    <package name="zsh" version="0:1-1" arch="i386">
  44.630 -		<requires name="libzip" relation="EQ" version="0:2-1"/>
  44.631 -	    </package>
  44.632 -	    <package name="zip" version="0:2-1" arch="i386">
  44.633 -		<requires name="zip-libs" relation="EQ" version="0:2-1"/>
  44.634 -	    </package>
  44.635 -	    <package name="zip-libs" version="0:2-1" arch="i386">
  44.636 -		<provides name="libzip" relation="EQ" version="0:2-1"/>
  44.637 -	    </package>
  44.638 -	</set>
  44.639 -	<transaction>
  44.640 -	    <install name="zsh"/>
  44.641 -	</transaction>
  44.642 -	<result>
  44.643 -	    <set>
  44.644 -		<package name="zip" version="0:1-1" arch="i386"/>
  44.645 -		<package name="zip-libs" version="0:2-1" arch="i386"/>
  44.646 -		<package name="zsh" version="0:1-1" arch="i386"/>
  44.647 -	    </set>
  44.648 -	</result>
  44.649 -    </test>
  44.650 -
  44.651 -    <test name="testUpdateSinglePackageNewRequires">
  44.652 -	<set name="system">
  44.653 -	    <package name="zsh" version="1-1" arch="i386"/>
  44.654 -	</set>
  44.655 -	<set name="repo">
  44.656 -	    <package name="zsh" version="1-3" arch="i386">
  44.657 -		<requires name="zip"/>
  44.658 -	    </package>
  44.659 -	    <package name="zip" version="1-3" arch="x86_64"/>
  44.660 -	</set>
  44.661 -	<transaction>
  44.662 -	    <install name="zsh"/>
  44.663 -	</transaction>
  44.664 -	<result>
  44.665 -	    <set>
  44.666 -		<package name="zsh" version="1-3" arch="i386"/>
  44.667 -		<package name="zip" version="1-3" arch="x86_64"/>
  44.668 -	    </set>
  44.669 -	</result>
  44.670 -    </test>
  44.671 -
  44.672 -    <test name="testUpdateSinglePackageOldRequires">
  44.673 -	<set name="system">
  44.674 -	    <package name="zsh" version="1-1" arch="i386">
  44.675 -		<requires name="zip"/>
  44.676 -	    </package>
  44.677 -	    <package name="zip" version="1-3" arch="x86_64"/>
  44.678 -	</set>
  44.679 -	<set name="repo">
  44.680 -	    <package name="zsh" version="1-3" arch="i386">
  44.681 -		<requires name="zip"/>
  44.682 -	    </package>
  44.683 -	</set>
  44.684 -	<transaction>
  44.685 -	    <install name="zsh"/>
  44.686 -	</transaction>
  44.687 -	<result>
  44.688 -	    <set>
  44.689 -		<package name="zip" version="1-3" arch="x86_64"/>
  44.690 -		<package name="zsh" version="1-3" arch="i386"/>
  44.691 -	    </set>
  44.692 -	</result>
  44.693 -    </test>
  44.694 -
  44.695 -    <test name="testUpdateSinglePackageOldRequiresGone">
  44.696 -	<set name="system">
  44.697 -	    <package name="zsh" version="1-1" arch="i386">
  44.698 -		<requires name="zip"/>
  44.699 -	    </package>
  44.700 -	    <package name="zip" version="1-3" arch="x86_64"/>
  44.701 -	</set>
  44.702 -	<set name="repo">
  44.703 -	    <package name="zsh" version="1-3" arch="i386"/>
  44.704 -	</set>
  44.705 -	<transaction>
  44.706 -	    <install name="zsh"/>
  44.707 -	</transaction>
  44.708 -	<result>
  44.709 -	    <set>
  44.710 -		<package name="zip" version="1-3" arch="x86_64"/>
  44.711 -		<package name="zsh" version="1-3" arch="i386"/>
  44.712 -	    </set>
  44.713 -	</result>
  44.714 -    </test>
  44.715 -
  44.716 -    <test name="testUpdateSinglePackageObsoletesOldRequirement">
  44.717 -	<set name="system">
  44.718 -	    <package name="zsh" version="1-1" arch="i386">
  44.719 -		<requires name="zip"/>
  44.720 -	    </package>
  44.721 -	    <package name="zip" version="1-1" arch="i386"/>
  44.722 -	</set>
  44.723 -	<set name="repo">
  44.724 -	    <package name="zsh" version="1-3" arch="i386">
  44.725 -		<!-- depsolvetests.py actually adds the obsoletes
  44.726 -		     to the installed zsh rather than the new zsh,
  44.727 -		     but I'm assuming that's a bug -->
  44.728 -		<obsoletes name="zip"/>
  44.729 -	    </package>
  44.730 -	</set>
  44.731 -	<transaction>
  44.732 -	    <install name="zsh"/>
  44.733 -	</transaction>
  44.734 -	<result>
  44.735 -	    <set>
  44.736 -		<package name="zsh" version="1-3" arch="i386"/>
  44.737 -	    </set>
  44.738 -	</result>
  44.739 -    </test>
  44.740 -
  44.741 -    <test name="testUpdateForConflict">
  44.742 -	<set name="system">
  44.743 -	    <package name="zip" version="0:1-1" arch="i386"/>
  44.744 -	</set>
  44.745 -	<set name="repo">
  44.746 -	    <package name="zsh" version="0:1-1" arch="i386">
  44.747 -		<conflicts name="zip" relation="LE" version="0:1-1"/>
  44.748 -	    </package>
  44.749 -	    <package name="zip" version="0:2-1" arch="i386"/>
  44.750 -	</set>
  44.751 -	<transaction>
  44.752 -	    <install name="zsh"/>
  44.753 -	</transaction>
  44.754 -	<result>
  44.755 -	    <set>
  44.756 -		<package name="zip" version="0:2-1" arch="i386"/>
  44.757 -		<package name="zsh" version="0:1-1" arch="i386"/>
  44.758 -	    </set>
  44.759 -	</result>
  44.760 -    </test>
  44.761 -
  44.762 -    <test name="testUpdateForConflict2">
  44.763 -	<set name="system">
  44.764 -	    <package name="zip" version="0:1-1" arch="i386">
  44.765 -		<conflicts name="zsh" relation="LE" version="0:1-1"/>
  44.766 -	    </package>
  44.767 -	</set>
  44.768 -	<set name="repo">
  44.769 -	    <package name="zsh" version="0:1-1" arch="i386"/>
  44.770 -	    <package name="zip" version="0:2-1" arch="i386"/>
  44.771 -	</set>
  44.772 -	<transaction>
  44.773 -	    <install name="zsh"/>
  44.774 -	</transaction>
  44.775 -	<result>
  44.776 -	    <set>
  44.777 -		<package name="zsh" version="0:1-1" arch="i386"/>
  44.778 -		<package name="zip" version="0:2-1" arch="i386"/>
  44.779 -	    </set>
  44.780 -	</result>
  44.781 -    </test>
  44.782 -
  44.783 -    <test name="testUpdateForConflictProvide">
  44.784 -	<set name="system">
  44.785 -	    <package name="zip" version="0:1-1" arch="i386">
  44.786 -		<provides name="zippy" relation="EQ" version="0:1-1"/>
  44.787 -	    </package>
  44.788 -	</set>
  44.789 -	<set name="repo">
  44.790 -	    <package name="zsh" version="0:1-1" arch="i386">
  44.791 -		<conflicts name="zippy" relation="LE" version="0:1-1"/>
  44.792 -	    </package>
  44.793 -	    <package name="zip" version="0:2-1" arch="i386"/>
  44.794 -	</set>
  44.795 -	<transaction>
  44.796 -	    <install name="zsh"/>
  44.797 -	</transaction>
  44.798 -	<result>
  44.799 -	    <set>
  44.800 -		<package name="zip" version="0:2-1" arch="i386"/>
  44.801 -		<package name="zsh" version="0:1-1" arch="i386"/>
  44.802 -	    </set>
  44.803 -	</result>
  44.804 -    </test>
  44.805 -
  44.806 -    <test name="testUpdateForConflictProvide2">
  44.807 -	<set name="system">
  44.808 -	    <package name="zip" version="0:1-1" arch="i386">
  44.809 -		<conflicts name="zippy" relation="GT" version="0:1-1"/>
  44.810 -		<conflicts name="zippy" relation="LT" version="0:1-1"/>
  44.811 -	    </package>
  44.812 -	</set>
  44.813 -	<set name="repo">
  44.814 -	    <package name="zsh" version="0:1-1" arch="i386">
  44.815 -		<provides name="zippy" relation="EQ" version="0:2-1"/>
  44.816 -	    </package>
  44.817 -	    <package name="zip" version="0:2-1" arch="i386">
  44.818 -		<conflicts name="zippy" relation="GT" version="0:2-1"/>
  44.819 -		<conflicts name="zippy" relation="LT" version="0:2-1"/>
  44.820 -	    </package>
  44.821 -	</set>
  44.822 -	<transaction>
  44.823 -	    <install name="zsh"/>
  44.824 -	</transaction>
  44.825 -	<result>
  44.826 -	    <set>
  44.827 -		<package name="zip" version="0:2-1" arch="i386"/>
  44.828 -		<package name="zsh" version="0:1-1" arch="i386"/>
  44.829 -	    </set>
  44.830 -	</result>
  44.831 -    </test>
  44.832 -
  44.833 -    <test name="testEraseSinglePackage">
  44.834 -	<set name="system">
  44.835 -	    <package name="zsh" version="0:1-1" arch="i386"/>
  44.836 -	</set>
  44.837 -	<set name="repo"/>
  44.838 -	<transaction>
  44.839 -	    <remove name="zsh"/>
  44.840 -	</transaction>
  44.841 -	<result>
  44.842 -	    <set/>
  44.843 -	</result>
  44.844 -    </test>
  44.845 -
  44.846 -    <test name="testEraseSinglePackageRequiredByOneInstalled">
  44.847 -	<set name="system">
  44.848 -	    <package name="zippy" version="0:1-1" arch="i386">
  44.849 -		<requires name="zsh"/>
  44.850 -	    </package>
  44.851 -	    <package name="zsh" version="0:1-1" arch="i386"/>
  44.852 -	</set>
  44.853 -	<set name="repo"/>
  44.854 -	<transaction>
  44.855 -	    <remove name="zsh"/>
  44.856 -	</transaction>
  44.857 -	<result>
  44.858 -	    <set/>
  44.859 -	</result>
  44.860 -    </test>
  44.861 -</tests>
    45.1 --- a/types.c	Sun Jun 15 23:15:59 2008 -0400
    45.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.3 @@ -1,246 +0,0 @@
    45.4 -#include <stdlib.h>
    45.5 -#include <string.h>
    45.6 -
    45.7 -#include "types.h"
    45.8 -
    45.9 -void
   45.10 -array_init(struct array *array)
   45.11 -{
   45.12 -	memset(array, 0, sizeof *array);
   45.13 -}
   45.14 -
   45.15 -void
   45.16 -array_release(struct array *array)
   45.17 -{
   45.18 -	free(array->data);
   45.19 -}
   45.20 -
   45.21 -void *
   45.22 -array_add(struct array *array, int size)
   45.23 -{
   45.24 -	int alloc;
   45.25 -	void *data, *p;
   45.26 -
   45.27 -	if (array->alloc > 0)
   45.28 -		alloc = array->alloc;
   45.29 -	else
   45.30 -		alloc = 16;
   45.31 -
   45.32 -	while (alloc < array->size + size)
   45.33 -		alloc *= 2;
   45.34 -
   45.35 -	if (array->alloc < alloc) {
   45.36 -		data = realloc(array->data, alloc);
   45.37 -		if (data == NULL)
   45.38 -			return 0;
   45.39 -		array->data = data;
   45.40 -		array->alloc = alloc;
   45.41 -	}
   45.42 -
   45.43 -	p = array->data + array->size;
   45.44 -	array->size += size;
   45.45 -
   45.46 -	return p;
   45.47 -}
   45.48 -
   45.49 -/* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
   45.50 -#define RAZOR_ENTRY_LAST 0x80
   45.51 -#define RAZOR_IMMEDIATE  0x80
   45.52 -#define RAZOR_EMPTY_LIST 0xff
   45.53 -
   45.54 -void
   45.55 -list_set_empty(struct list_head *head)
   45.56 -{
   45.57 -	head->list_ptr = ~0;
   45.58 -	head->flags = RAZOR_EMPTY_LIST;
   45.59 -}
   45.60 -
   45.61 -void
   45.62 -list_set_ptr(struct list_head *head, uint32_t ptr)
   45.63 -{
   45.64 -	head->list_ptr = ptr;
   45.65 -	head->flags = 0;
   45.66 -}
   45.67 -
   45.68 -void
   45.69 -list_set_array(struct list_head *head, struct array *pool,
   45.70 -	       struct array *items, int force_indirect)
   45.71 -{
   45.72 -	struct list *p;
   45.73 -
   45.74 -	if (!force_indirect) {
   45.75 -		if (items->size == 0) {
   45.76 -			list_set_empty(head);
   45.77 -			return;
   45.78 -		} else if (items->size == sizeof (uint32_t)) {
   45.79 -			head->list_ptr = *(uint32_t *) items->data;
   45.80 -			head->flags = RAZOR_IMMEDIATE;
   45.81 -			return;
   45.82 -		}
   45.83 -	}
   45.84 -
   45.85 -	p = array_add(pool, items->size);
   45.86 -	memcpy(p, items->data, items->size);
   45.87 -	p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
   45.88 -	list_set_ptr(head, p - (struct list *) pool->data);
   45.89 -}
   45.90 -
   45.91 -struct list *
   45.92 -list_first(struct list_head *head, struct array *pool)
   45.93 -{
   45.94 -	if (head->flags == RAZOR_EMPTY_LIST)
   45.95 -		return NULL;
   45.96 -	else if (head->flags == RAZOR_IMMEDIATE)
   45.97 -		return (struct list *) head;
   45.98 -	else
   45.99 -		return (struct list *) pool->data + head->list_ptr;
  45.100 -}
  45.101 -
  45.102 -struct list *
  45.103 -list_next(struct list *list)
  45.104 -{
  45.105 -	if (list->flags)
  45.106 -		return NULL;
  45.107 -	return ++list;
  45.108 -}
  45.109 -
  45.110 -void
  45.111 -list_remap_pool(struct array *pool, uint32_t *map)
  45.112 -{
  45.113 -	struct list *p, *end;
  45.114 -
  45.115 -	end = pool->data + pool->size;
  45.116 -	for (p = pool->data; p < end; p++)
  45.117 -		p->data = map[p->data];
  45.118 -}
  45.119 -
  45.120 -void
  45.121 -list_remap_head(struct list_head *head, uint32_t *map)
  45.122 -{
  45.123 -	if (head->flags == RAZOR_IMMEDIATE)
  45.124 -		head->list_ptr = map[head->list_ptr];
  45.125 -}
  45.126 -
  45.127 -
  45.128 -void
  45.129 -hashtable_init(struct hashtable *table, struct array *pool)
  45.130 -{
  45.131 -	array_init(&table->buckets);
  45.132 -	table->pool = pool;
  45.133 -}
  45.134 -
  45.135 -void
  45.136 -hashtable_release(struct hashtable *table)
  45.137 -{
  45.138 -	array_release(&table->buckets);
  45.139 -}
  45.140 -
  45.141 -static unsigned int
  45.142 -hash_string(const char *key)
  45.143 -{
  45.144 -	const char *p;
  45.145 -	unsigned int hash = 0;
  45.146 -
  45.147 -	for (p = key; *p; p++)
  45.148 -		hash = (hash * 617) ^ *p;
  45.149 -
  45.150 -	return hash;
  45.151 -}
  45.152 -
  45.153 -uint32_t
  45.154 -hashtable_lookup(struct hashtable *table, const char *key)
  45.155 -{
  45.156 -	unsigned int mask, start, i;
  45.157 -	uint32_t *b;
  45.158 -	char *pool;
  45.159 -
  45.160 -	pool = table->pool->data;
  45.161 -	mask = table->buckets.alloc - 1;
  45.162 -	start = hash_string(key) * sizeof(uint32_t);
  45.163 -
  45.164 -	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  45.165 -		b = table->buckets.data + ((start + i) & mask);
  45.166 -
  45.167 -		if (*b == 0)
  45.168 -			return 0;
  45.169 -
  45.170 -		if (strcmp(key, &pool[*b]) == 0)
  45.171 -			return *b;
  45.172 -	}
  45.173 -
  45.174 -	return 0;
  45.175 -}
  45.176 -
  45.177 -static void
  45.178 -do_insert(struct hashtable *table, uint32_t value)
  45.179 -{
  45.180 -	unsigned int mask, start, i;
  45.181 -	uint32_t *b;
  45.182 -	const char *key;
  45.183 -
  45.184 -	key = (char *) table->pool->data + value;
  45.185 -	mask = table->buckets.alloc - 1;
  45.186 -	start = hash_string(key) * sizeof(uint32_t);
  45.187 -
  45.188 -	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  45.189 -		b = table->buckets.data + ((start + i) & mask);
  45.190 -		if (*b == 0) {
  45.191 -			*b = value;
  45.192 -			break;
  45.193 -		}
  45.194 -	}
  45.195 -}
  45.196 -
  45.197 -static uint32_t
  45.198 -add_to_string_pool(struct hashtable *table, const char *key)
  45.199 -{
  45.200 -	int len;
  45.201 -	char *p;
  45.202 -
  45.203 -	len = strlen(key) + 1;
  45.204 -	p = array_add(table->pool, len);
  45.205 -	memcpy(p, key, len);
  45.206 -
  45.207 -	return p - (char *) table->pool->data;
  45.208 -}
  45.209 -
  45.210 -uint32_t
  45.211 -hashtable_insert(struct hashtable *table, const char *key)
  45.212 -{
  45.213 -	uint32_t value, *buckets, *b, *end;
  45.214 -	int alloc;
  45.215 -
  45.216 -	alloc = table->buckets.alloc;
  45.217 -	array_add(&table->buckets, 4 * sizeof *buckets);
  45.218 -	if (alloc != table->buckets.alloc) {
  45.219 -		end = table->buckets.data + alloc;
  45.220 -		memset(end, 0, table->buckets.alloc - alloc);
  45.221 -		for (b = table->buckets.data; b < end; b++) {
  45.222 -			value = *b;
  45.223 -			if (value != 0) {
  45.224 -				*b = 0;
  45.225 -				do_insert(table, value);
  45.226 -			}
  45.227 -		}
  45.228 -	}
  45.229 -
  45.230 -	value = add_to_string_pool(table, key);
  45.231 -	do_insert (table, value);
  45.232 -
  45.233 -	return value;
  45.234 -}
  45.235 -
  45.236 -uint32_t
  45.237 -hashtable_tokenize(struct hashtable *table, const char *string)
  45.238 -{
  45.239 -	uint32_t token;
  45.240 -
  45.241 -	if (string == NULL)
  45.242 -		string = "";
  45.243 -
  45.244 -	token = hashtable_lookup(table, string);
  45.245 -	if (token != 0)
  45.246 -		return token;
  45.247 -
  45.248 -	return hashtable_insert(table, string);
  45.249 -}
    46.1 --- a/types.h	Sun Jun 15 23:15:59 2008 -0400
    46.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3 @@ -1,59 +0,0 @@
    46.4 -#ifndef _RAZOR_TYPES_H_
    46.5 -#define _RAZOR_TYPES_H_
    46.6 -
    46.7 -#include <stdint.h>
    46.8 -
    46.9 -struct array {
   46.10 -	void *data;
   46.11 -	int size, alloc;
   46.12 -};
   46.13 -
   46.14 -void array_init(struct array *array);
   46.15 -void array_release(struct array *array);
   46.16 -void *array_add(struct array *array, int size);
   46.17 -
   46.18 -
   46.19 -struct list_head {
   46.20 -	uint list_ptr : 24;
   46.21 -	uint flags    : 8;
   46.22 -};
   46.23 -
   46.24 -struct list {
   46.25 -	uint data  : 24;
   46.26 -	uint flags : 8;
   46.27 -};
   46.28 -
   46.29 -void list_set_empty(struct list_head *head);
   46.30 -void list_set_ptr(struct list_head *head, uint32_t ptr);
   46.31 -void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
   46.32 -
   46.33 -struct list *list_first(struct list_head *head, struct array *pool);
   46.34 -struct list *list_next(struct list *list);
   46.35 -
   46.36 -void list_remap_pool(struct array *pool, uint32_t *map);
   46.37 -void list_remap_head(struct list_head *list, uint32_t *map);
   46.38 -
   46.39 -
   46.40 -struct hashtable {
   46.41 -	struct array buckets;
   46.42 -	struct array *pool;
   46.43 -};
   46.44 -
   46.45 -void hashtable_init(struct hashtable *table, struct array *pool);
   46.46 -void hashtable_release(struct hashtable *table);
   46.47 -uint32_t hashtable_insert(struct hashtable *table, const char *key);
   46.48 -uint32_t hashtable_lookup(struct hashtable *table, const char *key);
   46.49 -uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
   46.50 -
   46.51 -
   46.52 -struct bitarray {
   46.53 -	uint32_t *bits;
   46.54 -};
   46.55 -
   46.56 -void bitarray_init(struct bitarray *bitarray, int size, int intial_value);
   46.57 -void bitarray_release(struct bitarray *bitarray);
   46.58 -void bitarray_set(struct bitarray *bitarray, int bit, int value);
   46.59 -int bitarray_get(struct bitarray *bitarray, int bit);
   46.60 -
   46.61 -
   46.62 -#endif /* _RAZOR_TYPES_H_ */
    47.1 --- a/util.c	Sun Jun 15 23:15:59 2008 -0400
    47.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3 @@ -1,167 +0,0 @@
    47.4 -#include <limits.h>
    47.5 -#include <string.h>
    47.6 -#include <sys/stat.h>
    47.7 -#include <stdlib.h>
    47.8 -#include <stdio.h>
    47.9 -#include <stdint.h>
   47.10 -#include <unistd.h>
   47.11 -
   47.12 -#include "razor-internal.h"
   47.13 -
   47.14 -int
   47.15 -razor_create_dir(const char *root, const char *path)
   47.16 -{
   47.17 -	char buffer[PATH_MAX], *p;
   47.18 -	const char *slash, *next;
   47.19 -	struct stat buf;
   47.20 -
   47.21 -	/* Create all sub-directories in dir. We know root exists and
   47.22 -	 * is a dir, root does not end in a '/', and path has a
   47.23 -	 * leading '/'. */
   47.24 -
   47.25 -	strcpy(buffer, root);
   47.26 -	p = buffer + strlen(buffer);
   47.27 -	slash = path;
   47.28 -	for (slash = path; *slash != '\0'; slash = next) {
   47.29 -		next = strchr(slash + 1, '/');
   47.30 -		if (next == NULL)
   47.31 -			break;
   47.32 -
   47.33 -		memcpy(p, slash, next - slash);
   47.34 -		p += next - slash;
   47.35 -		*p = '\0';
   47.36 -
   47.37 -		if (stat(buffer, &buf) == 0) {
   47.38 -			if (!S_ISDIR(buf.st_mode)) {
   47.39 -				fprintf(stderr,
   47.40 -					"%s exists but is not a directory\n",
   47.41 -					buffer);
   47.42 -				return -1;
   47.43 -			}
   47.44 -		} else if (mkdir(buffer, 0777) < 0) {
   47.45 -			fprintf(stderr, "failed to make directory %s: %m\n",
   47.46 -				buffer);
   47.47 -			return -1;
   47.48 -		}
   47.49 -
   47.50 -		/* FIXME: What to do about permissions for dirs we
   47.51 -		 * have to create but are not in the cpio archive? */
   47.52 -	}
   47.53 -
   47.54 -	return 0;
   47.55 -}
   47.56 -
   47.57 -int
   47.58 -razor_write(int fd, const void *data, size_t size)
   47.59 -{
   47.60 -	size_t rest;
   47.61 -	ssize_t written;
   47.62 -	const unsigned char *p;
   47.63 -
   47.64 -	rest = size;
   47.65 -	p = data;
   47.66 -	while (rest > 0) {
   47.67 -		written = write(fd, p, rest);
   47.68 -		if (written < 0) {
   47.69 -			fprintf(stderr, "write error: %m\n");
   47.70 -			return -1;
   47.71 -		}
   47.72 -		rest -= written;
   47.73 -		p += written;
   47.74 -	}
   47.75 -
   47.76 -	return 0;
   47.77 -}
   47.78 -
   47.79 -struct qsort_context {
   47.80 -	size_t size;
   47.81 -	razor_compare_with_data_func_t compare;
   47.82 -	void *data;
   47.83 -};
   47.84 -
   47.85 -static void
   47.86 -qsort_swap(void *p1, void *p2, size_t size)
   47.87 -{
   47.88 -	char buffer[size];
   47.89 -
   47.90 -	memcpy(buffer, p1, size);
   47.91 -	memcpy(p1, p2, size);
   47.92 -	memcpy(p2, buffer, size);
   47.93 -}
   47.94 -
   47.95 -static void
   47.96 -__qsort_with_data(void *base, size_t nelem, uint32_t *map,
   47.97 -		  struct qsort_context *ctx)
   47.98 -{
   47.99 -	void *p, *start, *end, *pivot;
  47.100 -	uint32_t *mp, *mstart, *mend, tmp;
  47.101 -	int left, right, result;
  47.102 -	size_t size = ctx->size;
  47.103 -
  47.104 -	p = base;
  47.105 -	start = base;
  47.106 -	end = base + nelem * size;
  47.107 -	mp = map;
  47.108 -	mstart = map;
  47.109 -	mend = map + nelem;
  47.110 -	pivot = base + (random() % nelem) * size;
  47.111 -
  47.112 -	while (p < end) {
  47.113 -		result = ctx->compare(p, pivot, ctx->data);
  47.114 -		if (result < 0) {
  47.115 -			qsort_swap(p, start, size);
  47.116 -			tmp = *mp;
  47.117 -			*mp = *mstart;
  47.118 -			*mstart = tmp;
  47.119 -			if (start == pivot)
  47.120 -				pivot = p;
  47.121 -			start += size;
  47.122 -			mstart++;
  47.123 -			p += size;
  47.124 -			mp++;
  47.125 -		} else if (result == 0) {
  47.126 -			p += size;
  47.127 -			mp++;
  47.128 -		} else {
  47.129 - 			end -= size;
  47.130 -			mend--;
  47.131 -			qsort_swap(p, end, size);
  47.132 -			tmp = *mp;
  47.133 -			*mp = *mend;
  47.134 -			*mend = tmp;
  47.135 -			if (end == pivot)
  47.136 -				pivot = p;
  47.137 -		}
  47.138 -	}
  47.139 -
  47.140 -	left = (start - base) / size;
  47.141 -	right = (base + nelem * size - end) / size;
  47.142 -	if (left > 1)
  47.143 -		__qsort_with_data(base, left, map, ctx);
  47.144 -	if (right > 1)
  47.145 -		__qsort_with_data(end, right, mend, ctx);
  47.146 -}
  47.147 -
  47.148 -uint32_t *
  47.149 -razor_qsort_with_data(void *base, size_t nelem, size_t size,
  47.150 -		      razor_compare_with_data_func_t compare, void *data)
  47.151 -{
  47.152 -	struct qsort_context ctx;
  47.153 -	uint32_t *map;
  47.154 -	int i;
  47.155 -
  47.156 -	if (nelem == 0)
  47.157 -		return NULL;
  47.158 -
  47.159 -	ctx.size = size;
  47.160 -	ctx.compare = compare;
  47.161 -	ctx.data = data;
  47.162 -
  47.163 -	map = malloc(nelem * sizeof (uint32_t));
  47.164 -	for (i = 0; i < nelem; i++)
  47.165 -		map[i] = i;
  47.166 -
  47.167 -	__qsort_with_data(base, nelem, map, &ctx);
  47.168 -
  47.169 -	return map;
  47.170 -}
    48.1 --- a/yum.c	Sun Jun 15 23:15:59 2008 -0400
    48.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3 @@ -1,337 +0,0 @@
    48.4 -/*
    48.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    48.6 - * Copyright (C) 2008  Red Hat, Inc
    48.7 - *
    48.8 - * This program is free software; you can redistribute it and/or modify
    48.9 - * it under the terms of the GNU General Public License as published by
   48.10 - * the Free Software Foundation; either version 2 of the License, or
   48.11 - * (at your option) any later version.
   48.12 - *
   48.13 - * This program is distributed in the hope that it will be useful,
   48.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   48.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   48.16 - * GNU General Public License for more details.
   48.17 - *
   48.18 - * You should have received a copy of the GNU General Public License along
   48.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   48.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   48.21 - */
   48.22 -
   48.23 -#define _GNU_SOURCE
   48.24 -
   48.25 -#include <string.h>
   48.26 -#include <stdio.h>
   48.27 -#include <sys/stat.h>
   48.28 -#include <sys/mman.h>
   48.29 -#include <unistd.h>
   48.30 -#include <fcntl.h>
   48.31 -#include <errno.h>
   48.32 -
   48.33 -#include <expat.h>
   48.34 -#include <zlib.h>
   48.35 -#include "razor.h"
   48.36 -
   48.37 -/* Import a yum filelist as a razor package set. */
   48.38 -
   48.39 -enum {
   48.40 -	YUM_STATE_BEGIN,
   48.41 -	YUM_STATE_PACKAGE_NAME,
   48.42 -	YUM_STATE_PACKAGE_ARCH,
   48.43 -	YUM_STATE_CHECKSUM,
   48.44 -	YUM_STATE_REQUIRES,
   48.45 -	YUM_STATE_PROVIDES,
   48.46 -	YUM_STATE_OBSOLETES,
   48.47 -	YUM_STATE_CONFLICTS,
   48.48 -	YUM_STATE_FILE
   48.49 -};
   48.50 -
   48.51 -struct yum_context {
   48.52 -	XML_Parser primary_parser;
   48.53 -	XML_Parser filelists_parser;
   48.54 -	XML_Parser current_parser;
   48.55 -
   48.56 -	struct razor_importer *importer;
   48.57 -	struct import_property_context *current_property_context;
   48.58 -	char name[256], arch[64], buffer[512], *p;
   48.59 -	char pkgid[128];
   48.60 -	int state;
   48.61 -};
   48.62 -
   48.63 -static enum razor_version_relation
   48.64 -yum_to_razor_flags (const char *flags)
   48.65 -{
   48.66 -	/* FIXME? */
   48.67 -	if (!flags)
   48.68 -		return RAZOR_VERSION_EQUAL;
   48.69 -
   48.70 -	if (flags[0] == 'L') {
   48.71 -		if (flags[1] == 'T')
   48.72 -			return RAZOR_VERSION_LESS;
   48.73 -		else
   48.74 -			return RAZOR_VERSION_LESS_OR_EQUAL;
   48.75 -	} else if (flags[0] == 'G') {
   48.76 -		if (flags[1] == 'T')
   48.77 -			return RAZOR_VERSION_GREATER;
   48.78 -		else
   48.79 -			return RAZOR_VERSION_GREATER_OR_EQUAL;
   48.80 -	} else
   48.81 -		return RAZOR_VERSION_EQUAL;
   48.82 -}
   48.83 -
   48.84 -static void
   48.85 -yum_primary_start_element(void *data, const char *name, const char **atts)
   48.86 -{
   48.87 -	struct yum_context *ctx = data;
   48.88 -	const char *n, *epoch, *version, *release, *flags;
   48.89 -	char buffer[128];
   48.90 -	int i;
   48.91 -
   48.92 -	if (strcmp(name, "name") == 0) {
   48.93 -		ctx->state = YUM_STATE_PACKAGE_NAME;
   48.94 -		ctx->p = ctx->name;
   48.95 -	} else if (strcmp(name, "arch") == 0) {
   48.96 -		ctx->state = YUM_STATE_PACKAGE_ARCH;
   48.97 -		ctx->p = ctx->arch;
   48.98 -	} else if (strcmp(name, "version") == 0) {
   48.99 -		epoch = NULL;
  48.100 -		version = NULL;
  48.101 -		release = NULL;
  48.102 -		for (i = 0; atts[i]; i += 2) {
  48.103 -			if (strcmp(atts[i], "epoch") == 0)
  48.104 -				epoch = atts[i + 1];
  48.105 -			else if (strcmp(atts[i], "ver") == 0)
  48.106 -				version = atts[i + 1];
  48.107 -			else if (strcmp(atts[i], "rel") == 0)
  48.108 -				release = atts[i + 1];
  48.109 -		}
  48.110 -		if (version == NULL || release == NULL) {
  48.111 -			fprintf(stderr, "invalid version tag, "
  48.112 -				"missing version or  release attribute\n");
  48.113 -			return;
  48.114 -		}
  48.115 -
  48.116 -		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  48.117 -		razor_importer_begin_package(ctx->importer,
  48.118 -					     ctx->name, buffer, ctx->arch);
  48.119 -	} else if (strcmp(name, "checksum") == 0) {
  48.120 -		ctx->p = ctx->pkgid;
  48.121 -		ctx->state = YUM_STATE_CHECKSUM;
  48.122 -	} else if (strcmp(name, "rpm:requires") == 0) {
  48.123 -		ctx->state = YUM_STATE_REQUIRES;
  48.124 -	} else if (strcmp(name, "rpm:provides") == 0) {
  48.125 -		ctx->state = YUM_STATE_PROVIDES;
  48.126 -	} else if (strcmp(name, "rpm:obsoletes") == 0) {
  48.127 -		ctx->state = YUM_STATE_OBSOLETES;
  48.128 -	} else if (strcmp(name, "rpm:conflicts") == 0) {
  48.129 -		ctx->state = YUM_STATE_CONFLICTS;
  48.130 -	} else if (strcmp(name, "rpm:entry") == 0 &&
  48.131 -		   ctx->state != YUM_STATE_BEGIN) {
  48.132 -		n = NULL;
  48.133 -		epoch = NULL;
  48.134 -		version = NULL;
  48.135 -		release = NULL;
  48.136 -		flags = NULL;
  48.137 -		for (i = 0; atts[i]; i += 2) {
  48.138 -			if (strcmp(atts[i], "name") == 0)
  48.139 -				n = atts[i + 1];
  48.140 -			else if (strcmp(atts[i], "epoch") == 0)
  48.141 -				epoch = atts[i + 1];
  48.142 -			else if (strcmp(atts[i], "ver") == 0)
  48.143 -				version = atts[i + 1];
  48.144 -			else if (strcmp(atts[i], "rel") == 0)
  48.145 -				release = atts[i + 1];
  48.146 -			else if (strcmp(atts[i], "flags") == 0)
  48.147 -				flags = atts[i + 1];
  48.148 -		}
  48.149 -
  48.150 -		if (n == NULL) {
  48.151 -			fprintf(stderr, "invalid rpm:entry, "
  48.152 -				"missing name or version attributes\n");
  48.153 -			return;
  48.154 -		}
  48.155 -
  48.156 -		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  48.157 -		switch (ctx->state) {
  48.158 -		case YUM_STATE_REQUIRES:
  48.159 -			razor_importer_add_property(ctx->importer, n,
  48.160 -						    yum_to_razor_flags (flags),
  48.161 -						    buffer,
  48.162 -						    RAZOR_PROPERTY_REQUIRES);
  48.163 -			break;
  48.164 -		case YUM_STATE_PROVIDES:
  48.165 -			razor_importer_add_property(ctx->importer, n,
  48.166 -						    yum_to_razor_flags (flags),
  48.167 -						    buffer,
  48.168 -						    RAZOR_PROPERTY_PROVIDES);
  48.169 -			break;
  48.170 -		case YUM_STATE_OBSOLETES:
  48.171 -			razor_importer_add_property(ctx->importer, n,
  48.172 -						    yum_to_razor_flags (flags),
  48.173 -						    buffer,
  48.174 -						    RAZOR_PROPERTY_OBSOLETES);
  48.175 -			break;
  48.176 -		case YUM_STATE_CONFLICTS:
  48.177 -			razor_importer_add_property(ctx->importer, n,
  48.178 -						    yum_to_razor_flags (flags),
  48.179 -						    buffer,
  48.180 -						    RAZOR_PROPERTY_CONFLICTS);
  48.181 -			break;
  48.182 -		}
  48.183 -	}
  48.184 -}
  48.185 -
  48.186 -static void
  48.187 -yum_primary_end_element (void *data, const char *name)
  48.188 -{
  48.189 -	struct yum_context *ctx = data;
  48.190 -
  48.191 -	switch (ctx->state) {
  48.192 -	case YUM_STATE_PACKAGE_NAME:
  48.193 -	case YUM_STATE_PACKAGE_ARCH:
  48.194 -	case YUM_STATE_CHECKSUM:
  48.195 -	case YUM_STATE_FILE:
  48.196 -		ctx->state = YUM_STATE_BEGIN;
  48.197 -		break;
  48.198 -	}
  48.199 -
  48.200 -	if (strcmp(name, "package") == 0) {
  48.201 -		XML_StopParser(ctx->current_parser, XML_TRUE);
  48.202 -		ctx->current_parser = ctx->filelists_parser;
  48.203 -	}
  48.204 -}
  48.205 -
  48.206 -static void
  48.207 -yum_character_data (void *data, const XML_Char *s, int len)
  48.208 -{
  48.209 -	struct yum_context *ctx = data;
  48.210 -
  48.211 -	switch (ctx->state) {
  48.212 -	case YUM_STATE_PACKAGE_NAME:
  48.213 -	case YUM_STATE_PACKAGE_ARCH:
  48.214 -	case YUM_STATE_CHECKSUM:
  48.215 -	case YUM_STATE_FILE:
  48.216 -		memcpy(ctx->p, s, len);
  48.217 -		ctx->p += len;
  48.218 -		*ctx->p = '\0';
  48.219 -		break;
  48.220 -	}
  48.221 -}
  48.222 -
  48.223 -static void
  48.224 -yum_filelists_start_element(void *data, const char *name, const char **atts)
  48.225 -{
  48.226 -	struct yum_context *ctx = data;
  48.227 -	const char *pkg, *pkgid;
  48.228 -	int i;
  48.229 -
  48.230 -	if (strcmp(name, "package") == 0) {
  48.231 -		pkg = NULL;
  48.232 -		pkgid = NULL;
  48.233 -		for (i = 0; atts[i]; i += 2) {
  48.234 -			if (strcmp(atts[i], "name") == 0)
  48.235 -				pkg = atts[i + 1];
  48.236 -			else if (strcmp(atts[i], "pkgid") == 0)
  48.237 -				pkgid = atts[i + 1];
  48.238 -		}
  48.239 -		if (strcmp(pkgid, ctx->pkgid) != 0)
  48.240 -			fprintf(stderr, "primary.xml and filelists.xml "
  48.241 -				"mismatch for %s: %s vs %s",
  48.242 -				pkg, pkgid, ctx->pkgid);
  48.243 -	} else if (strcmp(name, "file") == 0) {
  48.244 -		ctx->state = YUM_STATE_FILE;
  48.245 -		ctx->p = ctx->buffer;
  48.246 -	}
  48.247 -}
  48.248 -
  48.249 -
  48.250 -static void
  48.251 -yum_filelists_end_element (void *data, const char *name)
  48.252 -{
  48.253 -	struct yum_context *ctx = data;
  48.254 -
  48.255 -	ctx->state = YUM_STATE_BEGIN;
  48.256 -	if (strcmp(name, "package") == 0) {
  48.257 -		XML_StopParser(ctx->current_parser, XML_TRUE);
  48.258 -		ctx->current_parser = ctx->primary_parser;
  48.259 -		razor_importer_finish_package(ctx->importer);
  48.260 -	} else if (strcmp(name, "file") == 0)
  48.261 -		razor_importer_add_file(ctx->importer, ctx->buffer);
  48.262 -
  48.263 -}
  48.264 -
  48.265 -#define XML_BUFFER_SIZE 4096
  48.266 -
  48.267 -struct razor_set *
  48.268 -razor_set_create_from_yum(void)
  48.269 -{
  48.270 -	struct yum_context ctx;
  48.271 -	void *buf;
  48.272 -	int len, ret;
  48.273 -	gzFile primary, filelists;
  48.274 -	XML_ParsingStatus status;
  48.275 -
  48.276 -	ctx.importer = razor_importer_new();	
  48.277 -	ctx.state = YUM_STATE_BEGIN;
  48.278 -
  48.279 -	ctx.primary_parser = XML_ParserCreate(NULL);
  48.280 -	XML_SetUserData(ctx.primary_parser, &ctx);
  48.281 -	XML_SetElementHandler(ctx.primary_parser,
  48.282 -			      yum_primary_start_element,
  48.283 -			      yum_primary_end_element);
  48.284 -	XML_SetCharacterDataHandler(ctx.primary_parser,
  48.285 -				    yum_character_data);
  48.286 -
  48.287 -	ctx.filelists_parser = XML_ParserCreate(NULL);
  48.288 -	XML_SetUserData(ctx.filelists_parser, &ctx);
  48.289 -	XML_SetElementHandler(ctx.filelists_parser,
  48.290 -			      yum_filelists_start_element,
  48.291 -			      yum_filelists_end_element);
  48.292 -	XML_SetCharacterDataHandler(ctx.filelists_parser,
  48.293 -				    yum_character_data);
  48.294 -
  48.295 -	primary = gzopen("primary.xml.gz", "rb");
  48.296 -	if (primary == NULL)
  48.297 -		return NULL;
  48.298 -	filelists = gzopen("filelists.xml.gz", "rb");
  48.299 -	if (filelists == NULL)
  48.300 -		return NULL;
  48.301 -
  48.302 -	ctx.current_parser = ctx.primary_parser;
  48.303 -
  48.304 -	do {
  48.305 -		XML_GetParsingStatus(ctx.current_parser, &status);
  48.306 -		switch (status.parsing) {
  48.307 -		case XML_SUSPENDED:
  48.308 -			ret = XML_ResumeParser(ctx.current_parser);
  48.309 -			break;
  48.310 -		case XML_PARSING:
  48.311 -		case XML_INITIALIZED:
  48.312 -			buf = XML_GetBuffer(ctx.current_parser,
  48.313 -					    XML_BUFFER_SIZE);
  48.314 -			if (ctx.current_parser == ctx.primary_parser)
  48.315 -				len = gzread(primary, buf, XML_BUFFER_SIZE);
  48.316 -			else
  48.317 -				len = gzread(filelists, buf, XML_BUFFER_SIZE);
  48.318 -			if (len < 0) {
  48.319 -				fprintf(stderr,
  48.320 -					"couldn't read input: %s\n",
  48.321 -					strerror(errno));
  48.322 -				return NULL;
  48.323 -			}
  48.324 -
  48.325 -			XML_ParseBuffer(ctx.current_parser, len, len == 0);
  48.326 -			break;
  48.327 -		case XML_FINISHED:
  48.328 -			break;
  48.329 -		}
  48.330 -	} while (status.parsing != XML_FINISHED);
  48.331 -
  48.332 -
  48.333 -	XML_ParserFree(ctx.primary_parser);
  48.334 -	XML_ParserFree(ctx.filelists_parser);
  48.335 -
  48.336 -	gzclose(primary);
  48.337 -	gzclose(filelists);
  48.338 -
  48.339 -	return razor_importer_finish(ctx.importer);
  48.340 -}